WDK logoWDK documentation
SolanaStandard SolanaGuides

Transfer SPL Tokens

Transfer SPL tokens and estimate transfer fees on Solana.

This guide explains how to transfer SPL tokens, estimate fees, add a memo, and validate a transfer. These methods support the original SPL Token program; Token-2022 mints remain unsupported.

Transfer Tokens

Use account.transfer() to send SPL tokens to a recipient address. If the recipient does not have a token account, one is created automatically.

Transfer SPL Tokens
const transferResult = await account.transfer({
  token: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB', // USDt mint address
  recipient: 'publicKey', // Recipient's base58-encoded public key
  amount: 1000000n // Amount in token's base units (6 decimals for USDt)
})
console.log('Transfer hash:', transferResult.hash)
console.log('Transfer fee:', transferResult.fee, 'lamports')

Estimate Transfer Fees

Use account.quoteTransfer() to get a fee estimate before executing the transfer.

Quote Token Transfer
const transferQuote = await account.quoteTransfer({
  token: 'Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB',
  recipient: 'publicKey',
  amount: 1000000n
})
console.log('Transfer fee estimate:', transferQuote.fee, 'lamports')

Add a Memo (optional)

Pass { memo } as the second argument to quoteTransfer() and transfer(). The memo is a public, on-chain payment reference; keep secrets and personal data out of it.

  1. Prepare the same transfer fields and memo for both calls.
  2. Inspect the quote before sending; configure transferMaxFee to enforce a fee cap during execution.
  3. Submit the transfer with the same memo.

You can quote and send a transfer using your reviewed mint, recipient, and amount:

Attach an SPL transfer memo
const transferOptions = { token: splTokenMint, recipient, amount }
const solanaOptions = { memo: 'Invoice 1042' }
const quote = await account.quoteTransfer(transferOptions, solanaOptions)
console.log('Estimated fee:', quote.fee, 'lamports')

const result = await account.transfer(transferOptions, solanaOptions)
console.log('Transfer hash:', result.hash)

The memo must be a string; an empty string adds no memo instruction. Both calls throw ValueError for a non-string memo or a memo that makes the transaction exceed Solana's transaction-size limit. The limit applies to the complete transaction, so there is no fixed character allowance. The second argument applies to SPL transfers, not native SOL sends. This feature does not enable Token-2022 memo-transfer extensions.

Transfer with Validation

You can validate addresses and check balances before transferring to catch errors early.

1. Validate Addresses

Address Validation
if (typeof splTokenMint !== 'string' || splTokenMint.length < 32) {
  throw new Error('Invalid SPL token mint address')
}

if (typeof recipient !== 'string' || recipient.length < 32) {
  throw new Error('Invalid recipient address')
}

2. Check Balance

Use account.getTokenBalance() to verify sufficient funds:

Balance Check
const balance = await account.getTokenBalance(splTokenMint)
if (balance < amount) {
  throw new Error('Insufficient SPL token balance')
}

3. Quote and Execute Transfer

Use account.quoteTransfer() to estimate fees, then account.transfer() to execute:

Quote and Execute
const quote = await account.quoteTransfer({
  token: splTokenMint,
  recipient,
  amount
})
console.log('Transfer fee estimate:', quote.fee, 'lamports')

const result = await account.transfer({
  token: splTokenMint,
  recipient,
  amount
})
console.log('Transfer hash:', result.hash)
console.log('Actual fee:', result.fee, 'lamports')

Next Steps

Learn how to sign and verify messages with your Solana account.

On this page