UNPKG

permissionless

Version:

A utility library for working with ERC-4337

298 lines (282 loc) • 10.2 kB
import { type Address, type Hex, encodeFunctionData } from "viem" import { type EntryPointVersion, type UserOperation, entryPoint06Abi, toPackedUserOperation } from "viem/account-abstraction" function getPimlicoEstimationCallData06({ userOperation, entrypoint }: { userOperation: UserOperation<"0.6"> entrypoint: { address: Address version: "0.6" } }): { to: Address; data: Hex } { return { to: entrypoint.address, data: encodeFunctionData({ abi: entryPoint06Abi, functionName: "simulateHandleOp", args: [ { callData: userOperation.callData, callGasLimit: userOperation.callGasLimit, initCode: userOperation.initCode ?? "0x", maxFeePerGas: userOperation.maxFeePerGas, maxPriorityFeePerGas: userOperation.maxPriorityFeePerGas, nonce: userOperation.nonce, paymasterAndData: userOperation.paymasterAndData ?? "0x", preVerificationGas: userOperation.preVerificationGas, sender: userOperation.sender, signature: userOperation.signature, verificationGasLimit: userOperation.verificationGasLimit }, "0x", "0x" ] }) } } function encodeSimulateHandleOpLast({ userOperation }: { userOperation: UserOperation<"0.7" | "0.8"> }): Hex { const userOperations = [userOperation] const packedUserOperations = userOperations.map((uop) => ({ packedUserOperation: toPackedUserOperation(uop) })) const simulateHandleOpCallData = encodeFunctionData({ abi: [ { type: "function", name: "simulateHandleOpLast", inputs: [ { name: "ops", type: "tuple[]", internalType: "struct PackedUserOperation[]", components: [ { name: "sender", type: "address", internalType: "address" }, { name: "nonce", type: "uint256", internalType: "uint256" }, { name: "initCode", type: "bytes", internalType: "bytes" }, { name: "callData", type: "bytes", internalType: "bytes" }, { name: "accountGasLimits", type: "bytes32", internalType: "bytes32" }, { name: "preVerificationGas", type: "uint256", internalType: "uint256" }, { name: "gasFees", type: "bytes32", internalType: "bytes32" }, { name: "paymasterAndData", type: "bytes", internalType: "bytes" }, { name: "signature", type: "bytes", internalType: "bytes" } ] } ], outputs: [ { name: "", type: "tuple", internalType: "struct IEntryPointSimulations.ExecutionResult", components: [ { name: "preOpGas", type: "uint256", internalType: "uint256" }, { name: "paid", type: "uint256", internalType: "uint256" }, { name: "accountValidationData", type: "uint256", internalType: "uint256" }, { name: "paymasterValidationData", type: "uint256", internalType: "uint256" }, { name: "paymasterVerificationGasLimit", type: "uint256", internalType: "uint256" }, { name: "paymasterPostOpGasLimit", type: "uint256", internalType: "uint256" }, { name: "targetSuccess", type: "bool", internalType: "bool" }, { name: "targetResult", type: "bytes", internalType: "bytes" } ] } ], stateMutability: "nonpayable" } ], functionName: "simulateHandleOpLast", args: [packedUserOperations.map((uop) => uop.packedUserOperation)] }) return simulateHandleOpCallData } const PIMLICO_ESTIMATION_ADDRESS = "0x949CeCa936909f75E5A40bD285d9985eFBb9B0D3" function getPimlicoEstimationCallData07({ userOperation, estimationAddress, entrypoint }: { userOperation: UserOperation<"0.7" | "0.8"> estimationAddress?: Address entrypoint: { address: Address version: "0.7" | "0.8" } }): { to: Address; data: Hex } { const simulateHandleOpLast = encodeSimulateHandleOpLast({ userOperation }) return { to: estimationAddress ?? PIMLICO_ESTIMATION_ADDRESS, data: encodeFunctionData({ abi: [ { inputs: [ { internalType: "address payable", name: "ep", type: "address" }, { internalType: "bytes[]", name: "data", type: "bytes[]" } ], name: "simulateEntryPoint", outputs: [ { internalType: "bytes[]", name: "", type: "bytes[]" } ], stateMutability: "nonpayable", type: "function" } ], functionName: "simulateEntryPoint", args: [entrypoint.address, [simulateHandleOpLast]] }) } } export type GetPimlicoEstimationCallDataParams< entryPointVersion extends EntryPointVersion > = { userOperation: UserOperation<entryPointVersion> entrypoint: { address: Address version: entryPointVersion } } & (entryPointVersion extends "0.6" ? { estimationAddress: never } : { estimationAddress?: Address }) function isEntryPoint06( args: GetPimlicoEstimationCallDataParams<EntryPointVersion> ): args is GetPimlicoEstimationCallDataParams<"0.6"> { return args.entrypoint.version === "0.6" } function isEntryPoint07( args: GetPimlicoEstimationCallDataParams<EntryPointVersion> ): args is GetPimlicoEstimationCallDataParams<"0.7"> { return args.entrypoint.version === "0.7" } function isEntryPoint08( args: GetPimlicoEstimationCallDataParams<EntryPointVersion> ): args is GetPimlicoEstimationCallDataParams<"0.8"> { return args.entrypoint.version === "0.8" } export function getPimlicoEstimationCallData< entryPointVersion extends EntryPointVersion >( args: GetPimlicoEstimationCallDataParams<entryPointVersion> ): { to: Address; data: Hex } { if (isEntryPoint06(args)) { return getPimlicoEstimationCallData06({ userOperation: args.userOperation, entrypoint: { address: args.entrypoint.address, version: "0.6" } }) } if (isEntryPoint07(args)) { return getPimlicoEstimationCallData07({ userOperation: args.userOperation, estimationAddress: args.estimationAddress, entrypoint: { address: args.entrypoint.address, version: "0.7" } }) } if (isEntryPoint08(args)) { return getPimlicoEstimationCallData07({ userOperation: args.userOperation, estimationAddress: args.estimationAddress, entrypoint: { address: args.entrypoint.address, version: "0.8" } }) } throw new Error("Invalid entrypoint version") }