Skip to content

Commit

Permalink
Make interval waiting to bundle variable
Browse files Browse the repository at this point in the history
  • Loading branch information
plusminushalf committed Jan 16, 2025
1 parent 51fdd72 commit d059014
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 27 deletions.
2 changes: 1 addition & 1 deletion src/executor/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ export class Executor {
): Promise<ReplaceTransactionResult> {
const newRequest = { ...transactionInfo.transactionRequest }

let gasPriceParameters
let gasPriceParameters: GasPriceParameters
try {
gasPriceParameters =
await this.gasPriceManager.tryGetNetworkGasPrice()
Expand Down
83 changes: 58 additions & 25 deletions src/executor/executorManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ function getTransactionsFromUserOperationEntries(
)
}

const MIN_INTERVAL = 100 // 0.1 seconds (100ms)
const MAX_INTERVAL = 1000 // Capped at 1 second (1000ms)
const SCALE_FACTOR = 5 // Interval increases by 5ms per task per minute
const RPM_WINDOW = 60000 // 1 minute window in ms

export class ExecutorManager {
private config: AltoConfig
private executor: Executor
Expand All @@ -61,6 +66,7 @@ export class ExecutorManager {
private timer?: NodeJS.Timer
private gasPriceManager: GasPriceManager
private eventManager: EventManager
private opsCount: number[] = []

constructor({
config,
Expand Down Expand Up @@ -97,23 +103,68 @@ export class ExecutorManager {
this.eventManager = eventManager

if (this.config.bundleMode === "auto") {
this.timer = setInterval(async () => {
await this.bundle()
}, this.config.maxBundleWait) as NodeJS.Timer
this.autoScalingBundling()
}
}

setBundlingMode(bundleMode: BundlingMode): void {
if (bundleMode === "auto" && !this.timer) {
this.timer = setInterval(async () => {
await this.bundle()
}, this.config.maxBundleWait) as NodeJS.Timer
this.autoScalingBundling()
} else if (bundleMode === "manual" && this.timer) {
clearInterval(this.timer)
this.timer = undefined
}
}

async autoScalingBundling() {
const now = Date.now()
this.opsCount = this.opsCount.filter(
(timestamp) => now - timestamp < RPM_WINDOW
)

const opsToBundle = await this.getOpsToBundle()

if (opsToBundle.length === 0) {
return
}

const opsCount: number = opsToBundle.length
const timestamp: number = Date.now()
this.opsCount.push(...Array(opsCount).fill(timestamp)) // Add timestamps for each task

await this.bundle(opsToBundle)

const rpm: number = this.opsCount.length
// Calculate next interval with linear scaling
const nextInterval: number = Math.min(
MIN_INTERVAL + rpm * SCALE_FACTOR, // Linear scaling
MAX_INTERVAL // Cap at 1000ms
)
setTimeout(this.autoScalingBundling, nextInterval)
}

async getOpsToBundle() {
const opsToBundle: UserOperationInfo[][] = []

while (true) {
const ops = await this.mempool.process(
this.config.maxGasPerBundle,
1
)
if (ops?.length > 0) {
opsToBundle.push(ops)
} else {
break
}
}

if (opsToBundle.length === 0) {
return []
}

return opsToBundle
}

async bundleNow(): Promise<Hash[]> {
const ops = await this.mempool.process(this.config.maxGasPerBundle, 1)
if (ops.length === 0) {
Expand Down Expand Up @@ -285,25 +336,7 @@ export class ExecutorManager {
return txHash
}

async bundle() {
const opsToBundle: UserOperationInfo[][] = []

while (true) {
const ops = await this.mempool.process(
this.config.maxGasPerBundle,
1
)
if (ops?.length > 0) {
opsToBundle.push(ops)
} else {
break
}
}

if (opsToBundle.length === 0) {
return
}

async bundle(opsToBundle: UserOperationInfo[][] = []) {
await Promise.all(
opsToBundle.map(async (ops) => {
const opEntryPointMap = new Map<
Expand Down
5 changes: 4 additions & 1 deletion src/rpc/rpcHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ import {
import { base, baseSepolia, optimism } from "viem/chains"
import type { NonceQueuer } from "./nonceQueuer"
import type { AltoConfig } from "../createConfig"
import { SignedAuthorization, SignedAuthorizationList } from "viem/experimental"
import type {
SignedAuthorization,
SignedAuthorizationList
} from "viem/experimental"

export interface IRpcEndpoint {
handleMethod(
Expand Down

0 comments on commit d059014

Please sign in to comment.