From d60fe9cdeb7d406b9757d87adeff4167f3be46b9 Mon Sep 17 00:00:00 2001 From: Sahil Vasava Date: Wed, 23 Oct 2024 17:52:26 +0700 Subject: [PATCH] feat: Added sponsorUserOperationEip7677 action to ZeroDevPaymasterClient --- packages/core/CHANGELOG.md | 6 + packages/core/actions/index.ts | 6 + .../actions/paymaster/sponsorUserOperation.ts | 3 +- .../paymaster/sponsorUserOperationEip7677.ts | 152 ++++++++++++++++++ packages/core/clients/decorators/kernel.ts | 26 ++- packages/core/package.json | 2 +- 6 files changed, 191 insertions(+), 4 deletions(-) create mode 100644 packages/core/actions/paymaster/sponsorUserOperationEip7677.ts diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index cec7ec25..0a0166a3 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,11 @@ # @zerodev/sdk +## 5.3.23 + +### Patch Changes + +- Added sponsorUserOperationEip7677 action to ZeroDevPaymasterClient + ## 5.3.22 ### Patch Changes diff --git a/packages/core/actions/index.ts b/packages/core/actions/index.ts index ab6fd1c9..2551f98a 100644 --- a/packages/core/actions/index.ts +++ b/packages/core/actions/index.ts @@ -30,3 +30,9 @@ export { type EstimateGasInERC20Parameters, type EstimateGasInERC20ReturnType } from "./paymaster/estimateGasInERC20.js" + +export { + type SponsorUserOperationEip7677Parameters, + type SponsorUserOperationEip7677ReturnType, + sponsorUserOperationEip7677 +} from "./paymaster/sponsorUserOperationEip7677.js" diff --git a/packages/core/actions/paymaster/sponsorUserOperation.ts b/packages/core/actions/paymaster/sponsorUserOperation.ts index 6e4aaa5c..56549d89 100644 --- a/packages/core/actions/paymaster/sponsorUserOperation.ts +++ b/packages/core/actions/paymaster/sponsorUserOperation.ts @@ -1,4 +1,5 @@ import { getEntryPointVersion } from "permissionless" +import type { PartialPick } from "permissionless/types" import type { ENTRYPOINT_ADDRESS_V06_TYPE, EntryPoint @@ -29,8 +30,6 @@ export type SponsorUserOperationParameters = { shouldConsume?: boolean } -export type PartialPick = Partial> - export type SponsorUserOperationReturnType = entryPoint extends ENTRYPOINT_ADDRESS_V06_TYPE ? Pick< diff --git a/packages/core/actions/paymaster/sponsorUserOperationEip7677.ts b/packages/core/actions/paymaster/sponsorUserOperationEip7677.ts new file mode 100644 index 00000000..04cbbffe --- /dev/null +++ b/packages/core/actions/paymaster/sponsorUserOperationEip7677.ts @@ -0,0 +1,152 @@ +import { + type BundlerClient, + ENTRYPOINT_ADDRESS_V06, + type EstimateUserOperationGasParameters, + type EstimateUserOperationGasReturnType +} from "permissionless" +import { + type GetPaymasterDataParameters, + type GetPaymasterDataReturnType, + type GetPaymasterStubDataParameters, + type GetPaymasterStubDataReturnType, + paymasterActionsEip7677 +} from "permissionless/experimental" +import type { + ENTRYPOINT_ADDRESS_V06_TYPE, + ENTRYPOINT_ADDRESS_V07_TYPE, + EntryPoint, + PartialPick +} from "permissionless/types" +import type { StateOverrides } from "permissionless/types/bundler" +import type { UserOperation } from "permissionless/types/userOperation.js" +import type { PartialBy } from "viem/types/utils" +import type { ZeroDevPaymasterClient } from "../../clients/paymasterClient.js" + +export type SponsorUserOperationEip7677Parameters< + entryPoint extends EntryPoint +> = { + userOperation: entryPoint extends ENTRYPOINT_ADDRESS_V06_TYPE + ? PartialBy< + UserOperation<"v0.6">, + "callGasLimit" | "preVerificationGas" | "verificationGasLimit" + > + : PartialBy< + UserOperation<"v0.7">, + | "callGasLimit" + | "preVerificationGas" + | "verificationGasLimit" + | "paymasterVerificationGasLimit" + | "paymasterPostOpGasLimit" + > + entryPoint: entryPoint +} + +export type SponsorUserOperationEip7677ReturnType< + entryPoint extends EntryPoint +> = entryPoint extends ENTRYPOINT_ADDRESS_V06_TYPE + ? Pick< + UserOperation<"v0.6">, + | "callGasLimit" + | "verificationGasLimit" + | "preVerificationGas" + | "paymasterAndData" + > & + PartialPick< + UserOperation<"v0.6">, + "maxFeePerGas" | "maxPriorityFeePerGas" + > + : Pick< + UserOperation<"v0.7">, + | "callGasLimit" + | "verificationGasLimit" + | "preVerificationGas" + | "paymaster" + | "paymasterVerificationGasLimit" + | "paymasterPostOpGasLimit" + | "paymasterData" + > & + PartialPick< + UserOperation<"v0.7">, + "maxFeePerGas" | "maxPriorityFeePerGas" + > + +/** + * Returns paymasterAndData & updated gas parameters required to sponsor a userOperation. + */ +export const sponsorUserOperationEip7677 = async < + entryPoint extends EntryPoint +>( + client: ZeroDevPaymasterClient, + args: SponsorUserOperationEip7677Parameters, + bundlerClient: BundlerClient, + stateOverrides?: StateOverrides +): Promise> => { + const { entryPoint: entryPointAddress, userOperation } = args + const chain = client.chain + const paymasterClient = client.extend( + paymasterActionsEip7677(entryPointAddress) + ) + const stubData = await paymasterClient.getPaymasterStubData({ + userOperation: userOperation as GetPaymasterStubDataParameters< + entryPoint, + typeof chain + >["userOperation"], + chain + }) + const stubUserOperation = { + ...userOperation, + ...stubData + } + + const gas = (await bundlerClient.estimateUserOperationGas( + { + userOperation: + stubUserOperation as EstimateUserOperationGasParameters["userOperation"] + }, + stateOverrides + )) as EstimateUserOperationGasReturnType + const userOperationWithGas = { + ...stubUserOperation, + callGasLimit: gas.callGasLimit, + verificationGasLimit: gas.verificationGasLimit, + preVerificationGas: gas.preVerificationGas + } as GetPaymasterDataParameters["userOperation"] + + const paymasterData = await paymasterClient.getPaymasterData({ + userOperation: userOperationWithGas, + chain + }) + + if (entryPointAddress === ENTRYPOINT_ADDRESS_V06) { + const paymasterDataV06 = + paymasterData as GetPaymasterDataReturnType + return { + callGasLimit: BigInt(gas.callGasLimit), + verificationGasLimit: BigInt(gas.verificationGasLimit), + preVerificationGas: BigInt(gas.preVerificationGas), + paymasterAndData: paymasterDataV06?.paymasterAndData, + maxFeePerGas: BigInt(userOperation.maxFeePerGas), + maxPriorityFeePerGas: BigInt(userOperation.maxPriorityFeePerGas) + } as SponsorUserOperationEip7677ReturnType + } + const stubDataV07 = + stubData as GetPaymasterStubDataReturnType + const paymasterDataV07 = + paymasterData as GetPaymasterDataReturnType + + return { + callGasLimit: BigInt(gas.callGasLimit), + verificationGasLimit: BigInt(gas.verificationGasLimit), + preVerificationGas: BigInt(gas.preVerificationGas), + paymaster: paymasterDataV07.paymaster, + paymasterData: paymasterDataV07.paymasterData, + paymasterVerificationGasLimit: + stubDataV07.paymasterVerificationGasLimit && + BigInt(stubDataV07.paymasterVerificationGasLimit), + paymasterPostOpGasLimit: + stubDataV07?.paymasterPostOpGasLimit && + BigInt(stubDataV07.paymasterPostOpGasLimit), + maxFeePerGas: BigInt(userOperation.maxFeePerGas), + maxPriorityFeePerGas: BigInt(userOperation.maxPriorityFeePerGas) + } as SponsorUserOperationEip7677ReturnType +} diff --git a/packages/core/clients/decorators/kernel.ts b/packages/core/clients/decorators/kernel.ts index 1318bce4..021ff77e 100644 --- a/packages/core/clients/decorators/kernel.ts +++ b/packages/core/clients/decorators/kernel.ts @@ -1,6 +1,11 @@ -import { type SmartAccountActions, smartAccountActions } from "permissionless" +import { + type BundlerClient, + type SmartAccountActions, + smartAccountActions +} from "permissionless" import type { Middleware } from "permissionless/actions/smartAccount" import type { EntryPoint, Prettify } from "permissionless/types" +import type { StateOverrides } from "permissionless/types/bundler" import type { Chain, Client, Hash, Transport } from "viem" import type { KernelSmartAccount } from "../../accounts/index.js" import { @@ -19,11 +24,14 @@ import type { ChangeSudoValidatorParameters, SignUserOperationParameters, SignUserOperationReturnType, + SponsorUserOperationEip7677Parameters, + SponsorUserOperationEip7677ReturnType, UninstallPluginParameters } from "../../actions/index.js" import { changeSudoValidator, signUserOperation, + sponsorUserOperationEip7677, uninstallPlugin } from "../../actions/index.js" import { @@ -48,6 +56,11 @@ export type ZeroDevPaymasterClientActions = { estimateGasInERC20: ( args: EstimateGasInERC20Parameters ) => Promise + sponsorUserOperationEip7677: ( + args: SponsorUserOperationEip7677Parameters, + bundlerClient: BundlerClient, + stateOverrides?: StateOverrides + ) => Promise> } export const zerodevPaymasterActions = @@ -67,6 +80,17 @@ export const zerodevPaymasterActions = estimateGasInERC20( client as ZeroDevPaymasterClient, args + ), + sponsorUserOperationEip7677: async ( + args: SponsorUserOperationEip7677Parameters, + bundlerClient: BundlerClient, + stateOverrides?: StateOverrides + ) => + sponsorUserOperationEip7677( + client as ZeroDevPaymasterClient, + args, + bundlerClient, + stateOverrides ) }) diff --git a/packages/core/package.json b/packages/core/package.json index 83b0d704..99925b60 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@zerodev/sdk", - "version": "5.3.22", + "version": "5.3.23", "author": "ZeroDev", "main": "./_cjs/index.js", "module": "./_esm/index.js",