7.0 KiB
title, description
| title | description |
|---|---|
| SPL Token Program | Kit-compatible @solana-program/token client for mint creation, transfers, ATAs, delegation, burning, and instruction plans. |
SPL Token Program
Solana's standard token program. Defines Mints (token config + supply) and Token Accounts (per-owner balances). For tokens that need extensions, use Token-2022 instead.
If using plugin clients, prefer client.use(tokenProgram()) for a fluent API that auto-derives ATAs and defaults the payer. The low-level instructions below are for manual pipe() transaction building. See overview.md and plugins.md.
Program address: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
import { TOKEN_PROGRAM_ADDRESS } from '@solana-program/token';
Account Types
Mint (82 bytes)
import { fetchMint, fetchMaybeMint, getMintSize } from '@solana-program/token';
const mint = await fetchMint(rpc, mintAddress);
// mint.data.decimals, mint.data.supply, mint.data.mintAuthority, mint.data.freezeAuthority
Token Account (165 bytes)
import { fetchToken, fetchMaybeToken, getTokenSize } from '@solana-program/token';
const token = await fetchToken(rpc, tokenAddress);
// token.data.mint, token.data.owner, token.data.amount
Multisig
import { fetchMultisig } from '@solana-program/token';
const multisig = await fetchMultisig(rpc, multisigAddress);
// multisig.data.m, multisig.data.n, multisig.data.signers
PDA: Associated Token Account
One deterministic token account per owner per mint. Derived from owner + mint + token program — no on-chain lookup needed. Always prefer ATAs for user-facing flows.
import { findAssociatedTokenPda, TOKEN_PROGRAM_ADDRESS } from '@solana-program/token';
const [ata] = await findAssociatedTokenPda({
owner: walletAddress,
mint: mintAddress,
tokenProgram: TOKEN_PROGRAM_ADDRESS,
});
Key Instructions
Initialize Mint
import { getInitializeMintInstruction } from '@solana-program/token';
const ix = getInitializeMintInstruction({
mint: mintKeypair.address,
decimals: 9,
mintAuthority: authority.address,
freezeAuthority: authority.address, // optional
});
Transfer
Prefer getTransferCheckedInstruction — validates mint and decimals on-chain, preventing wrong-token transfers.
import { getTransferInstruction, getTransferCheckedInstruction } from '@solana-program/token';
// Simple transfer
const ix = getTransferInstruction({
source: sourceTokenAccount,
destination: destTokenAccount,
authority: owner,
amount: 1_000_000n,
});
// Checked transfer (validates decimals)
const ix = getTransferCheckedInstruction({
source: sourceTokenAccount,
mint: mintAddress,
destination: destTokenAccount,
authority: owner,
amount: 1_000_000n,
decimals: 9,
});
Mint To
import { getMintToInstruction, getMintToCheckedInstruction } from '@solana-program/token';
const ix = getMintToInstruction({
mint: mintAddress,
token: destinationTokenAccount,
mintAuthority: authority,
amount: 1_000_000_000n,
});
Approve Delegate
import { getApproveInstruction } from '@solana-program/token';
const ix = getApproveInstruction({
source: tokenAccount,
delegate: delegateAddress,
owner: owner,
amount: 500_000n,
});
Burn
import { getBurnInstruction } from '@solana-program/token';
const ix = getBurnInstruction({
account: tokenAccount,
mint: mintAddress,
authority: owner,
amount: 100_000n,
});
Instruction Plans
Handle multi-step operations (e.g., create ATA if needed). Auto-check preconditions and only include necessary instructions — use for user-facing flows. Build a plan with the get*InstructionPlan builders, then execute it through a plugin client that has planning + sending capability via client.sendTransaction(plan) (see plugins.md). For a shorter form, client.use(tokenProgram()) exposes client.token.instructions.createMint(...) / client.token.instructions.mintToATA(...); call .sendTransaction() on the returned plan to submit (e.g. await client.token.instructions.createMint({ newMint, decimals, mintAuthority }).sendTransaction()).
Create Mint
import { getCreateMintInstructionPlan } from '@solana-program/token';
const plan = getCreateMintInstructionPlan({
payer,
newMint: mintKeypair,
decimals: 9,
mintAuthority: authority.address,
});
await client.sendTransaction(plan);
Mint to ATA (Creates ATA if needed)
Use the async builder — it derives the ATA automatically.
import { getMintToATAInstructionPlanAsync } from '@solana-program/token';
const plan = await getMintToATAInstructionPlanAsync({
payer,
owner: recipientAddress,
mint: mintAddress,
mintAuthority: authority,
amount: 1_000_000_000n,
decimals: 9,
});
await client.sendTransaction(plan);
Complete Pattern: Create Token + Mint
import {
pipe, createTransactionMessage, setTransactionMessageFeePayerSigner,
setTransactionMessageLifetimeUsingBlockhash, appendTransactionMessageInstructions,
signTransactionMessageWithSigners, sendAndConfirmTransactionFactory,
assertIsTransactionWithBlockhashLifetime, generateKeyPairSigner, lamports,
} from '@solana/kit';
import {
getInitializeMintInstruction, getMintToInstruction,
getMintSize, TOKEN_PROGRAM_ADDRESS, findAssociatedTokenPda,
getCreateAssociatedTokenInstruction,
} from '@solana-program/token';
import { getCreateAccountInstruction } from '@solana-program/system';
// 1. Generate mint keypair
const mintKeypair = await generateKeyPairSigner();
// 2. Get rent
const mintRent = await rpc.getMinimumBalanceForRentExemption(BigInt(getMintSize())).send();
// 3. Derive ATA
const [ata] = await findAssociatedTokenPda({
owner: recipient.address,
mint: mintKeypair.address,
tokenProgram: TOKEN_PROGRAM_ADDRESS,
});
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
const message = pipe(
createTransactionMessage({ version: 0 }),
m => setTransactionMessageFeePayerSigner(payer, m),
m => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, m),
m => appendTransactionMessageInstructions([
// Create mint account
getCreateAccountInstruction({
payer,
newAccount: mintKeypair,
lamports: lamports(mintRent),
space: getMintSize(),
programAddress: TOKEN_PROGRAM_ADDRESS,
}),
// Initialize mint
getInitializeMintInstruction({
mint: mintKeypair.address,
decimals: 9,
mintAuthority: payer.address,
}),
// Create ATA
getCreateAssociatedTokenInstruction({
payer,
ata,
owner: recipient.address,
mint: mintKeypair.address,
}),
// Mint tokens
getMintToInstruction({
mint: mintKeypair.address,
token: ata,
mintAuthority: payer,
amount: 1_000_000_000n,
}),
], m),
);
const sendAndConfirm = sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions });
const signed = await signTransactionMessageWithSigners(message);
assertIsTransactionWithBlockhashLifetime(signed);
await sendAndConfirm(signed, { commitment: 'confirmed' });