LiteSVM Docs
Additional Cratesanchor-litesvm

Quick Start

Learn how to use anchor-litesvm for testing Anchor programs with simplified syntax

Installation

Make sure you have all the needed dependencies:

cargo add --dev anchor-litesvm litesvm solana-sdk

What is anchor-litesvm?

The anchor-litesvm crate provides a simplified syntax similar to anchor-client but without RPC overhead. It achieves 78% code reduction compared to raw LiteSVM while maintaining type safety with Anchor types.

AnchorContext

  • Production-compatible test context
  • Same API patterns as anchor-client
  • Manages LiteSVM instance, payer, and program
  • Execute instructions without RPC overhead

Program API

  • Fluent instruction building
  • Type-safe account and argument handling
  • Familiar anchor-client syntax

Account Deserialization

  • Fetch and deserialize Anchor accounts
  • Automatic discriminator handling
  • Support for PDAs and custom layouts

Event Parsing

  • Parse events from transaction logs
  • Assert event emission
  • Type-safe event deserialization

Quick Example

Here's a complete example showing the power of anchor-litesvm:

use anchor_litesvm::{AnchorLiteSVM, AnchorContext};
use anchor_lang::prelude::*;
use solana_sdk::{
    native_token::LAMPORTS_PER_SOL,
    signature::Signer,
};

// Your Anchor program's ID
declare_id!("YourProgramId11111111111111111111111111111");

#[test]
fn test_anchor_program() {
    // Build test context with your program
    let ctx: AnchorContext = AnchorLiteSVM::new()
        .deploy_program(id(), include_bytes!("../target/deploy/your_program.so"))
        .build();

    // Create a funded account
    let user = ctx.create_funded_account(10 * LAMPORTS_PER_SOL);

    // Build and execute an instruction using familiar anchor-client syntax
    let ix = ctx.program()
        .accounts(Initialize {
            user: user.pubkey(),
            system_program: solana_sdk::system_program::id(),
        })
        .args(instruction::Initialize {
            name: "test".to_string()
        })
        .instruction()
        .unwrap();

    // Execute the instruction
    ctx.execute_instruction(ix, &[&user]).unwrap();

    // Fetch and deserialize the account
    let account: UserAccount = ctx.get_account(&user_pda).unwrap();
    assert_eq!(account.name, "test");
}

Comparison: Raw LiteSVM vs anchor-litesvm

Before (Raw LiteSVM)

use litesvm::LiteSVM;
use solana_sdk::{
    instruction::{AccountMeta, Instruction},
    message::Message,
    transaction::Transaction,
};

let mut svm = LiteSVM::new();
svm.add_program(program_id, program_bytes);

let payer = Keypair::new();
svm.airdrop(&payer.pubkey(), 10 * LAMPORTS_PER_SOL).unwrap();

// Manually build instruction data with discriminator
let mut data = Vec::new();
data.extend_from_slice(&anchor_lang::idl::DISCRIMINATOR);
data.extend_from_slice(&args.try_to_vec().unwrap());

let accounts = vec![
    AccountMeta::new(user, true),
    AccountMeta::new_readonly(system_program::id(), false),
];

let ix = Instruction::new_with_bytes(program_id, &data, accounts);

let message = Message::new(&[ix], Some(&payer.pubkey()));
let tx = Transaction::new(&[&payer], message, svm.latest_blockhash());
svm.send_transaction(tx).unwrap();

// Manually deserialize with discriminator handling
let account_data = svm.get_account(&pda).unwrap().data;
let account: UserAccount = UserAccount::try_deserialize(&mut &account_data[8..]).unwrap();

After (anchor-litesvm)

use anchor_litesvm::{AnchorLiteSVM, AnchorContext};

let ctx = AnchorLiteSVM::build_with_program(program_id, program_bytes);
let user = ctx.create_funded_account(10 * LAMPORTS_PER_SOL);

let ix = ctx.program()
    .accounts(Initialize { user: user.pubkey(), system_program: system_program::id() })
    .args(instruction::Initialize { name: "test".to_string() })
    .instruction()
    .unwrap();

ctx.execute_instruction(ix, &[&user]).unwrap();

let account: UserAccount = ctx.get_account(&pda).unwrap();

Key Components

AnchorLiteSVM Builder

MethodDescription
new()Creates a new builder instance
with_payer(keypair)Sets a custom payer keypair
deploy_program(id, bytes)Adds a program to deploy
build()Builds the AnchorContext
build_with_program(id, bytes)Convenience for single program
build_with_programs(programs)Deploy multiple programs

AnchorContext

MethodDescription
program()Returns Program for instruction building
execute_instruction(ix, signers)Execute a single instruction
execute_instructions(ixs, signers)Execute multiple instructions
get_account<T>(pubkey)Fetch and deserialize account
create_funded_account(lamports)Create a funded keypair
payer()Get the payer keypair
airdrop(pubkey, lamports)Airdrop SOL to an address

Program

MethodDescription
accounts(accounts)Set instruction accounts
args(args)Set instruction arguments
instruction()Build the final instruction
id()Get the program ID

Troubleshooting

Common Errors

ErrorCauseSolution
AccountNotFoundAccount doesn't existEnsure account is created before fetching
DiscriminatorMismatchWrong account typeVerify you're using the correct account struct
DeserializationErrorInvalid account dataCheck account was initialized correctly
No programs addedCalled build() without deploy_program()Add at least one program before building