Crate light_program_test

Source
Expand description

§Light Program Test

A fast local test environment for Solana programs using compressed accounts and tokens.

§Features

  • Fast in-memory indexer and SVM via LiteSVM
  • Supports custom programs
  • Built-in prover

Use light-program-test when:

  • You need fast test execution
  • You write unit/integration tests for your program or client code

Use solana-test-validator when:

  • You need RPC methods or external tools that are incompatible with LiteSVM
  • Testing against real validator behavior

§Configuration Options

§with_prover: bool

  • true: Starts a prover server in the background for generating validity proofs
  • false: Runs without prover (faster for tests that don’t need proofs, or repeated test runs to reduce startup time)

§additional_programs: Option<Vec<(&str, Pubkey)>>

  • Specify custom programs to deploy alongside the default Light Protocol programs
  • Format: vec![("program_name", program_id)]
  • Programs are loaded from built artifacts

§Prerequisites

  1. ZK Compression CLI: Required to start the prover server and download Light Protocol programs

    npm i -g @lightprotocol/zk-compression-cli
    • If programs are missing after CLI installation, run light test-validator once to download them
  2. Build programs: Run cargo test-sbf to build program binaries and set the required environment variables for locating program artifacts

§Prover Server

The prover server runs on port 3001 when enabled. To manually stop it:

# Find the process ID
lsof -i:3001
# Kill the process
kill <pid>

§Examples

§V1 Trees

use light_program_test::{LightProgramTest, ProgramTestConfig};
use solana_sdk::signer::Signer;

#[tokio::test]
async fn test_v1_compressed_account() {
    // Initialize with v1 trees
    let config = ProgramTestConfig::default();
    let mut rpc = LightProgramTest::new(config).await.unwrap();

    let payer = Keypair::new();

    // Get v1 tree info
    let address_tree_info = rpc.get_address_tree_v1();
    let state_tree_info = rpc.get_random_state_tree_info();

    // Airdrop for testing
    rpc.airdrop_lamports(&payer.pubkey(), 1_000_000_000).await.unwrap();

    // Query compressed accounts using Indexer trait
    let accounts = rpc.indexer().unwrap()
        .get_compressed_accounts_by_owner(&payer.pubkey())
        .await
        .unwrap();

    println!("Found {} compressed accounts", accounts.len());
}

§V2 Trees

use light_program_test::{LightProgramTest, ProgramTestConfig};
use solana_sdk::signer::Signer;

#[tokio::test]
async fn test_v2_compressed_account() {
    // Initialize with v2 batched trees and custom program
    let config = ProgramTestConfig::new_v2(
        true, // with_prover
        Some(vec![("my_program", my_program::ID)])
    );
    let mut rpc = LightProgramTest::new(config).await.unwrap();

    let payer = Keypair::new();

    // Get v2 tree pubkeys
    let address_tree_info = rpc.get_address_tree_v2();
    let state_tree_info = rpc.get_random_state_tree_info();


    rpc.airdrop_lamports(&payer.pubkey(), 1_000_000_000).await.unwrap();

    // Query using Indexer trait methods
    let accounts = rpc.indexer().unwrap()
        .get_compressed_accounts_by_owner(&payer.pubkey())
        .await
        .unwrap();

    println!("Found {} compressed accounts with v2 trees", accounts.len());
}

Re-exports§

pub use program_test::config::ProgramTestConfig;
pub use program_test::LightProgramTest;

Modules§

accounts
indexer
program_test
utils

Structs§

AddressWithTree

Enums§

RpcError

Traits§

Indexer
Rpc