Solana-DokumentationLiteSVMRustZusätzliche Cratesanchor-litesvm

Schnellstart

Installation

Fügen Sie die benötigten Abhängigkeiten hinzu:

cargo add --dev anchor-litesvm litesvm litesvm-utils

Was ist anchor-litesvm?

Das anchor-litesvm-Crate bietet eine vereinfachte Syntax ähnlich wie anchor-client, jedoch ohne RPC-Overhead. Es erreicht eine 78%ige Code-Reduzierung im Vergleich zu rohem LiteSVM und gewährleistet dabei Typsicherheit mit Anchor-Typen.

AnchorContext

  • Produktionskompatible Testumgebung
  • Gleiche API-Muster wie anchor-client
  • Verwaltet LiteSVM-Instanz, Zahler und Programm
  • Anweisungen ohne RPC-Overhead ausführen

Programm-API – Flüssiges Erstellen von Anweisungen – Typsichere Konten- und Argumentverarbeitung – Vertraute anchor-client-Syntax

Konten-Deserialisierung – Anchor-Konten abrufen und deserialisieren – Automatische Diskriminator-Verarbeitung – Unterstützung für PDAs und benutzerdefinierte Layouts

Ereignis-Parsing

  • Ereignisse aus Transaktionsprotokollen parsen
  • Ereignisausgabe prüfen
  • Typsichere Ereignis-Deserialisierung

Schnellbeispiel

Mit Anchor 1.0 verwenden Sie declare_program!, um Client-Typen aus der IDL Ihres Programms zu generieren. Dieses Makro erstellt die Module client::accounts::* und client::args::* für typsicheres Erstellen von Anweisungen:

use anchor_litesvm::AnchorLiteSVM;
use anchor_litesvm::{AssertionHelpers, TestHelpers};
use anchor_lang::system_program;
use solana_sdk::signature::{read_keypair_file, Signer};
// Generate client types from your program's IDL
anchor_lang::declare_program!(my_program);
#[test]
fn test_anchor_program() {
// One-line setup — reads program keypair for the correct ID
let program_keypair = read_keypair_file("target/deploy/my_program-keypair.json").unwrap();
let mut ctx = AnchorLiteSVM::build_with_program(
program_keypair.pubkey(),
include_bytes!("../target/deploy/my_program.so"),
);
// Create a funded account via TestHelpers on ctx.svm
let user = ctx.svm.create_funded_account(10_000_000_000).unwrap();
// Derive PDA
let seed: u64 = 42;
let pda = ctx.svm.get_pda(
&[b"user", user.pubkey().as_ref(), &seed.to_le_bytes()],
&program_keypair.pubkey(),
);
// Build instruction using generated client types
let ix = ctx.program()
.accounts(my_program::client::accounts::Initialize {
user: user.pubkey(),
user_account: pda,
system_program: system_program::ID,
})
.args(my_program::client::args::Initialize {
seed,
name: "test".to_string(),
})
.instruction()
.unwrap();
// Execute and assert in one chain
ctx.execute_instruction(ix, &[&user])
.unwrap()
.assert_success();
// Fetch and deserialize the account
let account: my_program::MyAccount = ctx.get_account(&pda).unwrap();
assert_eq!(account.name, "test");
}

declare_program!(my_program) liest die IDL zur Kompilierzeit aus target/idl/my_program.json und generiert die Module client::accounts::* und client::args::*. Hierfür muss Ihr Programm zuerst gebaut werden.

Vergleich: Raw LiteSVM vs anchor-litesvm

Vorher (Raw LiteSVM)

use litesvm::LiteSVM;
use solana_keypair::Keypair;
use solana_signer::Signer;
use solana_program::instruction::{AccountMeta, Instruction};
use solana_message::Message;
use solana_transaction::Transaction;
let mut svm = LiteSVM::new();
svm.add_program(program_id, program_bytes).unwrap();
let payer = Keypair::new();
svm.airdrop(&payer.pubkey(), 10_000_000_000).unwrap();
// Manually compute 8-byte discriminator
let discriminator = {
let mut hasher = sha2::Sha256::new();
hasher.update(b"global:initialize");
let result = hasher.finalize();
result[..8].to_vec()
};
// Manually serialize args and build instruction
let mut data = discriminator;
data.extend_from_slice(&borsh::to_vec(&args).unwrap());
let accounts = vec![
AccountMeta::new(user.pubkey(), true),
AccountMeta::new(user_pda, false),
AccountMeta::new_readonly(system_program::id(), false),
];
let ix = Instruction::new_with_bytes(program_id, &data, accounts);
let tx = Transaction::new_signed_with_payer(
&[ix],
Some(&payer.pubkey()),
&[&payer],
svm.latest_blockhash(),
);
svm.send_transaction(tx).unwrap();
// Manually deserialize with discriminator skip
let account_data = svm.get_account(&pda).unwrap().data;
let account: UserAccount = UserAccount::try_deserialize(
&mut &account_data[8..]
).unwrap();

Nachher (anchor-litesvm)

use anchor_litesvm::AnchorLiteSVM;
anchor_lang::declare_program!(my_program);
let mut ctx = AnchorLiteSVM::build_with_program(program_id, program_bytes);
let user = ctx.svm.create_funded_account(10_000_000_000).unwrap();
let ix = ctx.program()
.accounts(my_program::client::accounts::Initialize {
user: user.pubkey(),
user_account: user_pda,
system_program: anchor_lang::system_program::ID,
})
.args(my_program::client::args::Initialize { name: "test".to_string() })
.instruction()
.unwrap();
ctx.execute_instruction(ix, &[&user]).unwrap().assert_success();
let account: my_program::UserAccount = ctx.get_account(&user_pda).unwrap();

Hauptkomponenten

AnchorLiteSVM Builder

MethodeBeschreibung
new()Erstellt eine neue Builder-Instanz
with_payer(keypair)Setzt ein benutzerdefiniertes Payer-keypair
deploy_program(id, bytes)Fügt ein Programm zum Deployment hinzu
build()Erstellt den AnchorContext
build_with_program(id, bytes)Komfortmethode für ein einzelnes Programm
build_with_programs(programs)Mehrere Programme deployen

AnchorContext

MethodeBeschreibung
svmDirektzugriff auf die zugrunde liegende LiteSVM-Instanz (öffentliches Feld)
program_idDie Programm-ID (öffentliches Feld)
program()Gibt Program für den Aufbau von Anweisungen zurück
payer()Payer-keypair abrufen
execute_instruction(ix, signers)Eine einzelne Anweisung ausführen
execute_instructions(ixs, signers)Mehrere Anweisungen in einer Transaktion ausführen
send_and_confirm_transaction(&tx)Eine rohe Transaktion senden
get_account<T>(pubkey)Ein Anchor-Konten abrufen und deserialisieren
get_account_unchecked<T>(pubkey)Abrufen ohne Diskriminatorprüfung
create_funded_account(lamports)Ein neues keypair erstellen und finanzieren
airdrop(pubkey, lamports)SOL an eine Adresse airdroppen
latest_blockhash()Den aktuellen Blockhash abrufen
account_exists(pubkey)Prüfen, ob ein Konten existiert
deploy_program(id, bytes)Ein zusätzliches Programm deployen (über ProgramTestExt)

Programm

MethodeBeschreibung
accounts(accounts)Anweisungs-Konten setzen (beliebiger ToAccountMetas-Typ)
args(args)Anweisungs-Argumente setzen (beliebiger InstructionData-Typ)
instruction()Die finale Instruction erstellen
id()Die Programm-ID abrufen

ctx.svm — TestHelpers & AssertionHelpers

ctx.svm ist ein öffentliches LiteSVM-Feld mit den Traits TestHelpers und AssertionHelpers, die über litesvm-utils verfügbar sind:

MethodeBeschreibung
ctx.svm.create_funded_account(lamports)Ein keypair erstellen und finanzieren
ctx.svm.create_token_mint(authority, decimals)Eine SPL-Token-Mint erstellen
ctx.svm.create_associated_token_account(mint, owner)Eine ATA erstellen
ctx.svm.mint_to(mint, token_account, authority, amount)Token prägen
ctx.svm.get_pda(seeds, program_id)Eine PDA-Adresse ableiten
ctx.svm.get_pda_with_bump(seeds, program_id)PDA mit bump seed ableiten
ctx.svm.assert_token_balance(token_account, expected)Token-Guthaben prüfen
ctx.svm.assert_account_closed(pubkey)Prüfen, ob Konten geschlossen wurde
ctx.svm.assert_sol_balance(pubkey, expected)SOL-Guthaben prüfen

Fehlerbehebung

Häufige Fehler

FehlerUrsacheLösung
AccountNotFoundKonten existiert nichtSicherstellen, dass Konten vor dem Abrufen erstellt wurde
DiscriminatorMismatchFalscher KontentypÜberprüfen, ob der korrekte Konten-Struct verwendet wird
DeserializationErrorUngültige KontendatenPrüfen, ob Konten korrekt initialisiert wurde
Keine Programme hinzugefügtbuild() ohne deploy_program() aufgerufenMindestens ein Programm vor dem Build hinzufügen
Fehlende Client-Typendeclare_program! nicht aufgerufenZuerst anchor build ausführen, um IDL zu generieren, dann declare_program! aufrufen

Is this page helpful?

Inhaltsverzeichnis

Seite bearbeiten
© 2026 Solana Foundation. Alle Rechte vorbehalten.