AVAX Examples
Copy-paste integration snippets for real AVAX ERC-4337 flows.
Example 1 — Backend submit (minimal)
Server-side flow with
sk_nogas_*.backend-minimal.ts
TypeScript
1import { createSmoothSendAvaxClient } from '@smoothsend/sdk/avax';2 3const avax = createSmoothSendAvaxClient({4 apiKey: process.env.SMOOTHSEND_API_KEY!, // sk_nogas_*5 network: 'testnet',6});7 8const result = await avax.submitCall({9 to: '0x0000000000000000000000000000000000000001',10 data: '0x',11 value: 0n,12 mode: 'developer-sponsored',13 smartAccountAddress: '0xYourSmartAccount',14 waitForReceipt: false,15});16 17console.log('userOpHash:', result.userOpHash);Example 2 — React sponsored call (wagmi)
Frontend wallet flow with
pk_nogas_*.SponsoredTransferButton.tsx
TypeScript (React)
1import { SmoothSendAvaxProvider, useSmoothSendAvax } from '@smoothsend/sdk/avax';2import { usePublicClient, useWalletClient } from 'wagmi';3 4function SponsoredTransferButton(props: { to: `0x${string}`; data: `0x${string}` }) {5 const publicClient = usePublicClient();6 const { data: walletClient } = useWalletClient();7 const { submitCall } = useSmoothSendAvax({8 publicClient,9 walletClient: walletClient ?? undefined,10 });11 12 return (13 <button14 onClick={() =>15 submitCall({16 to: props.to,17 data: props.data,18 mode: 'developer-sponsored',19 })20 }21 >22 Submit sponsored call23 </button>24 );25}26 27export function Root({ children }: { children: React.ReactNode }) {28 return (29 <SmoothSendAvaxProvider30 apiKey={process.env.NEXT_PUBLIC_SMOOTHSEND_API_KEY!}31 network="testnet"32 smartAccountAddress={'0xYourSmartAccount' as `0x${string}`}33 >34 {children}35 </SmoothSendAvaxProvider>36 );37}Example 3 — Atomic approve + transfer (user pays in USDC)
The user pays gas in USDC. An ERC20 approval and the actual transfer are bundled into a single UserOperation — one signature, zero AVAX required. This is the recommended pattern for the
user-pays-erc20 mode.AtomicUSDCTransfer.tsx
TypeScript (React)
1import { useSmoothSendAvax, fetchAvaxAaPublicDefaults } from '@smoothsend/sdk/avax';2import { encodeFunctionData, parseUnits } from 'viem';3import { usePublicClient, useWalletClient } from 'wagmi';4 5const ERC20_ABI = [6 {7 name: 'approve', type: 'function', stateMutability: 'nonpayable',8 inputs: [{ name: 'spender', type: 'address' }, { name: 'amount', type: 'uint256' }],9 outputs: [{ type: 'bool' }],10 },11 {12 name: 'transfer', type: 'function', stateMutability: 'nonpayable',13 inputs: [{ name: 'to', type: 'address' }, { name: 'amount', type: 'uint256' }],14 outputs: [{ type: 'bool' }],15 },16] as const;17 18// Fuji testnet address for USDC — swap for mainnet when ready19const USDC = '0x5425890298aed601595a70AB815c96711a31Bc65';20 21export function AtomicUSDCTransfer({ recipient }: { recipient: `0x${string}` }) {22 const publicClient = usePublicClient();23 const { data: walletClient } = useWalletClient();24 const { submitSponsoredUserOp } = useSmoothSendAvax({25 publicClient,26 walletClient: walletClient ?? undefined,27 });28 29 const handleSend = async () => {30 // 1. Fetch the correct paymaster address from SmoothSend dynamically31 const { paymasterFuji } = await fetchAvaxAaPublicDefaults();32 if (!paymasterFuji) throw new Error('Paymaster not found');33 34 const amount = parseUnits('1', 6); // 1 USDC35 36 // Step 1 in batch: approve the paymaster to collect USDC for gas37 const approveData = encodeFunctionData({38 abi: ERC20_ABI,39 functionName: 'approve',40 args: [paymasterFuji, parseUnits('1000', 6)],41 });42 43 // Step 2 in batch: transfer USDC to the recipient44 const transferData = encodeFunctionData({45 abi: ERC20_ABI,46 functionName: 'transfer',47 args: [recipient, amount],48 });49 50 // Both calls go in one UserOperation — executeBatch(dest[], value[], func[])51 const result = await submitSponsoredUserOp({52 calls: [53 { to: USDC, data: approveData, value: 0n },54 { to: USDC, data: transferData, value: 0n },55 ],56 sponsorshipMode: 'user-pays-erc20',57 paymaster: { token: USDC },58 });59 60 console.log('UserOp hash:', result.userOpHash);61 };62 63 return <button onClick={handleSend}>Send 1 USDC (gasless)</button>;64}The SDK calls encodeAvaxExecuteBatchCalldata internally, producing a single executeBatch calldata. By using fetchAvaxAaPublicDefaults(), you ensure the correct Paymaster address is always used for the approval step.