Skip to content

Commit

Permalink
Merge branch 'main' into feat/add-resubmit-timeout-flag
Browse files Browse the repository at this point in the history
  • Loading branch information
mouseless0x authored Jan 24, 2025
2 parents 5160b47 + b95ae9c commit b00b551
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 7 deletions.
1 change: 1 addition & 0 deletions src/cli/config/bundler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export const bundlerArgsSchema = z.object({
})

export const executorArgsSchema = z.object({
"enable-fastlane": z.boolean(),
"resubmit-stuck-timeout": z.number().int().min(0).default(15_000),
"refilling-wallets": z.boolean().default(true),
"aa95-gas-multiplier": z.string().transform((val) => BigInt(val)),
Expand Down
13 changes: 12 additions & 1 deletion src/cli/config/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,12 @@ export const bundlerOptions: CliCommandOptions<IBundlerArgsInput> = {
"Should the bundler enable the pimlico_experimental_sendUserOperation7702 and pimlico_experimental_estimateUserOperationGas7702 endpoint",
type: "boolean",
default: false
}
},
"executor-gas-multiplier": {
description: "Amount to scale the gas estimations used for bundling",
type: "string",
default: "100"
},
}

export const gasEstimationOptions: CliCommandOptions<IGasEstimationArgsInput> =
Expand Down Expand Up @@ -226,6 +231,12 @@ export const gasEstimationOptions: CliCommandOptions<IGasEstimationArgsInput> =
}

export const executorOptions: CliCommandOptions<IExecutorArgsInput> = {
"enable-fastlane": {
description:
"Enable bundling v0.6 userOperations using the pfl_sendRawTransactionConditional endpoint",
type: "boolean",
default: false
},
"resubmit-stuck-timeout": {
description:
"Amount of time before retrying a failed userOperation (in ms)",
Expand Down
30 changes: 24 additions & 6 deletions src/executor/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import {
import type { SendTransactionErrorType } from "viem"
import type { AltoConfig } from "../createConfig"
import type { SendTransactionOptions } from "./types"
import { sendPflConditional } from "./fastlane"

export interface GasEstimateResult {
preverificationGas: bigint
Expand All @@ -58,6 +59,7 @@ export interface GasEstimateResult {
export type HandleOpsTxParam = {
ops: PackedUserOperation[]
isUserOpVersion06: boolean
isReplacementTx: boolean
entryPoint: Address
}

Expand Down Expand Up @@ -298,6 +300,7 @@ export class Executor {

txParam = {
isUserOpVersion06,
isReplacementTx: true,
ops: userOps,
entryPoint: transactionInfo.entryPoint
}
Expand Down Expand Up @@ -500,13 +503,31 @@ export class Executor {
// Try sending the transaction and updating relevant fields if there is an error.
while (attempts < maxAttempts) {
try {
if (
this.config.enableFastlane &&
isUserOpVersion06 &&
!txParam.isReplacementTx &&
attempts === 0
) {
const serializedTransaction =
await this.config.walletClient.signTransaction(request)

transactionHash = await sendPflConditional({
serializedTransaction,
publicClient: this.config.publicClient,
walletClient: this.config.walletClient,
logger: this.logger
})

break
}

transactionHash =
await this.config.walletClient.sendTransaction(request)

break
} catch (e: unknown) {
isTransactionUnderPriced = false
let isErrorHandled = false

if (e instanceof BaseError) {
if (isTransactionUnderpricedError(e)) {
Expand All @@ -520,7 +541,6 @@ export class Executor {
request.maxPriorityFeePerGas,
150n
)
isErrorHandled = true
isTransactionUnderPriced = true
}
}
Expand All @@ -540,13 +560,11 @@ export class Executor {
address: request.from,
blockTag: "pending"
})
isErrorHandled = true
}

if (cause instanceof IntrinsicGasTooLowError) {
this.logger.warn("Intrinsic gas too low, retrying")
request.gas = scaleBigIntByPercent(request.gas, 150n)
isErrorHandled = true
}

// This is thrown by OP-Stack chains that use proxyd.
Expand All @@ -556,11 +574,10 @@ export class Executor {
"no backends avaiable error, retrying after 500ms"
)
await new Promise((resolve) => setTimeout(resolve, 500))
isErrorHandled = true
}
}

if (attempts === maxAttempts || !isErrorHandled) {
if (attempts === maxAttempts) {
throw error
}

Expand Down Expand Up @@ -832,6 +849,7 @@ export class Executor {
transactionHash = await this.sendHandleOpsTransaction({
txParam: {
ops: userOps,
isReplacementTx: false,
isUserOpVersion06,
entryPoint
},
Expand Down
68 changes: 68 additions & 0 deletions src/executor/fastlane.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { Logger } from "@alto/utils"
import {
Hex,
createClient,
http,
SendRawTransactionReturnType,
Hash,
WalletClient,
PublicClient,
toHex,
BaseError
} from "viem"

const pflClient = createClient({
transport: http("https://polygon-rpc.fastlane.xyz")
})

export async function sendPflConditional({
serializedTransaction,
publicClient,
walletClient,
logger
}: {
serializedTransaction: Hash
publicClient: PublicClient
walletClient: WalletClient
logger: Logger
}): Promise<SendRawTransactionReturnType> {
try {
const blockNumberMin = await publicClient.getBlockNumber()
const blockNumberMax = blockNumberMin + 30n

const timestampMin = Date.now() / 1000
const timestampMax = timestampMin + 60

const opts = {
//knownAccounts: {}
blockNumberMin: toHex(blockNumberMin),
blockNumberMax: toHex(blockNumberMax),
timestampMin: Math.floor(timestampMin),
timestampMax: Math.floor(timestampMax)
}

const txHash = (await pflClient.request({
// @ts-ignore
method: "pfl_sendRawTransactionConditional",
// @ts-ignore
params: [serializedTransaction, opts]
})) as Hex

if (!txHash) {
const error = new BaseError(
"FastLane API returned empty transaction hash"
)
error.details =
"PFL conditional transaction failed: No txHash in response"
throw error
}

return txHash
} catch (e: unknown) {
logger.error(
"Error sending through pfl_sendRawTransactionConditional ",
(e as any)?.details
)
return await walletClient.sendRawTransaction({ serializedTransaction })
}
}

0 comments on commit b00b551

Please sign in to comment.