Documentação SolanaLiteSVMRustCaixas Adicionaisanchor-litesvm

Gerenciamento de Contas

Entendendo os Discriminadores de Contas Anchor

Os programas Anchor adicionam um discriminador de 8 bytes a todos os dados de conta. Este discriminador é um hash do nome do tipo de conta e é usado para verificar se os dados da conta correspondem ao tipo esperado.

┌─────────────────────────────────────────────────┐
│ Account Data Layout │
├────────────────┬────────────────────────────────┤
│ Discriminator │ Account Fields │
│ (8 bytes) │ (variable size) │
└────────────────┴────────────────────────────────┘

Os utilitários de conta anchor-litesvm tratam esse discriminador automaticamente.

Buscando Contas Anchor

Busca Básica de Contas

use anchor_litesvm::AnchorLiteSVM;
use anchor_lang::prelude::*;
use solana_signer::Signer;
use solana_program::pubkey::Pubkey;
#[account]
pub struct UserAccount {
pub name: String,
pub balance: u64,
pub authority: Pubkey,
}
#[test]
fn test_fetch_account() {
let mut ctx = AnchorLiteSVM::build_with_program(PROGRAM_ID, include_bytes!("../target/deploy/your_program.so"));
let user = ctx.create_funded_account(10_000_000_000).unwrap();
// ... initialize the account ...
let (user_pda, _) = Pubkey::find_program_address(
&[b"user", user.pubkey().as_ref()],
&PROGRAM_ID,
);
// Fetch and deserialize the account
let account: UserAccount = ctx.get_account(&user_pda).unwrap();
assert_eq!(account.name, "Alice");
assert_eq!(account.authority, user.pubkey());
}

get_account<T>() valida automaticamente o discriminador de 8 bytes para garantir que os dados da conta correspondam ao tipo esperado.

Desserialização Sem Verificação

Para PDAs ou layouts de conta personalizados onde a validação do discriminador pode falhar, use get_account_unchecked:

use anchor_litesvm::AnchorLiteSVM;
#[test]
fn test_fetch_unchecked() {
let ctx = AnchorLiteSVM::build_with_program(PROGRAM_ID, include_bytes!("../target/deploy/your_program.so"));
// Fetch without discriminator validation
let account: UserAccount = ctx.get_account_unchecked(&some_pda).unwrap();
}

Use get_account_unchecked com cuidado. Sem a validação do discriminador, você pode desserializar dados inválidos. Use isso apenas quando tiver certeza sobre o tipo de conta.

Usando o Módulo de Conta Diretamente

Você também pode usar as funções de desserialização de conta diretamente:

use anchor_litesvm::{get_anchor_account, get_anchor_account_unchecked};
use litesvm::LiteSVM;
#[test]
fn test_direct_account_fetch() {
let mut svm = LiteSVM::new();
// ... setup ...
// Fetch with discriminator check
let account: UserAccount = get_anchor_account(&svm, &account_pubkey).unwrap();
// Fetch without discriminator check
let account: UserAccount = get_anchor_account_unchecked(&svm, &account_pubkey).unwrap();
}

Erros de Conta

O enum AccountError fornece informações detalhadas sobre erros:

use anchor_litesvm::AccountError;
#[test]
fn test_handle_errors() {
let ctx = AnchorLiteSVM::build_with_program(PROGRAM_ID, include_bytes!("../target/deploy/your_program.so"));
let result: Result<UserAccount, AccountError> = ctx.get_account(&nonexistent_pubkey);
match result {
Ok(account) => println!("Found account: {}", account.name),
Err(AccountError::AccountNotFound(pubkey)) => {
println!("Account not found: {}", pubkey);
}
Err(AccountError::DiscriminatorMismatch) => {
println!("Wrong account type!");
}
Err(AccountError::DeserializationError(msg)) => {
println!("Failed to deserialize: {}", msg);
}
}
}
ErroDescrição
AccountNotFound(Pubkey)Nenhuma conta existe no endereço fornecido
DiscriminatorMismatchO discriminador da conta não corresponde ao tipo esperado
DeserializationError(String)Falha ao desserializar os dados da conta

Trabalhando com Múltiplos Tipos de Conta

Buscando Diferentes Tipos de Conta

use anchor_litesvm::AnchorLiteSVM;
use anchor_lang::prelude::*;
#[account]
pub struct Config {
pub admin: Pubkey,
pub fee_bps: u16,
}
#[account]
pub struct UserProfile {
pub owner: Pubkey,
pub username: String,
pub created_at: i64,
}
#[account]
pub struct Order {
pub user: Pubkey,
pub amount: u64,
pub status: OrderStatus,
}
#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
pub enum OrderStatus {
Pending,
Completed,
Cancelled,
}
#[test]
fn test_multiple_account_types() {
let ctx = AnchorLiteSVM::build_with_program(PROGRAM_ID, include_bytes!("../target/deploy/your_program.so"));
// Each account type is deserialized correctly
let config: Config = ctx.get_account(&config_pda).unwrap();
let profile: UserProfile = ctx.get_account(&profile_pda).unwrap();
let order: Order = ctx.get_account(&order_pda).unwrap();
assert_eq!(config.fee_bps, 100);
assert_eq!(profile.username, "alice");
assert!(matches!(order.status, OrderStatus::Pending));
}

Verificando a Existência da Conta Antes de Buscar

use anchor_litesvm::AnchorLiteSVM;
#[test]
fn test_check_before_fetch() {
let ctx = AnchorLiteSVM::build_with_program(PROGRAM_ID, include_bytes!("../target/deploy/your_program.so"));
let user_pda = Pubkey::new_unique();
// Check existence first
if ctx.account_exists(&user_pda) {
let account: UserAccount = ctx.get_account(&user_pda).unwrap();
println!("Found: {}", account.name);
} else {
println!("Account not initialized yet");
}
}

Exemplo Completo

Aqui está um exemplo abrangente que demonstra o gerenciamento de contas:

use anchor_litesvm::AnchorLiteSVM;
use anchor_litesvm::TestHelpers;
use anchor_lang::prelude::*;
use solana_signer::Signer;
use solana_program::pubkey::Pubkey;
anchor_lang::declare_program!(counter);
#[test]
fn test_counter_workflow() {
let mut ctx = AnchorLiteSVM::build_with_program(
id(),
include_bytes!("../target/deploy/counter.so"),
);
let authority = ctx.svm.create_funded_account(10_000_000_000).unwrap();
// Derive the counter PDA
let (counter_pda, bump) = Pubkey::find_program_address(
&[b"counter", authority.pubkey().as_ref()],
&id(),
);
// Verify counter doesn't exist yet
assert!(!ctx.account_exists(&counter_pda));
// Initialize using generated client types
let init_ix = ctx.program()
.accounts(counter::client::accounts::Initialize {
authority: authority.pubkey(),
counter: counter_pda,
system_program: anchor_lang::system_program::ID,
})
.args(counter::client::args::Initialize {})
.instruction()
.unwrap();
ctx.execute_instruction(init_ix, &[&authority]).unwrap();
// Verify counter exists and has correct initial state
assert!(ctx.account_exists(&counter_pda));
let counter: counter::Counter = ctx.get_account(&counter_pda).unwrap();
assert_eq!(counter.count, 0);
assert_eq!(counter.authority, authority.pubkey());
assert_eq!(counter.bump, bump);
// Increment using generated client types
let increment_ix = ctx.program()
.accounts(counter::client::accounts::Increment {
authority: authority.pubkey(),
counter: counter_pda,
})
.args(counter::client::args::Increment {})
.instruction()
.unwrap();
ctx.execute_instruction(increment_ix, &[&authority]).unwrap();
// Verify incremented
let counter: counter::Counter = ctx.get_account(&counter_pda).unwrap();
assert_eq!(counter.count, 1);
// Increment again
ctx.execute_instruction(increment_ix.clone(), &[&authority]).unwrap();
let counter: counter::Counter = ctx.get_account(&counter_pda).unwrap();
assert_eq!(counter.count, 2);
println!("Counter test passed! Final count: {}", counter.count);
}

Is this page helpful?

© 2026 Fundação Solana. Todos os direitos reservados.