From 3cbcf09664db96b8c7f83c34c75493b30c143d19 Mon Sep 17 00:00:00 2001 From: Lukas Rosario <36800180+lukasrosario@users.noreply.github.com> Date: Mon, 11 Dec 2023 17:55:52 +0900 Subject: [PATCH 1/6] add Base paymaster support --- src/actions/base.ts | 22 +++++++++++++++ .../base/getPaymasterAndDataForEstimateGas.ts | 27 +++++++++++++++++++ .../getPaymasterAndDataForUserOperation.ts | 27 +++++++++++++++++++ src/types/base.ts | 23 ++++++++++++++++ 4 files changed, 99 insertions(+) create mode 100644 src/actions/base.ts create mode 100644 src/actions/base/getPaymasterAndDataForEstimateGas.ts create mode 100644 src/actions/base/getPaymasterAndDataForUserOperation.ts create mode 100644 src/types/base.ts diff --git a/src/actions/base.ts b/src/actions/base.ts new file mode 100644 index 00000000..0879b3cb --- /dev/null +++ b/src/actions/base.ts @@ -0,0 +1,22 @@ +import { + type GetPaymasterAndDataForEstimateGasParameters, + type GetPaymasterAndDataForEstimateGasReturnType, + getPaymasterAndDataForEstimateGas +} from "./base/getPaymasterAndDataForEstimateGas.js" +import { + type GetPaymasterAndDataForUserOperationParameters, + type GetPaymasterAndDataForUserOperationReturnType, + getPaymasterAndDataForUserOperation +} from "./base/getPaymasterAndDataForUserOperation.js" + +export type { + GetPaymasterAndDataForEstimateGasParameters, + GetPaymasterAndDataForEstimateGasReturnType, + GetPaymasterAndDataForUserOperationParameters, + GetPaymasterAndDataForUserOperationReturnType, +} + +export { + getPaymasterAndDataForEstimateGas, + getPaymasterAndDataForUserOperation +} diff --git a/src/actions/base/getPaymasterAndDataForEstimateGas.ts b/src/actions/base/getPaymasterAndDataForEstimateGas.ts new file mode 100644 index 00000000..0d472a88 --- /dev/null +++ b/src/actions/base/getPaymasterAndDataForEstimateGas.ts @@ -0,0 +1,27 @@ +import type { Account, Address, Chain, Client, Hash, Hex, Transport } from "viem" +import { type BasePaymasterRpcSchema } from "../../types/base.js" +import { type UserOperation } from "../../types/userOperation.js" + +export type GetPaymasterAndDataForEstimateGasParameters = { + userOperation: UserOperation + entryPoint: Address + chainId: Hex +} + +export type GetPaymasterAndDataForEstimateGasReturnType = Hash + +export const getPaymasterAndDataForEstimateGas = async < + TTransport extends Transport = Transport, + TChain extends Chain | undefined = Chain | undefined, + TAccount extends Account | undefined = Account | undefined +>( + client: Client, + args: GetPaymasterAndDataForEstimateGasParameters +): Promise => { + const response = await client.request({ + method: "eth_paymasterAndDataForEstimateGas", + params: [args.userOperation, args.entryPoint, args.chainId] + }) + + return response +} diff --git a/src/actions/base/getPaymasterAndDataForUserOperation.ts b/src/actions/base/getPaymasterAndDataForUserOperation.ts new file mode 100644 index 00000000..4caa044b --- /dev/null +++ b/src/actions/base/getPaymasterAndDataForUserOperation.ts @@ -0,0 +1,27 @@ +import type { Account, Address, Chain, Client, Hash, Hex, Transport } from "viem" +import { type BasePaymasterRpcSchema } from "../../types/base.js" +import { type UserOperation } from "../../types/userOperation.js" + +export type GetPaymasterAndDataForUserOperationParameters = { + userOperation: UserOperation + entryPoint: Address + chainId: Hex +} + +export type GetPaymasterAndDataForUserOperationReturnType = Hash + +export const getPaymasterAndDataForUserOperation = async < + TTransport extends Transport = Transport, + TChain extends Chain | undefined = Chain | undefined, + TAccount extends Account | undefined = Account | undefined +>( + client: Client, + args: GetPaymasterAndDataForUserOperationParameters +): Promise => { + const response = await client.request({ + method: "eth_paymasterAndDataForUserOperation", + params: [args.userOperation, args.entryPoint, args.chainId] + }) + + return response +} diff --git a/src/types/base.ts b/src/types/base.ts new file mode 100644 index 00000000..5ecade32 --- /dev/null +++ b/src/types/base.ts @@ -0,0 +1,23 @@ +import type { Address, Hash, Hex } from "viem" +import type { UserOperation } from "./userOperation.js" + +export type BasePaymasterRpcSchema = [ + { + Method: "eth_paymasterAndDataForEstimateGas" + Parameters: [ + userOperation: UserOperation, + entryPoint: Address, + chainId: Hex + ] + ReturnType: Hash + }, + { + Method: "eth_paymasterAndDataForUserOperation" + Parameters: [ + userOperation: UserOperation, + entryPoint: Address, + chainId: Hex + ] + ReturnType: Hash + } +] From 20044bd5b5982661eb7f6119a5f65a0ecaa54de5 Mon Sep 17 00:00:00 2001 From: Lukas Rosario <36800180+lukasrosario@users.noreply.github.com> Date: Fri, 5 Jan 2024 11:54:18 -0500 Subject: [PATCH 2/6] fix types, format / lint, add client --- src/actions/base.ts | 2 +- .../base/getPaymasterAndDataForEstimateGas.ts | 14 +++++-- .../getPaymasterAndDataForUserOperation.ts | 14 +++++-- src/clients/base.ts | 37 +++++++++++++++++++ src/clients/decorators/base.ts | 33 +++++++++++++++++ src/types/base.ts | 6 +-- 6 files changed, 96 insertions(+), 10 deletions(-) create mode 100644 src/clients/base.ts create mode 100644 src/clients/decorators/base.ts diff --git a/src/actions/base.ts b/src/actions/base.ts index 0879b3cb..0aa9d533 100644 --- a/src/actions/base.ts +++ b/src/actions/base.ts @@ -13,7 +13,7 @@ export type { GetPaymasterAndDataForEstimateGasParameters, GetPaymasterAndDataForEstimateGasReturnType, GetPaymasterAndDataForUserOperationParameters, - GetPaymasterAndDataForUserOperationReturnType, + GetPaymasterAndDataForUserOperationReturnType } export { diff --git a/src/actions/base/getPaymasterAndDataForEstimateGas.ts b/src/actions/base/getPaymasterAndDataForEstimateGas.ts index 0d472a88..73aeb6a6 100644 --- a/src/actions/base/getPaymasterAndDataForEstimateGas.ts +++ b/src/actions/base/getPaymasterAndDataForEstimateGas.ts @@ -1,9 +1,17 @@ -import type { Account, Address, Chain, Client, Hash, Hex, Transport } from "viem" +import type { + Account, + Address, + Chain, + Client, + Hash, + Hex, + Transport +} from "viem" import { type BasePaymasterRpcSchema } from "../../types/base.js" -import { type UserOperation } from "../../types/userOperation.js" +import { type UserOperationWithBigIntAsHex } from "../../types/userOperation.js" export type GetPaymasterAndDataForEstimateGasParameters = { - userOperation: UserOperation + userOperation: UserOperationWithBigIntAsHex entryPoint: Address chainId: Hex } diff --git a/src/actions/base/getPaymasterAndDataForUserOperation.ts b/src/actions/base/getPaymasterAndDataForUserOperation.ts index 4caa044b..f5a59956 100644 --- a/src/actions/base/getPaymasterAndDataForUserOperation.ts +++ b/src/actions/base/getPaymasterAndDataForUserOperation.ts @@ -1,9 +1,17 @@ -import type { Account, Address, Chain, Client, Hash, Hex, Transport } from "viem" +import type { + Account, + Address, + Chain, + Client, + Hash, + Hex, + Transport +} from "viem" import { type BasePaymasterRpcSchema } from "../../types/base.js" -import { type UserOperation } from "../../types/userOperation.js" +import { type UserOperationWithBigIntAsHex } from "../../types/userOperation.js" export type GetPaymasterAndDataForUserOperationParameters = { - userOperation: UserOperation + userOperation: UserOperationWithBigIntAsHex entryPoint: Address chainId: Hex } diff --git a/src/clients/base.ts b/src/clients/base.ts new file mode 100644 index 00000000..da12bbbb --- /dev/null +++ b/src/clients/base.ts @@ -0,0 +1,37 @@ +import { + type Account, + type Chain, + type Client, + type PublicClientConfig, + type Transport, + createClient +} from "viem" +import { type BasePaymasterRpcSchema } from "../types/base.js" +import { + type BasePaymasterClientActions, + basePaymasterActions +} from "./decorators/base.js" + +export type BasePaymasterClient = Client< + Transport, + Chain | undefined, + Account | undefined, + BasePaymasterRpcSchema, + BasePaymasterClientActions +> + +export const createBasePaymasterClient = < + transport extends Transport, + chain extends Chain | undefined = undefined +>( + parameters: PublicClientConfig +): BasePaymasterClient => { + const { key = "public", name = "Base Paymaster Client" } = parameters + const client = createClient({ + ...parameters, + key, + name, + type: "basePaymasterClient" + }) + return client.extend(basePaymasterActions) +} diff --git a/src/clients/decorators/base.ts b/src/clients/decorators/base.ts new file mode 100644 index 00000000..34e70654 --- /dev/null +++ b/src/clients/decorators/base.ts @@ -0,0 +1,33 @@ +import type { Client } from "viem" +import { + type GetPaymasterAndDataForEstimateGasParameters, + type GetPaymasterAndDataForEstimateGasReturnType, + getPaymasterAndDataForEstimateGas +} from "../../actions/base/getPaymasterAndDataForEstimateGas.js" +import { + type GetPaymasterAndDataForUserOperationParameters, + type GetPaymasterAndDataForUserOperationReturnType, + getPaymasterAndDataForUserOperation +} from "../../actions/base/getPaymasterAndDataForUserOperation.js" +import { type BasePaymasterClient } from "../base.js" + +export type BasePaymasterClientActions = { + getPaymasterAndDataForEstimateGas: ( + args: GetPaymasterAndDataForEstimateGasParameters + ) => Promise + getPaymasterAndDataForUserOperation: ( + args: GetPaymasterAndDataForUserOperationParameters + ) => Promise +} + +export const basePaymasterActions = ( + client: Client +): BasePaymasterClientActions => ({ + getPaymasterAndDataForEstimateGas: async ( + args: GetPaymasterAndDataForEstimateGasParameters + ) => getPaymasterAndDataForEstimateGas(client as BasePaymasterClient, args), + getPaymasterAndDataForUserOperation: async ( + args: GetPaymasterAndDataForUserOperationParameters + ) => + getPaymasterAndDataForUserOperation(client as BasePaymasterClient, args) +}) diff --git a/src/types/base.ts b/src/types/base.ts index 5ecade32..e0244207 100644 --- a/src/types/base.ts +++ b/src/types/base.ts @@ -1,11 +1,11 @@ import type { Address, Hash, Hex } from "viem" -import type { UserOperation } from "./userOperation.js" +import type { UserOperationWithBigIntAsHex } from "./userOperation.js" export type BasePaymasterRpcSchema = [ { Method: "eth_paymasterAndDataForEstimateGas" Parameters: [ - userOperation: UserOperation, + userOperation: UserOperationWithBigIntAsHex, entryPoint: Address, chainId: Hex ] @@ -14,7 +14,7 @@ export type BasePaymasterRpcSchema = [ { Method: "eth_paymasterAndDataForUserOperation" Parameters: [ - userOperation: UserOperation, + userOperation: UserOperationWithBigIntAsHex, entryPoint: Address, chainId: Hex ] From 3210027ba041a0598b4bd062c1dc70574f2bb392 Mon Sep 17 00:00:00 2001 From: Lukas Rosario <36800180+lukasrosario@users.noreply.github.com> Date: Fri, 5 Jan 2024 11:55:23 -0500 Subject: [PATCH 3/6] add exports --- src/package.json | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/package.json b/src/package.json index 415c8c23..71199a73 100644 --- a/src/package.json +++ b/src/package.json @@ -48,6 +48,11 @@ "import": "./_esm/actions/smartAccount.js", "default": "./_cjs/actions/smartAccount.js" }, + "./actions/base": { + "types": "./_types/actions/base.d.ts", + "import": "./_esm/actions/base.js", + "default": "./_cjs/actions/base.js" + }, "./clients": { "types": "./_types/clients/index.d.ts", "import": "./_esm/clients/index.js", @@ -63,6 +68,11 @@ "import": "./_esm/clients/stackup.js", "default": "./_cjs/clients/stackup.js" }, + "./clients/base": { + "types": "./_types/clients/base.d.ts", + "import": "./_esm/clients/base.js", + "default": "./_cjs/clients/base.js" + }, "./utils": { "types": "./_types/utils/index.d.ts", "import": "./_esm/utils/index.js", From 17a261136aee0af8bdd707052f60cc3118fe5390 Mon Sep 17 00:00:00 2001 From: Lukas Rosario <36800180+lukasrosario@users.noreply.github.com> Date: Fri, 5 Jan 2024 11:57:03 -0500 Subject: [PATCH 4/6] changeset --- .changeset/red-dodos-dress.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/red-dodos-dress.md diff --git a/.changeset/red-dodos-dress.md b/.changeset/red-dodos-dress.md new file mode 100644 index 00000000..76da7cf1 --- /dev/null +++ b/.changeset/red-dodos-dress.md @@ -0,0 +1,5 @@ +--- +"permissionless": patch +--- + +Added Base Paymaster actions From 074fdaea860e91c5ab0bcb8a24b43899c2c55874 Mon Sep 17 00:00:00 2001 From: Lukas Rosario <36800180+lukasrosario@users.noreply.github.com> Date: Fri, 5 Jan 2024 12:47:17 -0500 Subject: [PATCH 5/6] docs --- .../base/getPaymasterAndDataForEstimateGas.ts | 43 ++++++++++++------- .../getPaymasterAndDataForUserOperation.ts | 43 ++++++++++++------- src/clients/base.ts | 15 +++++++ src/clients/decorators/base.ts | 43 +++++++++++++++++++ 4 files changed, 112 insertions(+), 32 deletions(-) diff --git a/src/actions/base/getPaymasterAndDataForEstimateGas.ts b/src/actions/base/getPaymasterAndDataForEstimateGas.ts index 73aeb6a6..8e767c58 100644 --- a/src/actions/base/getPaymasterAndDataForEstimateGas.ts +++ b/src/actions/base/getPaymasterAndDataForEstimateGas.ts @@ -1,13 +1,5 @@ -import type { - Account, - Address, - Chain, - Client, - Hash, - Hex, - Transport -} from "viem" -import { type BasePaymasterRpcSchema } from "../../types/base.js" +import type { Address, Hash, Hex } from "viem" +import { BasePaymasterClient } from "../../clients/base.js" import { type UserOperationWithBigIntAsHex } from "../../types/userOperation.js" export type GetPaymasterAndDataForEstimateGasParameters = { @@ -18,12 +10,31 @@ export type GetPaymasterAndDataForEstimateGasParameters = { export type GetPaymasterAndDataForEstimateGasReturnType = Hash -export const getPaymasterAndDataForEstimateGas = async < - TTransport extends Transport = Transport, - TChain extends Chain | undefined = Chain | undefined, - TAccount extends Account | undefined = Account | undefined ->( - client: Client, +/** + * Returns paymasterAndData for gas estimation. Note that this is a dummy signature that won't be accepted by the paymaster, except for gas estimation. + * + * @param client {@link BasePaymasterClient} that you created using viem's createClient whose transport url is pointing to the Base paymaster. + * @param args {@link GetPaymasterAndDataForEstimateGasParameters} UserOperation you want to sponsor, entryPoint, and chain ID. + * @returns paymasterAndData with a dummy signature just for gas estimation. + * + * + * @example + * import { createClient } from "viem" + * import { getPaymasterAndDataForEstimateGas } from "permissionless/actions/base" + * + * const paymasterClient = createClient({ + * transport: http("https://paymaster.base.org") + * }) + * + * await getPaymasterAndDataForEstimateGas(bundlerClient, { + * userOperation: userOperationWithoutPaymaster, + * entryPoint: entryPoint, + * chainId: toHex(chainId) + * }}) + * + */ +export const getPaymasterAndDataForEstimateGas = async ( + client: BasePaymasterClient, args: GetPaymasterAndDataForEstimateGasParameters ): Promise => { const response = await client.request({ diff --git a/src/actions/base/getPaymasterAndDataForUserOperation.ts b/src/actions/base/getPaymasterAndDataForUserOperation.ts index f5a59956..5c4c9f26 100644 --- a/src/actions/base/getPaymasterAndDataForUserOperation.ts +++ b/src/actions/base/getPaymasterAndDataForUserOperation.ts @@ -1,13 +1,5 @@ -import type { - Account, - Address, - Chain, - Client, - Hash, - Hex, - Transport -} from "viem" -import { type BasePaymasterRpcSchema } from "../../types/base.js" +import type { Account, Address, Chain, Hash, Hex, Transport } from "viem" +import { BasePaymasterClient } from "../../clients/base.js" import { type UserOperationWithBigIntAsHex } from "../../types/userOperation.js" export type GetPaymasterAndDataForUserOperationParameters = { @@ -18,12 +10,31 @@ export type GetPaymasterAndDataForUserOperationParameters = { export type GetPaymasterAndDataForUserOperationReturnType = Hash -export const getPaymasterAndDataForUserOperation = async < - TTransport extends Transport = Transport, - TChain extends Chain | undefined = Chain | undefined, - TAccount extends Account | undefined = Account | undefined ->( - client: Client, +/** + * Returns paymasterAndData for sponsoring a userOp. + * + * @param client {@link BasePaymasterClient} that you created using viem's createClient whose transport url is pointing to the Base paymaster. + * @param args {@link GetPaymasterAndDataForUserOperationParameters} UserOperation you want to sponsor, entryPoint, and chain ID. + * @returns paymasterAndData for sponsoring a userOp. + * + * + * @example + * import { createClient } from "viem" + * import { getPaymasterAndDataForUserOperation } from "permissionless/actions/base" + * + * const paymasterClient = createClient({ + * transport: http("https://paymaster.base.org") + * }) + * + * await getPaymasterAndDataForUserOperation(bundlerClient, { + * userOperation: userOperation, + * entryPoint: entryPoint, + * chainId: toHex(chainId) + * }}) + * + */ +export const getPaymasterAndDataForUserOperation = async ( + client: BasePaymasterClient, args: GetPaymasterAndDataForUserOperationParameters ): Promise => { const response = await client.request({ diff --git a/src/clients/base.ts b/src/clients/base.ts index da12bbbb..4dfa45f6 100644 --- a/src/clients/base.ts +++ b/src/clients/base.ts @@ -20,6 +20,21 @@ export type BasePaymasterClient = Client< BasePaymasterClientActions > +/** + * Creates a Base paymaster client. + * + * - Docs: https://github.com/base-org/paymaster + * + * @param config - {@link PublicClientConfig} + * @returns A Base Paymaster Client. {@link BasePaymasterClient} + * + * @example + * import { createPublicClient, http } from 'viem' + * + * const basePaymasterClient = createBasePaymasterClient({ + * transport: http("https://paymaster.base.org"), + * }) + */ export const createBasePaymasterClient = < transport extends Transport, chain extends Chain | undefined = undefined diff --git a/src/clients/decorators/base.ts b/src/clients/decorators/base.ts index 34e70654..970fa647 100644 --- a/src/clients/decorators/base.ts +++ b/src/clients/decorators/base.ts @@ -12,9 +12,52 @@ import { import { type BasePaymasterClient } from "../base.js" export type BasePaymasterClientActions = { + /** + * Returns paymasterAndData for gas estimation. Note that this is a dummy signature that won't be accepted by the paymaster, except for gas estimation. + * + * @param args {@link GetPaymasterAndDataForEstimateGasParameters} UserOperation you want to sponsor, entryPoint, and chain ID. + * @returns paymasterAndData with a dummy signature just for gas estimation. + * + * @example + * import { createClient } from "viem" + * import { basePaymasterActions } from "permissionless/actions/base" + * + * const basePaymasterClient = createClient({ + * transport: http("https://paymaster.base.org") + * }).extend(basePaymasterActions) + * + * await basePaymasterClient.getPaymasterAndDataForEstimateGas({ + * userOperation: userOperationWithoutPaymaster,, + * entryPoint: entryPoint, + * chainId: toHex(chainId) + * }) + * + */ getPaymasterAndDataForEstimateGas: ( args: GetPaymasterAndDataForEstimateGasParameters ) => Promise + + /** + * Returns paymasterAndData for sponsoring a userOp. + * + * @param args {@link GetPaymasterAndDataForUserOperationParameters} UserOperation you want to sponsor, entryPoint, and chain ID. + * @returns paymasterAndData for sponsoring a userOp. + * + * @example + * import { createClient } from "viem" + * import { basePaymasterActions } from "permissionless/actions/base" + * + * const basePaymasterClient = createClient({ + * transport: http("https://paymaster.base.org") + * }).extend(basePaymasterActions) + * + * await basePaymasterClient.getPaymasterAndDataForUserOperation({ + * userOperation: userOperation, + * entryPoint: entryPoint, + * chainId: toHex(chainId) + * }) + * + */ getPaymasterAndDataForUserOperation: ( args: GetPaymasterAndDataForUserOperationParameters ) => Promise From 76de2d53eb8b116344652bba77499fe6b6484c80 Mon Sep 17 00:00:00 2001 From: Lukas Rosario <36800180+lukasrosario@users.noreply.github.com> Date: Fri, 5 Jan 2024 13:16:06 -0500 Subject: [PATCH 6/6] simplify some stuff --- src/clients/base.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/clients/base.ts b/src/clients/base.ts index 4dfa45f6..bcfa2342 100644 --- a/src/clients/base.ts +++ b/src/clients/base.ts @@ -4,8 +4,10 @@ import { type Client, type PublicClientConfig, type Transport, - createClient + createClient, + http } from "viem" +import type { PartialBy } from "viem/types/utils" import { type BasePaymasterRpcSchema } from "../types/base.js" import { type BasePaymasterClientActions, @@ -39,14 +41,14 @@ export const createBasePaymasterClient = < transport extends Transport, chain extends Chain | undefined = undefined >( - parameters: PublicClientConfig + parameters?: PartialBy, 'transport'> ): BasePaymasterClient => { - const { key = "public", name = "Base Paymaster Client" } = parameters const client = createClient({ ...parameters, - key, - name, - type: "basePaymasterClient" + key: parameters?.key ?? "public", + name: parameters?.name ?? "Base Paymaster Client", + type: "basePaymasterClient", + transport: parameters?.transport ?? http("https://paymaster.base.org") }) return client.extend(basePaymasterActions) }