WDK logoWDK documentation

Transfer Tokens

Transfer ERC-20 tokens with gasless transactions.

This guide explains how to transfer ERC-20 tokens, estimate transfer fees, set a maximum fee limit, select a nonce lane, and apply UserOperation gas overrides.

Transfer ERC-20 Tokens

You can transfer ERC-20 tokens using gasless transactions with account.transfer():

Transfer ERC-20 Tokens
const result = await account.transfer({
  token: '0xdAC17F958D2ee523a2206206994597C13D831ec7', // USDT
  recipient: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
  amount: 1000000 // 1 USDT (6 decimals)
})
console.log('Transfer UserOperation hash:', result.hash)
console.log('Transfer fee:', result.fee)

Estimate Transfer Fees

You can estimate the fee for a token transfer without executing it using account.quoteTransfer():

Estimate Transfer Fee
const quote = await account.quoteTransfer({
  token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
  recipient: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
  amount: 1000000
})
console.log('Estimated transfer fee:', quote.fee)

Transfer with Maximum Fee Limit

You can set a maximum fee for a specific transfer by passing a transferMaxFee in the config object to account.transfer():

Transfer with Fee Limit
const result = await account.transfer({
  token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
  recipient: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
  amount: 1000000
}, {
  transferMaxFee: 100000
})

If the estimated fee meets or exceeds transferMaxFee, the transfer is cancelled with an "Exceeded maximum fee" error.

Transfer in a Nonce Lane

transfer() follows the same beta.14 nonce-lane rules as sends. Use a stable named lane for an independent transfer stream, and wait for inclusion before reusing that lane:

Transfer In A Named Lane
const result = await account.transfer({
  token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
  recipient: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
  amount: 1000000
}, {
  nonceKey: 'token-payouts'
})

quoteTransfer() estimates the transfer but does not select or reserve a lane. A lane transfer rebuilds its UserOperation. The beta.14 runtime accepts lane fields per call, while the published per-call TypeScript declaration omits them; see Use Parallel Nonce Lanes.

Transfer with UserOperation Gas Overrides

Use the third argument to pass UserOperation gas or EIP-1559 fee overrides through transfer() or quoteTransfer(). Set maxFeePerGas and maxPriorityFeePerGas together.

Transfer with Gas Overrides
const txOverrides = {
  callGasLimit: 90000n,
  verificationGasLimit: 120000n,
  maxFeePerGas: 30000000000n,
  maxPriorityFeePerGas: 2000000000n
}

const quote = await account.quoteTransfer({
  token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
  recipient: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
  amount: 1000000
}, undefined, txOverrides)

const result = await account.transfer({
  token: '0xdAC17F958D2ee523a2206206994597C13D831ec7',
  recipient: '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6',
  amount: 1000000
}, undefined, txOverrides)

Next Steps

Learn how to sign and verify messages.

On this page