From 21eb783d70de94eff552c0bb9e43e7a89b5e5772 Mon Sep 17 00:00:00 2001 From: Derek Chiang Date: Mon, 29 Jan 2024 18:32:53 -0500 Subject: [PATCH] Support ERC20 paymaster in presets --- packages/presets/package.json | 2 +- packages/presets/zerodev/index.ts | 64 +++++++++++++++++++++++-------- 2 files changed, 48 insertions(+), 18 deletions(-) diff --git a/packages/presets/package.json b/packages/presets/package.json index 9a3cca21..de0137f1 100644 --- a/packages/presets/package.json +++ b/packages/presets/package.json @@ -1,6 +1,6 @@ { "name": "@zerodev/presets", - "version": "5.0.1", + "version": "5.1.0", "author": "ZeroDev", "main": "./_cjs/index.js", "module": "./_esm/index.js", diff --git a/packages/presets/zerodev/index.ts b/packages/presets/zerodev/index.ts index d0de276e..6ef260af 100644 --- a/packages/presets/zerodev/index.ts +++ b/packages/presets/zerodev/index.ts @@ -3,12 +3,12 @@ import type { KernelAccountClient, KernelSmartAccount } from "@zerodev/sdk" import { createKernelAccount, createKernelAccountClient, - createZeroDevPaymasterClient + createZeroDevPaymasterClient, } from "@zerodev/sdk" import type { UserOperation } from "permissionless" import type { SmartAccountSigner } from "permissionless/accounts" import type { Address, Chain, HttpTransport } from "viem" -import { http, createPublicClient } from "viem" +import { http, createPublicClient, isAddress } from "viem" export type Provider = "STACKUP" | "PIMLICO" | "ALCHEMY" | "GELATO" @@ -34,6 +34,17 @@ const getZeroDevPaymasterRPC = ( return rpc } +// An enum type called "PAYMASTER" with the following values: +// - "NONE" +// - "SPONSOR" +// - "ERC20", which should wrap a string +type ERC20Paymaster = Address +type PaymasterType = "NONE" | "SPONSOR" | ERC20Paymaster + +function isERC20(value: PaymasterType): value is ERC20Paymaster { + return isAddress(value) +} + export async function createEcdsaKernelAccountClient< TChain extends Chain | undefined = Chain | undefined, TSource extends string = "custom", @@ -44,14 +55,14 @@ export async function createEcdsaKernelAccountClient< signer, provider, index, - usePaymaster = true + paymaster = 'SPONSOR', }: { chain: TChain projectId: string signer: SmartAccountSigner provider?: Provider index?: bigint - usePaymaster?: boolean + paymaster?: PaymasterType }): Promise< KernelAccountClient< HttpTransport, @@ -74,23 +85,42 @@ export async function createEcdsaKernelAccountClient< index }) + let sponsorUserOperation: ((args: { + userOperation: UserOperation + entryPoint: Address + }) => Promise) | undefined = undefined + + if (paymaster !== undefined) { + const zerodevPaymaster = createZeroDevPaymasterClient({ + chain: chain, + transport: http( + getZeroDevPaymasterRPC(projectId, provider) + ) + }) + + if (isERC20(paymaster)) { + sponsorUserOperation = async ({ userOperation }): Promise => { + return zerodevPaymaster.sponsorUserOperation({ + userOperation, + gasToken: paymaster, + }) + } + } else if (paymaster === "SPONSOR") { + sponsorUserOperation = async ({ userOperation }): Promise => { + return zerodevPaymaster.sponsorUserOperation({ + userOperation + }) + } + } else if (paymaster !== "NONE") { + throw new Error('Invalid paymaster type') + } + } + const kernelClient = createKernelAccountClient({ account, chain, transport: http(getZeroDevBundlerRPC(projectId, provider)), - sponsorUserOperation: usePaymaster - ? async ({ userOperation }): Promise => { - const zerodevPaymaster = createZeroDevPaymasterClient({ - chain: chain, - transport: http( - getZeroDevPaymasterRPC(projectId, provider) - ) - }) - return zerodevPaymaster.sponsorUserOperation({ - userOperation - }) - } - : undefined + sponsorUserOperation, }) return kernelClient as unknown as KernelAccountClient<