Sending Transactions
The TransactionHelpers trait provides convenient methods for sending
instructions and analyzing results.
Send a Single Instruction
use litesvm_utils::{LiteSVM, Signer, TestHelpers, TransactionHelpers};use solana_sdk::{native_token::LAMPORTS_PER_SOL, system_instruction};#[test]fn test_send_instruction() {let mut svm = LiteSVM::new();let alice = svm.create_funded_account(10 * LAMPORTS_PER_SOL).unwrap();let bob = svm.create_funded_account(0).unwrap();// Create a transfer instructionlet transfer_ix = system_instruction::transfer(&alice.pubkey(),&bob.pubkey(),LAMPORTS_PER_SOL,);// Send and get result (returns Result<TransactionResult, TransactionError>)let result = svm.send_instruction(transfer_ix, &[&alice]).unwrap();// Assert it succeededresult.assert_success();}
Send Multiple Instructions
use litesvm_utils::{LiteSVM, Signer, TestHelpers, TransactionHelpers};use solana_sdk::{native_token::LAMPORTS_PER_SOL, system_instruction};#[test]fn test_send_multiple_instructions() {let mut svm = LiteSVM::new();let alice = svm.create_funded_account(10 * LAMPORTS_PER_SOL).unwrap();let bob = svm.create_funded_account(0).unwrap();let carol = svm.create_funded_account(0).unwrap();// Create multiple transfer instructionslet instructions = vec![system_instruction::transfer(&alice.pubkey(), &bob.pubkey(), LAMPORTS_PER_SOL),system_instruction::transfer(&alice.pubkey(), &carol.pubkey(), LAMPORTS_PER_SOL),];// Send all in one transactionlet result = svm.send_instructions(&instructions, &[&alice]).unwrap();result.assert_success();}
TransactionResult
The send_instruction and send_instructions methods return a
TransactionResult that wraps the transaction metadata with useful testing
utilities.
Assert Success
use litesvm_utils::{LiteSVM, Signer, TestHelpers, TransactionHelpers};use solana_sdk::{native_token::LAMPORTS_PER_SOL, system_instruction};#[test]fn test_assert_success() {let mut svm = LiteSVM::new();let alice = svm.create_funded_account(10 * LAMPORTS_PER_SOL).unwrap();let bob = svm.create_funded_account(0).unwrap();let ix = system_instruction::transfer(&alice.pubkey(), &bob.pubkey(), LAMPORTS_PER_SOL);let result = svm.send_instruction(ix, &[&alice]).unwrap();// Panics with detailed logs if the transaction failedresult.assert_success();}
assert_success() will panic with the full transaction logs if the
transaction failed, making debugging much easier.
Assert Failure
use litesvm_utils::{LiteSVM, Signer, TestHelpers, TransactionHelpers};use solana_sdk::{native_token::LAMPORTS_PER_SOL, system_instruction};#[test]fn test_assert_failure() {let mut svm = LiteSVM::new();let alice = svm.create_funded_account(1 * LAMPORTS_PER_SOL).unwrap();let bob = svm.create_funded_account(0).unwrap();// Try to transfer more than Alice haslet ix = system_instruction::transfer(&alice.pubkey(),&bob.pubkey(),100 * LAMPORTS_PER_SOL, // Alice only has 1 SOL);let result = svm.send_instruction(ix, &[&alice]).unwrap();// This should failresult.assert_failure();}
Assert Specific Error
use litesvm_utils::{LiteSVM, Signer, TestHelpers, TransactionHelpers};use solana_sdk::{native_token::LAMPORTS_PER_SOL, system_instruction};#[test]fn test_assert_error() {let mut svm = LiteSVM::new();let alice = svm.create_funded_account(1 * LAMPORTS_PER_SOL).unwrap();let bob = svm.create_funded_account(0).unwrap();let ix = system_instruction::transfer(&alice.pubkey(),&bob.pubkey(),100 * LAMPORTS_PER_SOL,);let result = svm.send_instruction(ix, &[&alice]).unwrap();// Assert a specific error message is presentresult.assert_error("insufficient lamports");}
Assert Error Code
For custom program errors, you can assert on the error code:
// Assert a specific custom error coderesult.assert_error_code(6000); // Custom error code from your program
Assert Anchor Error
For Anchor programs, assert on error names:
// Assert an Anchor-specific errorresult.assert_anchor_error("InsufficientFunds");
Inspecting Transactions
Check Transaction Logs
use litesvm_utils::{LiteSVM, Signer, TestHelpers, TransactionHelpers};use solana_sdk::{native_token::LAMPORTS_PER_SOL, system_instruction};#[test]fn test_check_logs() {let mut svm = LiteSVM::new();let alice = svm.create_funded_account(10 * LAMPORTS_PER_SOL).unwrap();let bob = svm.create_funded_account(0).unwrap();let ix = system_instruction::transfer(&alice.pubkey(), &bob.pubkey(), LAMPORTS_PER_SOL);let result = svm.send_instruction(ix, &[&alice]).unwrap();// Check if a specific message is in the logsif result.has_log("Transfer") {println!("Found transfer log!");}// Find a log matching a patternif let Some(log) = result.find_log("Program") {println!("Found log: {}", log);}// Get all logslet logs = result.logs();for log in logs {println!("{}", log);}}
Print Logs for Debugging
use litesvm_utils::{LiteSVM, Signer, TestHelpers, TransactionHelpers};use solana_sdk::{native_token::LAMPORTS_PER_SOL, system_instruction};#[test]fn test_print_logs() {let mut svm = LiteSVM::new();let alice = svm.create_funded_account(10 * LAMPORTS_PER_SOL).unwrap();let bob = svm.create_funded_account(0).unwrap();let ix = system_instruction::transfer(&alice.pubkey(), &bob.pubkey(), LAMPORTS_PER_SOL);let result = svm.send_instruction(ix, &[&alice]).unwrap();// Print formatted logs for debuggingresult.print_logs();}
Check Compute Units
use litesvm_utils::{LiteSVM, Signer, TestHelpers, TransactionHelpers};use solana_sdk::{native_token::LAMPORTS_PER_SOL, system_instruction};#[test]fn test_compute_units() {let mut svm = LiteSVM::new();let alice = svm.create_funded_account(10 * LAMPORTS_PER_SOL).unwrap();let bob = svm.create_funded_account(0).unwrap();let ix = system_instruction::transfer(&alice.pubkey(), &bob.pubkey(), LAMPORTS_PER_SOL);let result = svm.send_instruction(ix, &[&alice]).unwrap();let compute_units = result.compute_units();println!("Compute units consumed: {}", compute_units);// Assert compute usage is within expected boundsassert!(compute_units < 10_000, "Transaction used too many compute units");}
Monitoring compute units is useful for optimization. Solana limits transactions to 1.4M compute units, and higher usage costs more.
Complete Example
Here's a comprehensive example demonstrating transaction helpers:
use litesvm_utils::{AssertionHelpers, LiteSVM, Signer, TestHelpers, TransactionHelpers};use solana_sdk::{native_token::LAMPORTS_PER_SOL, system_instruction};#[test]fn test_transaction_workflow() {let mut svm = LiteSVM::new();// Setup accountslet alice = svm.create_funded_account(10 * LAMPORTS_PER_SOL).unwrap();let bob = svm.create_funded_account(0).unwrap();// Test successful transferlet transfer_ix = system_instruction::transfer(&alice.pubkey(),&bob.pubkey(),2 * LAMPORTS_PER_SOL,);let result = svm.send_instruction(transfer_ix, &[&alice]).unwrap();// Verify successresult.assert_success();// Check compute usagelet cu = result.compute_units();println!("Transfer used {} compute units", cu);// Verify balancessvm.assert_sol_balance(&bob.pubkey(), 2 * LAMPORTS_PER_SOL);// Test expected failurelet bad_transfer = system_instruction::transfer(&alice.pubkey(),&bob.pubkey(),100 * LAMPORTS_PER_SOL, // More than Alice has);let fail_result = svm.send_instruction(bad_transfer, &[&alice]).unwrap();fail_result.assert_failure();// Print logs for debuggingfail_result.print_logs();println!("Transaction workflow test passed!");}
Error Types
The TransactionError enum provides structured error information:
| Variant | Description |
|---|---|
ExecutionFailed(String) | Transaction execution failed with message |
BuildError(String) | Failed to build the transaction |
AssertionFailed(String) | An assertion on the result failed |
Is this page helpful?