How to conditionally sponsor a user operation | Pimlico Docs
Skip to content

How to conditionally sponsor a user operation

With permissionless.js and Viem, you can conditionally sponsor a user operation. This can be useful in situations like:

  • Sponsor only first 10 transactions
  • Sponsor if they have a specific NFT

Let's take an example where you want to sponsor only the first 10 transactions.

Create the clients

First we must create the public, (optionally) pimlico paymaster clients that will be used to interact with the SimpleAccount.

import { createPublicClient, Hex, http, zeroAddress } from "viem"
import { decodeNonce } from "permissionless/utils"
import { createPimlicoClient } from "permissionless/clients/pimlico"
import { entryPoint07Address } from "viem/account-abstraction"
 
const publicClient = createPublicClient({
	chain: sepolia,
	transport: http("https://sepolia.rpc.thirdweb.com"),
})
 
const pimlicoUrl = `https://api.pimlico.io/v2/sepolia/rpc?apikey=${apiKey}`
 
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.

import { toSimpleSmartAccount } from "permissionless/accounts"
import { generatePrivateKey, privateKeyToAccount } from "viem/accounts"
 
export const simpleSmartAccount = await toSimpleSmartAccount({
	client: publicClient,
	owner: privateKeyToAccount(generatePrivateKey()),
	entryPoint: {
		address: entryPoint07Address,
		version: "0.7",
	},
})

Create the smart account client with the custom paymaster logic

We can sponsor a user operation conditionally by setting the paymaster field in sendTransaction only when the sponsorship conditions are met.

import { sepolia } from "viem/chains"
import { createSmartAccountClient } from "permissionless"
import { getAccountNonce } from "permissionless/actions"
 
const smartAccountClient = createSmartAccountClient({
	client: publicClient,
	account: simpleSmartAccount,
	chain: sepolia,
	bundlerTransport: http(pimlicoUrl),
	userOperation: {
		estimateFeesPerGas: async () => {
			return (await pimlicoClient.getUserOperationGasPrice()).fast
		},
	},
})
 
// Only sponsor userOps with nonce sequence < 10
const nonce = await getAccountNonce(publicClient, {
	address: simpleSmartAccount.address,
	entryPointAddress: entryPoint07Address,
})
const { sequence } = decodeNonce(nonce)
 
let txHash: Hex
if (sequence < 10) {
    txHash = await smartAccountClient.sendTransaction({
    	calls: [
    		{
    			to: zeroAddress,
    			value: 0n,
    			data: "0x",
    		},
    	],
    	paymaster: pimlicoClient 
    });
} else {
	txHash = await smartAccountClient.sendTransaction({
		calls: [
			{
				to: zeroAddress,
				value: 0n,
				data: "0x",
			},
		]
	});
}