A transfer refers to sending tokens from one account to another on a blockchain network.
Token transfers are supported on EVM Accounts, EVM Smart Accounts and Solana Accounts.
EVM Accounts can transfer native ETH or ERC-20 tokens, and Solana Accounts can transfer native SOL or SPL tokens.
A complete, runnable example can be found below. In the code below, we:
Create two EVM EOAs
Transfer ETH from one EOA to another
Wait for the transfer to be confirmed
Create a Smart Account
Transfer ETH from the Smart Account to an EOA
Wait for the transfer to be confirmed
Create two Solana Accounts
Transfer SOL from one Solana Account to another
Wait for the transfer to be confirmed
Copy
Ask AI
import { CdpClient } from '@coinbase/cdp-sdk';import { parseEther, createPublicClient, http } from 'viem';import { baseSepolia } from 'viem/chains';import { Connection } from '@solana/web3.js';const publicClient = createPublicClient({chain: baseSepolia,transport: http(),});const connection = new Connection("https://api.devnet.solana.com");async function sendTransferWithEVMAccount(cdp: CdpClient): Promise<void> {console.log("\n=== EOA Example ===");const sender = await cdp.evm.getOrCreateAccount({ name: "Sender" });const receiver = await cdp.evm.getOrCreateAccount({ name: "Receiver" });console.log(`Transferring 0.00001 ETH from ${sender.address} to ${receiver.address}...`);const { transactionHash } = await sender.transfer({to: receiver,amount: parseEther("0.00001"),token: "eth",network: "base-sepolia"});const receipt = await publicClient.waitForTransactionReceipt({hash: transactionHash,});console.log(`Transfer status: ${receipt.status}`);console.log(`Explorer link: https://sepolia.basescan.org/tx/${receipt.transactionHash}`);}async function sendTransferWithSmartAccount(cdp: CdpClient): Promise<void> {console.log("\n=== Smart Account Example ===");const sender = await cdp.evm.createSmartAccount({owner: await cdp.evm.getOrCreateAccount({ name: "Owner" })});const receiver = await cdp.evm.getOrCreateAccount({ name: "Receiver" });console.log(`Transferring 0.00001 ETH from ${sender.address} to ${receiver.address}...`);const { userOpHash } = await sender.transfer({to: receiver,amount: parseEther("0.00001"),token: "eth",network: "base-sepolia"});const receipt = await sender.waitForUserOperation({userOpHash,});console.log(`Transfer status: ${receipt.status}`);console.log(`Explorer link: https://sepolia.basescan.org/tx/${transactionHash}`);}async function sendTransferWithSolanaAccount(cdp: CdpClient): Promise<void> {console.log("\n=== Solana Account Example ===");const sender = await cdp.solana.getOrCreateAccount({ name: "Sender" });const receiver = await cdp.solana.getOrCreateAccount({ name: "Receiver" });console.log(`Transferring 0.0001 SOL from ${sender.address} to ${receiver.address}...`);const { signature } = await sender.transfer({to: receiver,amount: 0.0001 * LAMPORTS_PER_SOL,token: "sol",network: "devnet",});const { blockhash, lastValidBlockHeight } =await connection.getLatestBlockhash();const confirmation = await connection.confirmTransaction({ signature, blockhash, lastValidBlockHeight,},"confirmed");if (confirmation.value.err) {console.log(`Something went wrong! Error: ${confirmation.value.err.toString()}`);} else {console.log( `Transaction confirmed: Link: https://explorer.solana.com/tx/${signature}?cluster=devnet`);}}async function main(): Promise<void> {const cdp = new CdpClient();try {await sendTransferWithEVMAccount(cdp);await sendTransferWithSmartAccount(cdp);await sendTransferWithSolanaAccount(cdp);} catch (error) {console.error('Error:', error);}}if (require.main === module) {main().catch(console.error);}
After running the complete example, you should see the following:
Copy
Ask AI
=== EOA Example ===Transferring 0.00001 ETH from 0x689c59617D8Ec93a114E2304cC038bB8678775C7 to 0xe4026d8D0fA814379042f1E245096F0551931d14...Transfer status: successExplorer link: https://sepolia.basescan.org/tx/0xdaa53830fb62f407dfe65c6e10bac6c9af1fb2014551d107f7d9de2055914985=== Smart Account Example ===Transferring 0.00001 ETH from 0xC3c2D7879B31Aca4e26D16AD57D07422E4a23A67 to 0xe4026d8D0fA814379042f1E245096F0551931d14...Transfer status: completeExplorer link: https://sepolia.basescan.org/tx/0x045e29f40897dc01b50a6ba0d7c3d0a424fbca69792869f56e1321f1a899419f=== Solana Account Example ===Transferring 0.0001 SOL from DYjMQTJCcqmtdMvagJvW17U7teg8caUQ92nSrcXdqSZG to 32gPVc5gDvn2T5EgV81NFavDMpf5HU4oLUbmuipKpV8C...Transaction confirmed! Link: https://explorer.solana.com/tx/4KEPbhkRLTg2FJNqV5bbUd6zv1TNkksxF9PDHw2FodrTha3jq2Cojn4hSKtjPWdrZiRDuYp7okRuc1oYvh3JkLuE?cluster=devnet
In the examples above, we transferred native tokens (eth and sol). Using the transfer method, you can also easily transfer ERC-20 tokens or SPL tokens, like USDC.
The transfer method itself can receive usdc as the value for the token parameter:
Notice the value passed to the amount parameter is specified as 10000 for USDC. This is because USDC has 6 decimal places, so 10000 is equivalent to 0.01 USDC.
To work with more human-readable values, you can use the parseUnits function from viem if using TypeScript, or CDP’s parse_units function if using Python:
Copy
Ask AI
import { parseUnits } from "viem";await sender.transfer({to: receiver,amount: parseUnits("0.01", 6), // equivalent to 10000ntoken: "usdc",network: "base-sepolia"})
The transfer method can also receive an arbitrary token contract address as the value for the token parameter:
Copy
Ask AI
await sender.transfer({to: receiver,amount: parseEther("0.00001"),token: "0x4200000000000000000000000000000000000006", // Contract address of WETH on Base Sepolianetwork: "base-sepolia"})