Documentação SolanaLiteSVMRustCaixas Adicionaisanchor-litesvm

Eventos

Entendendo os Eventos do Anchor

Os programas Anchor podem emitir eventos que são registrados durante a execução de transações. Esses eventos são codificados em Base64 nos logs de transações com o prefixo Program data:. O crate anchor-litesvm fornece utilitários para analisar e validar esses eventos.

┌─────────────────────────────────────────────────┐
│ Anchor Event Structure │
├────────────────┬────────────────────────────────┤
│ Discriminator │ Event Data │
│ (8 bytes) │ (serialized fields) │
└────────────────┴────────────────────────────────┘

Definindo Eventos

Primeiro, defina seus eventos no seu programa Anchor:

use anchor_lang::prelude::*;
#[event]
pub struct TransferEvent {
pub from: Pubkey,
pub to: Pubkey,
pub amount: u64,
pub timestamp: i64,
}
#[event]
pub struct InitializeEvent {
pub authority: Pubkey,
pub name: String,
}

Analisando Eventos

Analisar Todos os Eventos de um Tipo

use anchor_litesvm::{AnchorLiteSVM, EventHelpers};
use solana_signer::Signer;
#[test]
fn test_parse_events() {
let mut ctx = AnchorLiteSVM::build_with_program(PROGRAM_ID, include_bytes!("../target/deploy/your_program.so"));
let user = ctx.svm.create_funded_account(10_000_000_000).unwrap();
// Execute instruction that emits events
let ix = ctx.program()
.accounts(Transfer { /* ... */ })
.args(TransferArgs { amount: 1000 })
.instruction()
.unwrap();
let result = ctx.execute_instruction(ix, &[&user]).unwrap();
// Parse all TransferEvent events from the transaction
let events: Vec<TransferEvent> = result.parse_events().unwrap();
assert_eq!(events.len(), 1);
assert_eq!(events[0].amount, 1000);
}

Analisar Evento Único

use anchor_litesvm::{AnchorLiteSVM, EventHelpers};
#[test]
fn test_parse_single_event() {
let mut ctx = AnchorLiteSVM::build_with_program(PROGRAM_ID, include_bytes!("../target/deploy/your_program.so"));
// ... execute instruction ...
// Get the first event of the type
let event: TransferEvent = result.parse_event().unwrap();
println!("Transfer: {} -> {} ({})", event.from, event.to, event.amount);
}

Validando Eventos

Verificar se o Evento Foi Emitido

use anchor_litesvm::{AnchorLiteSVM, EventHelpers};
#[test]
fn test_assert_event_emitted() {
let mut ctx = AnchorLiteSVM::build_with_program(PROGRAM_ID, include_bytes!("../target/deploy/your_program.so"));
let user = ctx.svm.create_funded_account(10_000_000_000).unwrap();
let ix = ctx.program()
.accounts(Initialize { /* ... */ })
.args(InitializeArgs { name: "test".to_string() })
.instruction()
.unwrap();
let result = ctx.execute_instruction(ix, &[&user]).unwrap();
// Assert that at least one InitializeEvent was emitted
result.assert_event_emitted::<InitializeEvent>();
}

assert_event_emitted entrará em pânico se nenhum evento do tipo especificado for encontrado nos logs de transações.

Verificar Contagem de Eventos

use anchor_litesvm::{AnchorLiteSVM, EventHelpers};
#[test]
fn test_assert_event_count() {
let mut ctx = AnchorLiteSVM::build_with_program(PROGRAM_ID, include_bytes!("../target/deploy/your_program.so"));
// Execute instruction that emits multiple events
let ix = ctx.program()
.accounts(BatchTransfer { /* ... */ })
.args(BatchTransferArgs { recipients: vec![...], amounts: vec![...] })
.instruction()
.unwrap();
let result = ctx.execute_instruction(ix, &[&user]).unwrap();
// Assert exactly 3 TransferEvent events were emitted
result.assert_event_count::<TransferEvent>(3);
}

Verificar Existência de Evento

use anchor_litesvm::{AnchorLiteSVM, EventHelpers};
#[test]
fn test_has_event() {
let mut ctx = AnchorLiteSVM::build_with_program(PROGRAM_ID, include_bytes!("../target/deploy/your_program.so"));
// ... execute instruction ...
// Check without panicking
if result.has_event::<TransferEvent>() {
let event: TransferEvent = result.parse_event().unwrap();
println!("Transfer occurred: {}", event.amount);
} else {
println!("No transfer in this transaction");
}
}

Análise Manual de Eventos

Para casos de uso avançados, você pode analisar os dados do evento diretamente:

use anchor_litesvm::parse_event_data;
#[test]
fn test_manual_parse() {
// If you have the base64-encoded event data
let base64_data = "SGVsbG8gV29ybGQ="; // Example
let event: TransferEvent = parse_event_data(base64_data).unwrap();
}

Erros de Eventos

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

use anchor_litesvm::EventError;
match result.parse_event::<TransferEvent>() {
Ok(event) => println!("Amount: {}", event.amount),
Err(EventError::EventNotFound) => println!("No event found"),
Err(EventError::ParseError(msg)) => println!("Parse error: {}", msg),
Err(EventError::Base64Error) => println!("Invalid Base64 encoding"),
Err(EventError::InvalidFormat) => println!("Malformed event data"),
Err(EventError::AnchorError(msg)) => println!("Anchor error: {}", msg),
}
ErroDescrição
EventNotFoundNenhum evento do tipo especificado nos logs
ParseError(String)Falha ao analisar os dados do evento
Base64ErrorFalha ao decodificar Base64
InvalidFormatOs dados do evento têm estrutura inválida
AnchorError(String)Falha na desserialização do Anchor

Exemplo Completo

Aqui está um exemplo abrangente demonstrando o tratamento de eventos:

use anchor_litesvm::{AnchorLiteSVM, EventHelpers, TestHelpers};
use anchor_lang::{prelude::*, system_program};
use solana_signer::Signer;
// declare_program! generates client types AND re-exports event structs
anchor_lang::declare_program!(vault);
#[test]
fn test_vault_events() {
let mut ctx = AnchorLiteSVM::build_with_program(
VAULT_PROGRAM_ID,
include_bytes!("../target/deploy/vault.so"),
);
let authority = ctx.svm.create_funded_account(100_000_000_000).unwrap();
let depositor = ctx.svm.create_funded_account(50_000_000_000).unwrap();
let vault_pda = ctx.svm.get_pda(
&[b"vault", authority.pubkey().as_ref()],
&VAULT_PROGRAM_ID,
);
// Create vault
let create_ix = ctx.program()
.accounts(vault::client::accounts::CreateVault {
authority: authority.pubkey(),
vault: vault_pda,
system_program: system_program::ID,
})
.args(vault::client::args::CreateVault {})
.instruction()
.unwrap();
let result = ctx.execute_instruction(create_ix, &[&authority]).unwrap();
// Assert VaultCreated event
result.assert_event_emitted::<vault::VaultCreated>();
let created_event: vault::VaultCreated = result.parse_event().unwrap();
assert_eq!(created_event.vault, vault_pda);
assert_eq!(created_event.authority, authority.pubkey());
// Deposit
let deposit_ix = ctx.program()
.accounts(vault::client::accounts::DepositToVault {
vault: vault_pda,
depositor: depositor.pubkey(),
system_program: system_program::ID,
})
.args(vault::client::args::Deposit { amount: 10_000_000_000 })
.instruction()
.unwrap();
let result = ctx.execute_instruction(deposit_ix, &[&depositor]).unwrap();
// Assert Deposit event
result.assert_event_emitted::<vault::Deposit>();
let deposit_event: vault::Deposit = result.parse_event().unwrap();
assert_eq!(deposit_event.amount, 10_000_000_000);
assert_eq!(deposit_event.depositor, depositor.pubkey());
// Withdrawal
let withdraw_ix = ctx.program()
.accounts(vault::client::accounts::WithdrawFromVault {
vault: vault_pda,
authority: authority.pubkey(),
recipient: authority.pubkey(),
})
.args(vault::client::args::Withdraw { amount: 5_000_000_000 })
.instruction()
.unwrap();
let result = ctx.execute_instruction(withdraw_ix, &[&authority]).unwrap();
// Check withdrawal event
assert!(result.has_event::<vault::Withdrawal>());
let withdraw_event: vault::Withdrawal = result.parse_event().unwrap();
assert_eq!(withdraw_event.amount, 5_000_000_000);
println!("All event tests passed!");
}

Os eventos são uma ótima maneira de verificar se o seu programa foi executado corretamente sem precisar buscar e desserializar contas. Eles são especialmente úteis para acompanhar mudanças de estado ao longo do tempo.

Is this page helpful?

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