LiteSVM Docs

Token Testing

Test with SPL tokens using @solana-program/token and LiteSVM

Testing token logic on Solana means setting up mints, token accounts, and authorities before you can test the transfer logic you actually care about. The tokenProgram() plugin from @solana-program/token collapses that setup to a few method calls — and handles ATA creation automatically.

Installation

pnpm add @solana/kit @solana/kit-client-litesvm @solana-program/token
npm install @solana/kit @solana/kit-client-litesvm @solana-program/token
yarn add @solana/kit @solana/kit-client-litesvm @solana-program/token
bun add @solana/kit @solana/kit-client-litesvm @solana-program/token

Create a Mint

import { createClient } from '@solana/kit-client-litesvm';
import { generateKeyPairSigner } from '@solana/kit';
import { tokenProgram } from '@solana-program/token';

const client = (await createClient()).use(tokenProgram());

const mintAuthority = await generateKeyPairSigner();
const newMint = await generateKeyPairSigner();

await client.token.instructions
    .createMint({
        newMint,
        decimals: 9,
        mintAuthority: mintAuthority.address,
    })
    .sendTransaction();

// Verify
const mintAccount = await client.token.accounts.mint.fetch(newMint.address);
console.log(mintAccount.data.supply);  // 0n
console.log(mintAccount.data.decimals); // 9

Mint Tokens

mintToATA issues tokens to an owner's Associated Token Account. If the ATA doesn't exist, it's created in the same transaction.

await client.token.instructions
    .mintToATA({
        mint: newMint.address,
        owner: client.payer.address,
        mintAuthority,
        amount: 1_000_000_000_000n, // 1000 tokens (9 decimals)
        decimals: 9,
    })
    .sendTransaction();

The decimals parameter is a safety check — it must match the mint's decimals exactly, or the Token program rejects the transaction with error 0x24. This prevents accidentally minting 1000x too many tokens.

Transfer Tokens

transferToATA moves tokens between users. The recipient's ATA is created automatically if needed.

const alice = await generateKeyPairSigner();
const bob = await generateKeyPairSigner();

// Mint to Alice
await client.token.instructions
    .mintToATA({
        mint: newMint.address,
        owner: alice.address,
        mintAuthority,
        amount: 1_000_000_000_000n,
        decimals: 9,
    })
    .sendTransaction();

// Transfer 400 tokens from Alice to Bob
await client.token.instructions
    .transferToATA({
        mint: newMint.address,
        authority: alice,
        recipient: bob.address,
        amount: 400_000_000_000n,
        decimals: 9,
    })
    .sendTransaction();

The authority is the signer who owns the source tokens. The plugin derives both source and destination ATAs from their addresses + the mint.

Verifying Balances

To read back token balances, derive the ATA address with findAssociatedTokenPda and fetch the decoded account:

import { findAssociatedTokenPda, TOKEN_PROGRAM_ADDRESS } from '@solana-program/token';

const [aliceAta] = await findAssociatedTokenPda({
    owner: alice.address,
    mint: newMint.address,
    tokenProgram: TOKEN_PROGRAM_ADDRESS,
});

const aliceAccount = await client.token.accounts.token.fetch(aliceAta);
console.log(aliceAccount.data.amount); // 600_000_000_000n
console.log(aliceAccount.data.mint);   // newMint.address
console.log(aliceAccount.data.owner);  // alice.address

Decimals

Token amounts are always in raw units. 1000 tokens with 9 decimals is 1_000_000_000_000n, not 1000n.

// USDC has 6 decimals
const oneUSDC = 10n ** 6n; // 1_000_000n

// SOL has 9 decimals
const oneSOL = 10n ** 9n;  // 1_000_000_000n

Always use BigInt for token amounts. JavaScript's Number loses precision above 2^53.

Plugin Reference

MethodDescription
client.token.instructions.createMint()Create a new SPL token mint
client.token.instructions.mintToATA()Mint tokens to an owner's ATA (creates ATA if needed)
client.token.instructions.transferToATA()Transfer tokens to a recipient's ATA (creates ATA if needed)
client.token.accounts.mint.fetch()Fetch and decode a mint account
client.token.accounts.token.fetch()Fetch and decode a token account

Common Errors

ErrorCauseFix
custom program error: 0x24decimals doesn't match the mintUse the same decimals value you passed to createMint
AccountNotFoundAccount doesn't exist yetEnsure mint is created before minting
InsufficientFundsNot enough lamports for rentAirdrop more SOL to the payer
OwnerMismatchWrong program owns the accountCheck program ID