Documentation Index
Fetch the complete documentation index at: https://docs.dynamic.xyz/docs/llms.txt
Use this file to discover all available pages before exploring further.
Checks if a user operation can be sponsored by the configured paymaster. Works for both single transactions and batch transactions. This is useful to determine if the user will need to pay gas fees or if the operation qualifies for gas sponsorship.
Usage
import { canSponsorUserOperation } from "@dynamic-labs-sdk/zerodev";
import { isEvmWalletAccount } from "@dynamic-labs-sdk/evm";
import { getPrimaryWalletAccount } from "@dynamic-labs-sdk/client";
import { parseEther } from "viem";
const walletAccount = getPrimaryWalletAccount();
if (walletAccount && isEvmWalletAccount(walletAccount)) {
const canSponsor = await canSponsorUserOperation({
walletAccount,
calls: [
{
to: recipientAddress,
value: parseEther("0.01"),
data: "0x",
},
],
});
if (canSponsor) {
console.log("Operation will be sponsored - no gas fees required!");
} else {
console.log("Operation cannot be sponsored - user pays gas fees");
}
}
Parameters
You must provide either a walletAccount or a kernelClient, but not both.
| Parameter | Type | Description |
|---|
calls | BatchCall[] | Array of calls to execute (single or multiple) |
calls[].to | Hex | The recipient address for this call |
calls[].value | bigint | The value to send in wei for this call |
calls[].data | Hex (optional) | The transaction data for this call |
walletAccount | EvmWalletAccount (optional) | The wallet account. Required if no kernelClient is provided |
kernelClient | KernelClient (optional) | An existing kernel client. Required if no walletAccount is provided |
Returns
Promise<boolean> - Returns true if the user operation can be sponsored, false otherwise.
Examples
Single transaction with wallet account
const canSponsor = await canSponsorUserOperation({
walletAccount,
calls: [
{
to: "0x...",
value: parseEther("0.1"),
},
],
});
Batch transaction
const canSponsor = await canSponsorUserOperation({
walletAccount,
calls: [
{ to: "0xRecipient1...", value: parseEther("0.1") },
{ to: "0xRecipient2...", value: parseEther("0.2") },
{ to: "0xRecipient3...", value: parseEther("0.3") },
],
});
Using existing kernel client
const kernelClient = await createKernelClientForWalletAccount({
smartWalletAccount: walletAccount,
});
const canSponsor = await canSponsorUserOperation({
kernelClient,
calls: [
{
to: "0x...",
value: parseEther("0.1"),
},
],
});
Error handling
import { isGasSponsorshipError } from '@dynamic-labs-sdk/zerodev';
try {
const canSponsor = await canSponsorUserOperation({ walletAccount, calls });
console.log('Can sponsor:', canSponsor);
} catch (error) {
if (isGasSponsorshipError(error)) {
console.log('Sponsorship check failed - user will need to pay gas');
}
}
React
Use canSponsorUserOperation inside a button handler to conditionally show a “gasless” badge or adjust UI before sending:
import { canSponsorUserOperation, sendUserOperation } from '@dynamic-labs-sdk/zerodev';
import { isEvmWalletAccount } from '@dynamic-labs-sdk/evm';
import { useWalletAccounts } from '@dynamic-labs-sdk/react-hooks';
import { useState } from 'react';
import { parseEther } from 'viem';
function SponsoredSendButton({ recipientAddress }) {
const walletAccounts = useWalletAccounts();
const walletAccount = walletAccounts.find(isEvmWalletAccount);
const [sponsored, setSponsored] = useState(null);
const calls = [{ to: recipientAddress, value: parseEther('0.01'), data: '0x' as const }];
const handleSend = async () => {
if (!walletAccount) return;
const canSponsor = await canSponsorUserOperation({ walletAccount, calls });
setSponsored(canSponsor);
await sendUserOperation({ walletAccount, calls, withSponsorship: canSponsor });
};
return (
<div>
<button onClick={handleSend} disabled={!walletAccount}>
Send {sponsored === true ? '(Gasless)' : ''}
</button>
</div>
);
}