Tài liệu SolanaLiteSVMRustThùng Hàng Bổ Sunganchor-litesvm

Bắt Đầu Nhanh

Cài Đặt

Thêm các phụ thuộc cần thiết:

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

anchor-litesvm là gì?

Crate anchor-litesvm cung cấp cú pháp đơn giản hóa tương tự anchor-client nhưng không có chi phí RPC. Nó đạt được giảm 78% mã nguồn so với LiteSVM thuần túy trong khi vẫn duy trì tính an toàn kiểu với các kiểu Anchor.

AnchorContext

  • Ngữ cảnh kiểm thử tương thích với môi trường production
  • Các mẫu API giống với anchor-client
  • Quản lý instance LiteSVM, payer và chương trình
  • Thực thi các lệnh không cần chi phí RPC

Program API - Xây dựng lệnh theo kiểu fluent - Xử lý tài khoản và tham số an toàn kiểu - Cú pháp anchor-client quen thuộc

Giải Tuần Tự Tài Khoản - Lấy và giải tuần tự các tài khoản Anchor - Xử lý discriminator tự động - Hỗ trợ PDA và các bố cục tùy chỉnh

Phân Tích Sự Kiện

  • Phân tích sự kiện từ nhật ký giao dịch
  • Xác nhận phát ra sự kiện
  • Giải tuần tự sự kiện an toàn kiểu

Ví Dụ Nhanh

Với Anchor 1.0, sử dụng declare_program! để tạo các kiểu client từ IDL của chương trình. Macro này tạo ra các module client::accounts::*client::args::* để xây dựng lệnh an toàn kiểu:

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) đọc IDL từ target/idl/my_program.json tại thời điểm biên dịch và tạo ra các module client::accounts::*client::args::*. Điều này yêu cầu phải build chương trình của bạn trước.

So sánh: Raw LiteSVM và anchor-litesvm

Trước (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();

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

Các thành phần chính

AnchorLiteSVM Builder

Phương thứcMô tả
new()Tạo một builder instance mới
with_payer(keypair)Đặt keypair người thanh toán tùy chỉnh
deploy_program(id, bytes)Thêm một chương trình để triển khai
build()Xây dựng AnchorContext
build_with_program(id, bytes)Tiện ích cho chương trình đơn lẻ
build_with_programs(programs)Triển khai nhiều chương trình

AnchorContext

Phương thứcMô tả
svmTruy cập trực tiếp vào instance LiteSVM bên dưới (trường public)
program_idID của chương trình (trường public)
program()Trả về Program để xây dựng lệnh
payer()Lấy keypair người thanh toán
execute_instruction(ix, signers)Thực thi một lệnh đơn lẻ
execute_instructions(ixs, signers)Thực thi nhiều lệnh trong một giao dịch
send_and_confirm_transaction(&tx)Gửi một giao dịch thô
get_account<T>(pubkey)Tìm nạp và giải tuần tự hóa một tài khoản Anchor
get_account_unchecked<T>(pubkey)Tìm nạp mà không kiểm tra discriminator
create_funded_account(lamports)Tạo và nạp tiền cho một keypair mới
airdrop(pubkey, lamports)Airdrop SOL vào một địa chỉ
latest_blockhash()Lấy blockhash hiện tại
account_exists(pubkey)Kiểm tra xem một tài khoản có tồn tại không
deploy_program(id, bytes)Triển khai thêm một chương trình (qua ProgramTestExt)

Program

Phương thứcMô tả
accounts(accounts)Đặt các tài khoản lệnh (bất kỳ kiểu ToAccountMetas nào)
args(args)Đặt các đối số lệnh (bất kỳ kiểu InstructionData nào)
instruction()Xây dựng Instruction cuối cùng
id()Lấy ID của chương trình

ctx.svm — TestHelpers & AssertionHelpers

ctx.svm là một trường LiteSVM công khai với các trait TestHelpersAssertionHelpers có sẵn thông qua litesvm-utils:

Phương thứcMô tả
ctx.svm.create_funded_account(lamports)Tạo và nạp tiền cho một keypair
ctx.svm.create_token_mint(authority, decimals)Tạo một token mint SPL
ctx.svm.create_associated_token_account(mint, owner)Tạo một ATA
ctx.svm.mint_to(mint, token_account, authority, amount)Mint token
ctx.svm.get_pda(seeds, program_id)Lấy địa chỉ PDA
ctx.svm.get_pda_with_bump(seeds, program_id)Lấy PDA kèm bump seed
ctx.svm.assert_token_balance(token_account, expected)Kiểm tra số dư token
ctx.svm.assert_account_closed(pubkey)Kiểm tra tài khoản đã bị đóng
ctx.svm.assert_sol_balance(pubkey, expected)Kiểm tra số dư SOL

Khắc phục sự cố

Lỗi thường gặp

LỗiNguyên nhânGiải pháp
AccountNotFoundTài khoản không tồn tạiĐảm bảo tài khoản đã được tạo trước khi truy xuất
DiscriminatorMismatchSai loại tài khoảnXác minh bạn đang sử dụng đúng struct tài khoản
DeserializationErrorDữ liệu tài khoản không hợp lệKiểm tra tài khoản đã được khởi tạo đúng cách
No programs addedĐã gọi build() mà không có deploy_program()Thêm ít nhất một chương trình trước khi build
Missing client typesdeclare_program! chưa được gọiChạy anchor build trước để tạo IDL, sau đó gọi declare_program!

Is this page helpful?