3rd Party Paymasters

The SmartAccountClient within @aa-sdk/core is unopinionated about which paymaster you use, so you can connect to any paymaster really simply. Configuration is done using the paymasterAndData config option when you call createSmartAccountClient.

Usage

import { 
function createSmartAccountClient<TTransport extends Transport = Transport, TChain extends Chain | undefined = Chain | undefined, TAccount extends SmartContractAccount | undefined = SmartContractAccount | undefined, TContext extends UserOperationContext | undefined = UserOperationContext | undefined>(config: SmartAccountClientConfig<TTransport, TChain, TAccount, TContext>): SmartAccountClient<TTransport, TChain, TAccount>
createSmartAccountClient
} from "@aa-sdk/core";
import {
function http<rpcSchema extends RpcSchema | undefined = undefined, raw extends boolean = false>(url?: string | undefined, config?: HttpTransportConfig<rpcSchema, raw>): HttpTransport<rpcSchema, raw>
http
} from "viem";
import {
const sepolia: { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; ... 11 more ...; serializers?: ChainSerializers<...> | undefined; }
sepolia
} from "viem/chains";
const
const chain: { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; ... 11 more ...; serializers?: ChainSerializers<...> | undefined; }
chain
=
const sepolia: { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; ... 11 more ...; serializers?: ChainSerializers<...> | undefined; }
sepolia
;
const
const client: { [x: string]: unknown; account: SmartContractAccount | undefined; batch?: { multicall?: boolean | Prettify<MulticallBatchOptions> | undefined; } | undefined; ... 83 more ...; extend: <const client extends { ...; } & ExactPartial<...>>(fn: (client: Client<...>) => client) => Client<...>; }
client
=
createSmartAccountClient<HttpTransport<undefined, false>, { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; ... 11 more ...; serializers?: ChainSerializers<...> | undefined; }, SmartContractAccount | undefined, UserOperationContext | undefined>(config: { ...; }): { ...; }
createSmartAccountClient
({
chain?: Chain | { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; ... 11 more ...; serializers?: ChainSerializers<...> | undefined; } | undefined

Chain for the client.

chain
,
transport: HttpTransport<undefined, false>

The RPC transport

transport
:
http<undefined, false>(url?: string | undefined, config?: HttpTransportConfig<undefined, false> | undefined): HttpTransport<undefined, false>
http
("RPC_URL"),
// sets the dummy paymasterAndData with paymaster address appended with some dummy paymasterData // that looks like a valid paymasterData
dummyPaymasterAndData?: ClientMiddlewareFn<UserOperationContext | undefined> | undefined
dummyPaymasterAndData
: async (
userop: Deferrable<UserOperationStruct<TEntryPointVersion>>
userop
) => ({
...
userop: Deferrable<UserOperationStruct<TEntryPointVersion>>
userop
,
paymasterAndData: string
paymasterAndData
: `0x<PAYMASTER_ADDRESS><PAYMASTER_DUMMY_DATA>`,
}),
paymasterAndData?: ClientMiddlewareFn<UserOperationContext | undefined> | undefined
paymasterAndData
: async (
userop: Deferrable<UserOperationStruct<TEntryPointVersion>>
userop
,
opts: ClientMiddlewareArgs<TAccount, C, UserOperationContext | undefined, TEntryPointVersion>
opts
) => {
// call your paymaster here to sponsor the userop // leverage the `opts` field to apply any overrides return { ...
userop: Deferrable<UserOperationStruct<TEntryPointVersion>>
userop
,
paymasterAndData: string
paymasterAndData
: "0xresponsefromprovider",
}; }, });

ERC-7677 Paymaster

If your paymaster supports the ERC-7677 standard, you can use the erc7677Middleware to interact with it.

Usage with single RPC provider

If you’re using the same RPC provider for your Paymaster, Bundler, and Node RPC traffic, then you can do the following:

import { 
function createSmartAccountClient<TTransport extends Transport = Transport, TChain extends Chain | undefined = Chain | undefined, TAccount extends SmartContractAccount | undefined = SmartContractAccount | undefined, TContext extends UserOperationContext | undefined = UserOperationContext | undefined>(config: SmartAccountClientConfig<TTransport, TChain, TAccount, TContext>): SmartAccountClient<TTransport, TChain, TAccount>
createSmartAccountClient
,
function erc7677Middleware<TContext extends Record<string, any> | undefined = Record<string, any> | undefined>(params?: Erc7677MiddlewareParams<TContext>): Required<Pick<ClientMiddlewareConfig, "dummyPaymasterAndData" | "paymasterAndData">>

Middleware function for interacting with ERC-7677 enabled clients. It supports resolving paymaster and data fields for user operations. This middleware assumes that your RPC provider supports the ERC-7677 methods (pm_getPaymasterStubData and pm_getPaymasterData).

erc7677Middleware
} from "@aa-sdk/core";
import {
function http<rpcSchema extends RpcSchema | undefined = undefined, raw extends boolean = false>(url?: string | undefined, config?: HttpTransportConfig<rpcSchema, raw>): HttpTransport<rpcSchema, raw>
http
} from "viem";
import {
const sepolia: { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; ... 11 more ...; serializers?: ChainSerializers<...> | undefined; }
sepolia
} from "viem/chains";
const
const chain: { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; ... 11 more ...; serializers?: ChainSerializers<...> | undefined; }
chain
=
const sepolia: { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; ... 11 more ...; serializers?: ChainSerializers<...> | undefined; }
sepolia
;
const
const client: { [x: string]: unknown; account: SmartContractAccount | undefined; batch?: { multicall?: boolean | Prettify<MulticallBatchOptions> | undefined; } | undefined; ... 83 more ...; extend: <const client extends { ...; } & ExactPartial<...>>(fn: (client: Client<...>) => client) => Client<...>; }
client
=
createSmartAccountClient<HttpTransport<undefined, false>, { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; ... 11 more ...; serializers?: ChainSerializers<...> | undefined; }, SmartContractAccount | undefined, UserOperationContext | undefined>(config: { ...; }): { ...; }
createSmartAccountClient
({
chain?: Chain | { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; ... 11 more ...; serializers?: ChainSerializers<...> | undefined; } | undefined

Chain for the client.

chain
,
// This example assumes that your RPC provider supports the ERC-7677 methods
transport: HttpTransport<undefined, false>

The RPC transport

transport
:
http<undefined, false>(url?: string | undefined, config?: HttpTransportConfig<undefined, false> | undefined): HttpTransport<undefined, false>
http
("RPC_URL"),
...
erc7677Middleware<Record<string, any> | undefined>(params?: Erc7677MiddlewareParams<Record<string, any> | undefined, keyof EntryPointRegistryBase<unknown>> | undefined): Required<Pick<ClientMiddlewareConfig, "dummyPaymasterAndData" | "paymasterAndData">>

Middleware function for interacting with ERC-7677 enabled clients. It supports resolving paymaster and data fields for user operations. This middleware assumes that your RPC provider supports the ERC-7677 methods (pm_getPaymasterStubData and pm_getPaymasterData).

erc7677Middleware
(),
});

Usage with multiple RPC providers

If you’re using a separate RPC provider for your Paymaster, you can can use the split transport to route your ERC-7677 traffic to a different provider:

import {
  
function createSmartAccountClient<TTransport extends Transport = Transport, TChain extends Chain | undefined = Chain | undefined, TAccount extends SmartContractAccount | undefined = SmartContractAccount | undefined, TContext extends UserOperationContext | undefined = UserOperationContext | undefined>(config: SmartAccountClientConfig<TTransport, TChain, TAccount, TContext>): SmartAccountClient<TTransport, TChain, TAccount>
createSmartAccountClient
,
function erc7677Middleware<TContext extends Record<string, any> | undefined = Record<string, any> | undefined>(params?: Erc7677MiddlewareParams<TContext>): Required<Pick<ClientMiddlewareConfig, "dummyPaymasterAndData" | "paymasterAndData">>

Middleware function for interacting with ERC-7677 enabled clients. It supports resolving paymaster and data fields for user operations. This middleware assumes that your RPC provider supports the ERC-7677 methods (pm_getPaymasterStubData and pm_getPaymasterData).

erc7677Middleware
,
const split: (params: SplitTransportParams) => CustomTransport

The Split Transport allows you to split RPC traffic for specific methods across different RPC providers. This is done by specifying the methods you want handled specially as overrides and providing a fallback transport for all other methods.

split
,
} from "@aa-sdk/core"; import {
function http<rpcSchema extends RpcSchema | undefined = undefined, raw extends boolean = false>(url?: string | undefined, config?: HttpTransportConfig<rpcSchema, raw>): HttpTransport<rpcSchema, raw>
http
} from "viem";
import {
const sepolia: { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; ... 11 more ...; serializers?: ChainSerializers<...> | undefined; }
sepolia
} from "viem/chains";
const
const chain: { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; ... 11 more ...; serializers?: ChainSerializers<...> | undefined; }
chain
=
const sepolia: { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; ... 11 more ...; serializers?: ChainSerializers<...> | undefined; }
sepolia
;
const
const erc7677Methods: string[]
erc7677Methods
= ["pm_getPaymasterStubData", "pm_getPaymasterData"];
const
const transport: CustomTransport
transport
=
function split(params: SplitTransportParams): CustomTransport

The Split Transport allows you to split RPC traffic for specific methods across different RPC providers. This is done by specifying the methods you want handled specially as overrides and providing a fallback transport for all other methods.

split
({
SplitTransportParams.overrides: { methods: string[]; transport: Transport; }[]
overrides
: [
// NOTE: if you're splitting Node and Bundler traffic too, you can add the bundler config to this array {
methods: string[]
methods
:
const erc7677Methods: string[]
erc7677Methods
,
transport: Transport
transport
:
http<undefined, false>(url?: string | undefined, config?: HttpTransportConfig<undefined, false> | undefined): HttpTransport<undefined, false>
http
("PAYMASTER_RPC_URL"),
}, ],
SplitTransportParams.fallback: Transport
fallback
:
http<undefined, false>(url?: string | undefined, config?: HttpTransportConfig<undefined, false> | undefined): HttpTransport<undefined, false>
http
("NODE_AND_BUNDLER_RPC_URL"),
}); const
const client: { [x: string]: unknown; account: SmartContractAccount | undefined; batch?: { multicall?: boolean | Prettify<MulticallBatchOptions> | undefined; } | undefined; ... 83 more ...; extend: <const client extends { ...; } & ExactPartial<...>>(fn: (client: Client<...>) => client) => Client<...>; }
client
=
createSmartAccountClient<CustomTransport, { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; ... 11 more ...; serializers?: ChainSerializers<...> | undefined; }, SmartContractAccount | undefined, UserOperationContext | undefined>(config: { ...; }): { ...; }
createSmartAccountClient
({
chain?: Chain | { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; ... 11 more ...; serializers?: ChainSerializers<...> | undefined; } | undefined

Chain for the client.

chain
,
transport: CustomTransport

The RPC transport

transport
,
...
erc7677Middleware<Record<string, any> | undefined>(params?: Erc7677MiddlewareParams<Record<string, any> | undefined, keyof EntryPointRegistryBase<unknown>> | undefined): Required<Pick<ClientMiddlewareConfig, "dummyPaymasterAndData" | "paymasterAndData">>

Middleware function for interacting with ERC-7677 enabled clients. It supports resolving paymaster and data fields for user operations. This middleware assumes that your RPC provider supports the ERC-7677 methods (pm_getPaymasterStubData and pm_getPaymasterData).

erc7677Middleware
(),
});

ERC-20 Gas Sponsorship

We are working on building support for an ERC-20 paymaster!

In the meantime, you could use a third-party paymaster, such as Stackup, to sponsor ERC-20 gas. Here’s an example using Stackup with the Alchemy SDK:

import { 
function createMultiOwnerModularAccountClient<TSigner extends SmartAccountSigner = SmartAccountSigner<any>>(params: AlchemyModularAccountClientConfig<TSigner> & { transport: AlchemyTransport; }): Promise<AlchemySmartAccountClient<Chain | undefined, MultiOwnerModularAccount<TSigner>, MultiOwnerPluginActions<MultiOwnerModularAccount<TSigner>> & PluginManagerActions<MultiOwnerModularAccount<TSigner>> & AccountLoupeActions<MultiOwnerModularAccount<TSigner>>>> (+1 overload)
createMultiOwnerModularAccountClient
} from "@account-kit/smart-contracts";
import {
const alchemyFeeEstimator: (transport: AlchemyTransport) => ClientMiddlewareFn

Function that estimates the transaction fees using Alchemy methods for a given client. It fetches the latest block and estimates the max priority fee per gas, applying any overrides or fee options provided.

alchemyFeeEstimator
,
const createAlchemyPublicRpcClient: ({ transport, chain, }: { transport: AlchemyTransport; chain: Chain | undefined; }) => ClientWithAlchemyMethods

Creates an Alchemy public RPC client with the provided chain, connection configuration, and optional fetch options. The client has alchemy methods and can dynamically update HTTP headers.

createAlchemyPublicRpcClient
,
function alchemy(config: AlchemyTransportConfig): AlchemyTransport

Creates an Alchemy transport with the specified configuration options. When sending all traffic to Alchemy, you must pass in one of rpcUrl, apiKey, or jwt. If you want to send Bundler and Paymaster traffic to Alchemy and Node traffic to a different RPC, you must pass in alchemyConnection and nodeRpcUrl.

alchemy
,
} from "@account-kit/infra"; import {
function deepHexlify(obj: any): any

Recursively converts all values in an object to hex strings

deepHexlify
,
function resolveProperties<T>(object: Deferrable<T>): Promise<T>

Await all of the properties of a Deferrable object

resolveProperties
,
class LocalAccountSigner<T extends HDAccount | PrivateKeyAccount | LocalAccount>

Represents a local account signer and provides methods to sign messages and transactions, as well as static methods to create the signer from mnemonic or private key.

LocalAccountSigner
,
} from "@aa-sdk/core"; import {
function createClient<transport extends Transport, chain extends Chain | undefined = undefined, accountOrAddress extends Account | Address | undefined = undefined, rpcSchema extends RpcSchema | undefined = undefined>(parameters: ClientConfig<transport, chain, accountOrAddress, rpcSchema>): Prettify<Client<transport, chain, accountOrAddress extends Address ? Prettify<JsonRpcAccount<accountOrAddress>> : accountOrAddress, rpcSchema>>
createClient
,
function http<rpcSchema extends RpcSchema | undefined = undefined, raw extends boolean = false>(url?: string | undefined, config?: HttpTransportConfig<rpcSchema, raw>): HttpTransport<rpcSchema, raw>
http
} from "viem";
import {
const sepolia: { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; ... 11 more ...; serializers?: ChainSerializers<...> | undefined; }
sepolia
} from "viem/chains";
const
const signer: LocalAccountSigner<{ address: Address; nonceManager?: NonceManager | undefined; sign: (parameters: { hash: Hash; }) => Promise<Hex>; ... 6 more ...; type: "local"; }>
signer
=
class LocalAccountSigner<T extends HDAccount | PrivateKeyAccount | LocalAccount>

Represents a local account signer and provides methods to sign messages and transactions, as well as static methods to create the signer from mnemonic or private key.

LocalAccountSigner
.
LocalAccountSigner<T extends HDAccount | PrivateKeyAccount | LocalAccount>.generatePrivateKeySigner(): LocalAccountSigner<PrivateKeyAccount>

Generates a new private key and creates a LocalAccountSigner for a PrivateKeyAccount.

generatePrivateKeySigner
();
const
const chain: { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; ... 11 more ...; serializers?: ChainSerializers<...> | undefined; }
chain
=
const sepolia: { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; ... 11 more ...; serializers?: ChainSerializers<...> | undefined; }
sepolia
;
const
const stackupClient: { account: undefined; batch?: { multicall?: boolean | Prettify<MulticallBatchOptions> | undefined; } | undefined; ... 10 more ...; extend: <const client extends { ...; } & ExactPartial<...>>(fn: (client: Client<...>) => client) => Client<...>; }
stackupClient
=
createClient<HttpTransport<undefined, false>, undefined, undefined, undefined>(parameters: ClientConfig<HttpTransport<undefined, false>, undefined, undefined, undefined>): { ...; }
createClient
({
// TODO: Replace with your stackup API key here (https://docs.stackup.sh/docs/paymaster-api)
transport: HttpTransport<undefined, false>

The RPC transport

transport
:
http<undefined, false>(url?: string | undefined, config?: HttpTransportConfig<undefined, false> | undefined): HttpTransport<undefined, false>
http
("https://api.stackup.sh/v1/paymaster/STACKUP_API_KEY"),
}); const
const alchemyTransport: HttpTransport<undefined, false>
alchemyTransport
=
http<undefined, false>(url?: string | undefined, config?: HttpTransportConfig<undefined, false> | undefined): HttpTransport<undefined, false>
http
("ALCHEMY_RPC_URL");
const
const alchemyClient: { account: MultiOwnerModularAccount<LocalAccountSigner<{ address: Address; nonceManager?: NonceManager | undefined; sign: (parameters: { hash: Hash; }) => Promise<Hex>; ... 6 more ...; type: "local"; }>>; ... 99 more ...; extend: <const client extends { ...; } & ExactPartial<...>>(fn: (client: Client<...>) => client) => Client<...>; }
alchemyClient
= await
createMultiOwnerModularAccountClient<HttpTransport<[{ Method: "web3_clientVersion"; Parameters?: undefined; ReturnType: string; }, { Method: "web3_sha3"; Parameters: [data: Hash]; ReturnType: string; }, { Method: "net_listening"; Parameters?: undefined; ReturnType: boolean; }, ... 43 more ..., { ...; }], false>, Chain | undefined, LocalAccountSigner<...>>(args: CreateMultiOwnerModularAccountClientParams<...>): Promise<...> (+1 overload)
createMultiOwnerModularAccountClient
({
chain: { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; ... 11 more ...; serializers?: ChainSerializers<...> | undefined; }
chain
,
signer: LocalAccountSigner<{ address: Address; nonceManager?: NonceManager | undefined; sign: (parameters: { hash: Hash; }) => Promise<Hex>; ... 6 more ...; type: "local"; }>
signer
,
transport: HttpTransport<[{ Method: "web3_clientVersion"; Parameters?: undefined; ReturnType: string; }, { Method: "web3_sha3"; Parameters: [data: Hash]; ReturnType: string; }, { Method: "net_listening"; Parameters?: undefined; ReturnType: boolean; }, ... 43 more ..., { ...; }], false>
transport
:
http<[{ Method: "web3_clientVersion"; Parameters?: undefined; ReturnType: string; }, { Method: "web3_sha3"; Parameters: [data: Hash]; ReturnType: string; }, { Method: "net_listening"; Parameters?: undefined; ReturnType: boolean; }, ... 43 more ..., { ...; }], false>(url?: string | undefined, config?: HttpTransportConfig<...> | undefined): HttpTransport<...>
http
("ALCHEMY_RPC_URL"),
// Bypasses alchemy gas estimation and instead uses Stackup for gas estimation
gasEstimator: <TAccount extends SmartContractAccount, C extends MiddlewareClient, TEntryPointVersion extends GetEntryPointFromAccount<TAccount, SmartContractAccount<string, keyof EntryPointRegistryBase<unknown>>> = GetEntryPointFromAccount<...>>(userOp: Deferrable<...>) => Promise<...>
gasEstimator
: async (
userOp: Deferrable<UserOperationStruct<TEntryPointVersion>>
userOp
) => ({
...
userOp: Deferrable<UserOperationStruct<TEntryPointVersion>>
userOp
,
callGasLimit: string
callGasLimit
: "0x0",
preVerificationGas: string
preVerificationGas
: "0x0",
verificationGasLimit: string
verificationGasLimit
: "0x0",
}), // Uses alchemy fee estimation to comply with bundler
feeEstimator: ClientMiddlewareFn
feeEstimator
:
function alchemyFeeEstimator(transport: AlchemyTransport): ClientMiddlewareFn

Function that estimates the transaction fees using Alchemy methods for a given client. It fetches the latest block and estimates the max priority fee per gas, applying any overrides or fee options provided.

alchemyFeeEstimator
(
const alchemyTransport: HttpTransport<undefined, false>
alchemyTransport
),
paymasterAndData?: ClientMiddlewareFn<UserOperationContext | undefined> | undefined
paymasterAndData
: async (
userop: any
userop
,
opts: any
opts
) => {
const
const pmResponse: any
pmResponse
: any = await
const stackupClient: { account: undefined; batch?: { multicall?: boolean | Prettify<MulticallBatchOptions> | undefined; } | undefined; ... 10 more ...; extend: <const client extends { ...; } & ExactPartial<...>>(fn: (client: Client<...>) => client) => Client<...>; }
stackupClient
.
request: <undefined, { method: "web3_clientVersion"; params?: undefined | undefined; } | { method: "web3_sha3"; params: [data: `0x${string}`]; } | { method: "net_listening"; params?: undefined | undefined; } | { method: "net_peerCount"; params?: undefined | undefined; } | ... 71 more ... | { ...; }, string | ... 26 more ... | null>(args: { method: "web3_clientVersion"; params?: undefined | undefined; } | ... 74 more ... | { ...; }, options?: EIP1193RequestOptions | undefined) => Promise<...>

Request function wrapped with friendly error handling

request
({
// @ts-ignore
method: "pm_sponsorUserOperation"
method
: "pm_sponsorUserOperation",
params: [any, any, { type: string; }]
params
: [
function deepHexlify(obj: any): any

Recursively converts all values in an object to hex strings

deepHexlify
(await
resolveProperties<unknown>(object: Deferrable<unknown>): Promise<unknown>

Await all of the properties of a Deferrable object

resolveProperties
(
userop: any
userop
)),
opts: any
opts
.
any
account
.
any
getEntryPoint
().
any
address
,
{ // @ts-ignore
type: string
type
: "payg", // Replace with ERC20 context based on stackups documentation
}, ], }); return { ...
userop: any
userop
,
...
const pmResponse: any
pmResponse
,
}; }, });