IntroductionRecipes

Send USDC (or other ERC-20s)

In this recipe you’ll construct an ERC-20 transfer call and submit it through a Smart Account Client. The same pattern works for any ERC-20 token; just swap the token address and number of decimals.

Prefer code? Jump straight to the React or Core tabs below.

Prerequisites

  1. Account Kit integrated in your app (see the React quickstart or Core quickstart).
  2. A connected user with an on-chain smart account.
  3. The USDC contract address for your target chain. For Ethereum mainnet this is 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48.

1. Encode the transfer calldata

1import { encodeFunctionData, parseAbi } from "viem";
2
3const usdcAddress = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
4const recipient = "0xRecipientAddress";
5const amount = 10n * 1_000_000n; // 10 USDC (6 decimals)
6
7const transferCalldata = encodeFunctionData({
8 abi: parseAbi(["function transfer(address,uint256) returns (bool)"]),
9 functionName: "transfer",
10 args: [recipient, amount],
11});

2. Send the transaction

1import {
2 useSmartAccountClient,
3 useSendUserOperation,
4} from "@account-kit/react";
5
6export function SendUsdcButton() {
7 const { client } = useSmartAccountClient({});
8
9 const { sendUserOperation, sendUserOperationResult } = useSendUserOperation({
10 client,
11 waitForTxn: true,
12 onSuccess: () => {
13 console.log("USDC transfer successful!");
14 },
15 onError: (error) => {
16 console.error("USDC transfer failed:", error);
17 },
18 });
19
20 const handleClick = async () => {
21 if (!client) return;
22
23 sendUserOperation({
24 uo: {
25 target: usdcAddress,
26 data: transferCalldata,
27 value: 0n, // no native value for ERC-20 transfers
28 },
29 });
30 };
31
32 return <button onClick={handleClick}>Send USDC</button>;
33}

3. Wait for the transaction to be mined

If you’re using the React hooks with waitForTxn: true, the transaction will automatically be waited for. You can access the transaction hash from sendUserOperationResult:

1const { sendUserOperation, sendUserOperationResult } = useSendUserOperation({
2 client,
3 waitForTxn: true,
4 onSuccess: () => {
5 console.log("Transaction hash:", sendUserOperationResult?.hash);
6 },
7});

Alternatively, you can manually wait for the transaction:

1import { useWaitForUserOperationTransaction } from "@account-kit/react";
2
3const { waitForUserOp } = useWaitForUserOperationTransaction();
4const receipt = await waitForUserOp(userOpHash);

Next steps

  • Parameterize the token address/decimals to support any ERC-20.
  • Batch multiple user operations in one request (e.g. aprrove, transfer, etc).
  • Combine with sponsored gas for a completely gas-less UX.