Send ERC-20 tokens using the embedded wallet by encoding the transfer function call.
Implementation
import { useSendTransaction } from '@moon-key/react-auth/ethereum' ;
import { encodeFunctionData } from 'viem' ;
import { useState } from 'react' ;
const ERC20_ABI = [
{
name: 'transfer' ,
type: 'function' ,
stateMutability: 'nonpayable' ,
inputs: [
{ name: 'to' , type: 'address' },
{ name: 'amount' , type: 'uint256' }
],
outputs: [{ name: '' , type: 'bool' }]
}
] as const ;
export default function SendTokens () {
const { sendTransaction } = useSendTransaction ();
const [ recipient , setRecipient ] = useState ( '' );
const [ amount , setAmount ] = useState ( '' );
const [ tokenAddress , setTokenAddress ] = useState ( '' );
const handleSendTokens = async () => {
try {
// Encode the transfer function call
const data = encodeFunctionData ({
abi: ERC20_ABI ,
functionName: 'transfer' ,
args: [ recipient as `0x ${ string } ` , BigInt ( amount )]
});
// Send the transaction
const txHash = await sendTransaction ({
to: tokenAddress ,
data
});
console . log ( 'Token transfer successful:' , txHash );
} catch ( error ) {
console . error ( 'Token transfer failed:' , error );
}
};
return (
< div >
< h2 > Send ERC-20 Tokens </ h2 >
< input
type = "text"
placeholder = "Token Contract Address"
value = { tokenAddress }
onChange = { ( e ) => setTokenAddress ( e . target . value ) }
/>
< input
type = "text"
placeholder = "Recipient Address"
value = { recipient }
onChange = { ( e ) => setRecipient ( e . target . value ) }
/>
< input
type = "text"
placeholder = "Amount (in smallest unit)"
value = { amount }
onChange = { ( e ) => setAmount ( e . target . value ) }
/>
< button onClick = { handleSendTokens } > Send Tokens </ button >
</ div >
);
}
Key concepts
ERC-20 ABI - Minimal ABI containing only the transfer function
Function encoding - Uses encodeFunctionData from viem to encode the function call
Amount handling - Amount should be in the token’s smallest unit (considering decimals)
Contract interaction - Sends transaction to the token contract address with encoded data
Important notes
The amount should be specified in the token’s smallest unit. For a token with 18 decimals, to send 1 token, you’d specify 1000000000000000000 (1 × 10^18).
Make sure the user has approved your contract to spend tokens if you’re building a dApp that needs to transfer tokens on behalf of users.
Next steps
NFT Minting Learn how to mint NFTs
Multi-Step Flow Handle approve + transfer flows