Τεκμηρίωση SolanaLiteSVMGoΠαραδείγματα

Δοκιμή Προγράμματος

Η δοκιμή ενός προσαρμοσμένου προγράμματος Solana από το Go σημαίνει φόρτωση του μεταγλωττισμένου αρχείου .so στο SVM, ρύθμιση των λογαριασμών που απαιτεί και αποστολή εντολών σε αυτό. Το litesvm-go διαχειρίζεται όλα αυτά εντός διεργασίας - δεν απαιτείται validator.

Φόρτωση Προγράμματος

package mytest
import (
"os"
"testing"
litesvm "github.com/LiteSVM/litesvm-go"
solana "github.com/gagliardetto/solana-go"
)
func TestLoadProgram(t *testing.T) {
svm, err := litesvm.New()
if err != nil {
t.Fatal(err)
}
defer svm.Close()
// Configure for program testing. Setters are infallible in practice;
// discarding the return keeps the example readable.
_ = svm.SetSigverify(false)
_ = svm.SetBlockhashCheck(false)
_ = svm.SetSysvars()
_ = svm.SetBuiltins()
// Load program from .so file.
programID := solana.NewWallet().PublicKey()
soPath := "./target/deploy/my_program.so"
if _, err := os.Stat(soPath); err != nil {
t.Skipf("program file not found: %s (build with: cargo build-sbf)", soPath)
}
if err := svm.AddProgramFromFile(programID, soPath); err != nil {
t.Fatal(err)
}
t.Logf("program loaded: %s", programID)
// Verify the program account.
acct := svm.GetAccount(programID)
if acct == nil {
t.Fatal("program account missing after load")
}
defer acct.Close()
t.Logf(" executable: %v", acct.Executable())
t.Logf(" data size: %d bytes", len(acct.Data()))
}

Πλήρης Ρύθμιση Δοκιμής Προγράμματος

package mytest
import (
"os"
"testing"
litesvm "github.com/LiteSVM/litesvm-go"
solana "github.com/gagliardetto/solana-go"
)
func TestProgramEndToEnd(t *testing.T) {
svm, err := litesvm.New()
if err != nil {
t.Fatal(err)
}
defer svm.Close()
// Wide-open config: faster tests, less plumbing. Setters are infallible
// in practice; discarding the return keeps the example readable.
_ = svm.SetSigverify(false)
_ = svm.SetBlockhashCheck(false)
_ = svm.SetSysvars()
_ = svm.SetBuiltins()
_ = svm.SetPrecompiles()
_ = svm.SetTransactionHistory(100)
// Load the program.
programID := solana.NewWallet().PublicKey()
soPath := "./target/deploy/my_program.so"
if _, err := os.Stat(soPath); err != nil {
t.Skipf("missing %s", soPath)
}
if err := svm.AddProgramFromFile(programID, soPath); err != nil {
t.Fatal(err)
}
// Seed any data accounts the program expects.
dataAddr := solana.NewWallet().PublicKey()
dataPayload := make([]byte, 100)
rent, err := svm.MinimumBalanceForRentExemption(len(dataPayload))
if err != nil {
t.Fatal(err)
}
acct, err := litesvm.NewAccount(rent, dataPayload, programID, false, 0)
if err != nil {
t.Fatal(err)
}
defer acct.Close()
if err := svm.SetAccount(dataAddr, acct); err != nil {
t.Fatal(err)
}
// Fund a payer that will sign the test instruction.
priv, err := solana.NewRandomPrivateKey()
if err != nil {
t.Fatal(err)
}
payer := priv.PublicKey()
if err := svm.Airdrop(payer, 1_000_000_000); err != nil {
t.Fatal(err)
}
// Build an instruction against the program.
bh, err := svm.LatestBlockhash()
if err != nil {
t.Fatal(err)
}
ix := &solana.GenericInstruction{
ProgID: programID,
AccountValues: solana.AccountMetaSlice{
{PublicKey: dataAddr, IsWritable: true, IsSigner: false},
{PublicKey: payer, IsWritable: true, IsSigner: true},
},
DataBytes: []byte{0x01 /* discriminator + args */},
}
tx, err := solana.NewTransaction(
[]solana.Instruction{ix},
bh,
solana.TransactionPayer(payer),
)
if err != nil {
t.Fatal(err)
}
if _, err := tx.Sign(func(k solana.PublicKey) *solana.PrivateKey {
if k.Equals(payer) {
return &priv
}
return nil
}); err != nil {
t.Fatal(err)
}
txBytes, err := tx.MarshalBinary()
if err != nil {
t.Fatal(err)
}
// Execute and inspect.
out, err := svm.SendLegacyTransaction(txBytes)
if err != nil {
t.Fatal(err)
}
defer out.Close()
if !out.IsOk() {
t.Fatalf("program failed: %s\nlogs: %v", out.Error(), out.Logs())
}
t.Logf("logs: %v", out.Logs())
t.Logf("compute: %d CU", out.ComputeUnits())
// Verify state changes by reading the data account back.
updated := svm.GetAccount(dataAddr)
if updated == nil {
t.Fatal("data account missing after execution")
}
defer updated.Close()
// Decode `updated.Data()` and assert as needed.
}

Χρήση Προεπιλεγμένων Προγραμμάτων

Για δοκιμές που χρειάζονται τυπικά προγράμματα (SPL Token, Memo, ...):

svm, err := litesvm.New()
if err != nil {
t.Fatal(err)
}
defer svm.Close()
if err := svm.SetDefaultPrograms(); err != nil { // SPL Token, Memo, etc.
t.Fatal(err)
}
if err := svm.WithNativeMints(); err != nil { // wrapped-SOL mint
t.Fatal(err)
}

Δημιουργήστε το πρόγραμμα Solana με cargo build-sbf για να παράγετε το αρχείο .so.

Το μοτίβο είναι πάντα το ίδιο:

  1. Διαμόρφωση - ενεργοποίηση sysvars, builtins, precompiles όπως απαιτείται.
  2. Φόρτωση προγράμματος - AddProgramFromFileAddProgram για bytes στη μνήμη).
  3. Ρύθμιση λογαριασμών - προκαταλήψτε τους λογαριασμούς δεδομένων με SetAccount.
  4. Αποστολή - δημιουργήστε την εντολή με solana-go, κωδικοποιήστε και υποβάλετε μέσω SendLegacyTransaction.
  5. Επαλήθευση - διαβάστε τους λογαριασμούς με GetAccount και ελέγξτε τα logs, τις μονάδες υπολογισμού και την τελική κατάσταση.

Μόλις αυτό το βασικό πλαίσιο λειτουργήσει, επεκτείνετέ το προσθέτοντας περισσότερες εντολές, περισσότερους λογαριασμούς και ένα βοηθητικό στοιχείο για τον επαναλαμβανόμενο κώδικα.

Is this page helpful?

Πίνακας Περιεχομένων

Επεξεργασία Σελίδας
© 2026 Ίδρυμα Solana. Με επιφύλαξη παντός δικαιώματος.