Overview
Transferring Solana Program Library (SPL) Tokens is essential for various blockchain operations, including airdrops, NFT distributions, and managing token flows between accounts. Unlike SOL transfers, SPL token transactions require understanding mint addresses and associated token accounts (ATAs).
What You Will Do
This guide demonstrates how to:
- Transfer SPL tokens between wallets on Solana’s devnet using TypeScript.
- Derive associated token accounts (ATAs).
- Handle token decimals for accurate transfers.
What You Will Need
- Node.js (v20+)
- TypeScript & ts-node
- Basic blockchain development knowledge
SPL Token Accounts Explained
Mint IDs
Every SPL token has a unique Mint ID (e.g., USDC: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v). NFTs also have distinct mint addresses.
Associated Token Accounts (ATAs)
ATAs link a wallet to a specific token mint. Transfers must occur between ATAs of the same mint. For example:
- Valid Transfer: USDC → USDC ATA.
- Invalid Transfer: USDC → SAMO ATA.
Project Setup
Initialize Your Project
mkdir spl-transfer-guide
cd spl-transfer-guide
npm init --yesInstall Dependencies
npm install @solana/web3.js @solana/spl-tokenConfigure TypeScript
Add tsconfig.json:
{
"compilerOptions": {
"module": "NodeNext",
"moduleResolution": "NodeNext",
"target": "ESNext"
}
}Core Script: Transfer SPL Tokens
1. Import Libraries
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
import { getOrCreateAssociatedTokenAccount, transfer } from '@solana/spl-token';2. Set Up RPC Connection
const QUICKNODE_RPC = 'https://example.solana-devnet.quiknode.pro/'; // Replace with your endpoint
const connection = new Connection(QUICKNODE_RPC);3. Declare Variables
const FROM_WALLET = Keypair.fromSecretKey(Uint8Array.from([...])); // Replace with your keypair
const DESTINATION_WALLET = new PublicKey('DemoKMZWkk483hX4mUrcJoo3zVvsKhm8XXs28TuwZw9H');
const MINT_ADDRESS = new PublicKey('YourTokenMintAddressHere');
const TRANSFER_AMOUNT = 1; // Tokens to send4. Fetch Decimals
async function getDecimals(mint: PublicKey): Promise<number> {
const info = await connection.getParsedAccountInfo(mint);
return info.value?.data.parsed.info.decimals || 0;
}5. Execute Transfer
async function sendSPLToken() {
const decimals = await getDecimals(MINT_ADDRESS);
const amount = TRANSFER_AMOUNT * 10 ** decimals;
// Get or create ATAs
const fromATA = await getOrCreateAssociatedTokenAccount(
connection,
FROM_WALLET,
MINT_ADDRESS,
FROM_WALLET.publicKey
);
const toATA = await getOrCreateAssociatedTokenAccount(
connection,
FROM_WALLET,
MINT_ADDRESS,
DESTINATION_WALLET
);
// Transfer
const tx = await transfer(
connection,
FROM_WALLET,
fromATA.address,
toATA.address,
FROM_WALLET.publicKey,
amount
);
console.log(`Transaction successful: https://explorer.solana.com/tx/${tx}?cluster=devnet`);
}FAQ
Q1: How do I find my SPL token’s mint address?
A: Check your wallet on Solana Explorer under the "Tokens" tab.
Q2: Why does the destination ATA need to be created?
A: An ATA must exist to hold tokens. The getOrCreateAssociatedTokenAccount function handles this automatically.
Q3: Can I transfer fractional tokens?
A: Yes! Adjust the TRANSFER_AMOUNT and factor in decimals (e.g., 0.5 * 10**decimals).
Next Steps
- Bulk Transfers: Adapt this script for multiple recipients.
- NFTs: Modify the code to transfer NFTs (1 token per mint).
👉 Explore advanced Solana guides
Tip: Always test on devnet before mainnet. Happy building! 🚀