You can sponsor user operations with any paymaster by passing a paymaster option to viem's bundler client. Two approaches:
- Custom paymaster object — supply your own
getPaymasterData/getPaymasterStubDatacallbacks that call your provider's API. - ERC-7677 paymaster — if your provider speaks the ERC-7677 RPC, use viem's
createPaymasterClientdirectly.
import { createBundlerClient } from "viem/account-abstraction";
import { createClient, http } from "viem";
import { privateKeyToAccount, generatePrivateKey } from "viem/accounts";
import { sepolia } from "viem/chains";
import { toLightAccount } from "@alchemy/smart-accounts";
const rpcClient = createClient({ chain: sepolia, transport: http() });
const owner = privateKeyToAccount(generatePrivateKey());
const account = await toLightAccount({
client: rpcClient,
owner,
version: "v2.0.0",
});
const bundlerClient = createBundlerClient({
account,
client: rpcClient,
chain: sepolia,
transport: http("https://your-bundler.example.com"),
paymaster: {
async getPaymasterData(_parameters) {
// Call your third-party paymaster's API here.
return {
paymaster: "0xabc123...",
paymasterData: "0x",
paymasterVerificationGasLimit: 100000n,
paymasterPostOpGasLimit: 50000n,
};
},
async getPaymasterStubData(_parameters) {
// Stub values used during gas estimation; same shape as above.
return {
paymaster: "0xabc123...",
paymasterData: "0x",
paymasterVerificationGasLimit: 100000n,
paymasterPostOpGasLimit: 50000n,
};
},
},
});
const hash = await bundlerClient.sendUserOperation({
calls: [{ to: "0x0000000000000000000000000000000000000000", value: 0n, data: "0x" }],
});import { createBundlerClient, createPaymasterClient } from "viem/account-abstraction";
import { createClient, http } from "viem";
import { privateKeyToAccount, generatePrivateKey } from "viem/accounts";
import { sepolia } from "viem/chains";
import { toLightAccount } from "@alchemy/smart-accounts";
const rpcClient = createClient({ chain: sepolia, transport: http() });
const owner = privateKeyToAccount(generatePrivateKey());
const account = await toLightAccount({
client: rpcClient,
owner,
version: "v2.0.0",
});
const paymasterClient = createPaymasterClient({
transport: http("https://your-erc7677-paymaster.example.com"),
});
const bundlerClient = createBundlerClient({
account,
client: rpcClient,
chain: sepolia,
transport: http("https://your-bundler.example.com"),
paymaster: paymasterClient,
});
const hash = await bundlerClient.sendUserOperation({
calls: [{ to: "0x0000000000000000000000000000000000000000", value: 0n, data: "0x" }],
});