How to use a custom paymaster with accounts in permissionless.js
permissionless.js allows you to define custom logic to select the paymaster (if any) to use with the accounts you control. This allows you to use your own paymaster or even use multiple paymasters in different scenarios.
Create the clients
First we must create the public, (optionally) pimlico paymaster clients that will be used to interact with the SimpleAccount.
export const publicClient = createPublicClient({
chain: sepolia,
transport: http("https://rpc.ankr.com/eth_sepolia"),
})
const pimlicoUrl = `https://api.pimlico.io/v2/sepolia/rpc?apikey=${apiKey}`
export const pimlicoClient = createPimlicoClient({
transport: http(pimlicoUrl),
entryPoint: {
address: entryPoint07Address,
version: "0.7",
},
})
Create an account
Now, create an account. This can any of the accounts supported by permissionless.js or custom accounts conforming to the interface. For this example, we'll use a Simple account.
const simpleAccount = await toSimpleSmartAccount({
client: publicClient,
owner: privateKeyToAccount(privateKey),
entryPoint: {
address: entryPoint07Address,
version: "0.7",
}
})
Create the smart account client with the custom paymaster logic
When creating the smartAccountClient
, we can pass in a sponsorUserOperation
function that will be called before a user operation is signed and sent. This function must return the paymasterAndData
, preVerificationGas
, verificationGasLimit
, and callGasLimit
fields.
const smartAccountClient = createSmartAccountClient({
account,
chain: sepolia,
bundlerTransport: http(pimlicoUrl),
paymaster: pimlicoClient,
userOperation: {
estimateFeesPerGas: async () => {
return (await pimlicoClient.getUserOperationGasPrice()).fast
},
}
})
Send a transaction
You can now send transactions as normal. The sponsorUserOperation
function will be called before each transaction is signed and sent, applying the custom paymaster logic you have set.
const txHash = await smartAccountClient.sendTransaction({
to: "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
value: parseEther("0.1")
});