Documentación de SolanaLiteSVMRustCajas adicionalesanchor-litesvm

Inicio Rápido

Instalación

Añade las dependencias necesarias:

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

¿Qué es anchor-litesvm?

El crate anchor-litesvm ofrece una sintaxis simplificada similar a anchor-client pero sin la sobrecarga de RPC. Consigue una reducción del 78% en el código en comparación con LiteSVM puro, manteniendo la seguridad de tipos con los tipos de Anchor.

AnchorContext

  • Contexto de prueba compatible con producción
  • Los mismos patrones de API que anchor-client
  • Gestiona la instancia de LiteSVM, el pagador y el programa
  • Ejecuta instrucciones sin sobrecarga de RPC

API del Programa - Construcción fluida de instrucciones - Manejo de cuentas y argumentos con seguridad de tipos - Sintaxis familiar de anchor-client

Deserialización de Cuentas - Obtén y deserializa cuentas de Anchor - Manejo automático del discriminador - Soporte para PDAs y layouts personalizados

Análisis de Eventos

  • Analiza eventos desde los logs de transacciones
  • Verifica la emisión de eventos
  • Deserialización de eventos con seguridad de tipos

Ejemplo Rápido

Con Anchor 1.0, usa declare_program! para generar tipos de cliente a partir del IDL de tu programa. Esta macro crea los módulos client::accounts::* e client::args::* para la construcción de instrucciones con seguridad de tipos:

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) lee el IDL desde target/idl/my_program.json en tiempo de compilación y genera los módulos client::accounts::* e client::args::*. Esto requiere compilar tu programa primero.

Comparación: LiteSVM sin procesar vs anchor-litesvm

Antes (LiteSVM sin procesar)

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();

Después (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();

Componentes principales

Constructor AnchorLiteSVM

MétodoDescripción
new()Crea una nueva instancia del constructor
with_payer(keypair)Establece un keypair de pagador personalizado
deploy_program(id, bytes)Agrega un programa para desplegar
build()Construye el AnchorContext
build_with_program(id, bytes)Método conveniente para un solo programa
build_with_programs(programs)Despliega múltiples programas

AnchorContext

MétodoDescripción
svmAcceso directo a la instancia subyacente de LiteSVM (campo público)
program_idEl ID del programa (campo público)
program()Devuelve Program para la construcción de instrucciones
payer()Obtener el keypair del pagador
execute_instruction(ix, signers)Ejecutar una sola instrucción
execute_instructions(ixs, signers)Ejecutar múltiples instrucciones en una transacción
send_and_confirm_transaction(&tx)Enviar una transacción sin procesar
get_account<T>(pubkey)Obtener y deserializar una cuenta de Anchor
get_account_unchecked<T>(pubkey)Obtener sin verificación de discriminador
create_funded_account(lamports)Crear y financiar un nuevo keypair
airdrop(pubkey, lamports)Transferir SOL a una dirección
latest_blockhash()Obtener el blockhash actual
account_exists(pubkey)Verificar si existe una cuenta
deploy_program(id, bytes)Desplegar un programa adicional (mediante ProgramTestExt)

Programa

MétodoDescripción
accounts(accounts)Establecer las cuentas de instrucción (cualquier tipo ToAccountMetas)
args(args)Establecer los argumentos de instrucción (cualquier tipo InstructionData)
instruction()Construir la Instruction final
id()Obtener el ID del programa

ctx.svm — TestHelpers y AssertionHelpers

ctx.svm es un campo público LiteSVM con los traits TestHelpers y AssertionHelpers disponibles a través de litesvm-utils:

MétodoDescripción
ctx.svm.create_funded_account(lamports)Crear y financiar un keypair
ctx.svm.create_token_mint(authority, decimals)Crear un mint de token SPL
ctx.svm.create_associated_token_account(mint, owner)Crear una ATA
ctx.svm.mint_to(mint, token_account, authority, amount)Acuñar tokens
ctx.svm.get_pda(seeds, program_id)Derivar una dirección PDA
ctx.svm.get_pda_with_bump(seeds, program_id)Derivar PDA con bump seed
ctx.svm.assert_token_balance(token_account, expected)Verificar saldo de tokens
ctx.svm.assert_account_closed(pubkey)Verificar que la cuenta fue cerrada
ctx.svm.assert_sol_balance(pubkey, expected)Verificar saldo de SOL

Solución de problemas

Errores comunes

ErrorCausaSolución
AccountNotFoundLa cuenta no existeAsegúrate de que la cuenta esté creada antes de consultarla
DiscriminatorMismatchTipo de cuenta incorrectoVerifica que estás usando el struct de cuenta correcto
DeserializationErrorDatos de cuenta inválidosComprueba que la cuenta fue inicializada correctamente
No se añadieron programasSe llamó a build() sin deploy_program()Añade al menos un programa antes de compilar
Tipos de cliente faltantesdeclare_program! no fue llamadoEjecuta primero anchor build para generar el IDL, luego llama a declare_program!

Is this page helpful?