Ajonaikaiset tapahtumat

Surfnet-ajoympäristö lähettää jäsenneltyjen tapahtumien virran, joka kattaa transaktiokäsittelyn, slot-tikitykset, tilivirroituksen, aikamatkustuksen ja virheet. SDK paljastaa tämän virran niin, että testit voivat tarkistaa ajonaikaisen käyttäytymisen ilman lokien jäsentämistä.

Rust: Kanavastaanotin

Surfnet::events() palauttaa viitteen crossbeam_channel::Receiver<SimnetEvent>-kanavaan, johon ajoympäristö julkaisee. Tyhjennä se try_iter()-funktiolla (ei-estävä) tai lue yksittäisiä tapahtumia recv()- / recv_timeout()-metodeilla.

use surfpool_sdk::{SimnetEvent, Surfnet};
let surfnet = Surfnet::start().await?;
// Drain whatever has accumulated so far.
for event in surfnet.events().try_iter() {
match event {
SimnetEvent::TransactionProcessed(_ts, metadata, error) => {
println!("tx {} -> {:?}", metadata.signature, metadata.logs);
if let Some(err) = error {
eprintln!(" failed: {err:?}");
}
}
SimnetEvent::ErrorLog(_ts, message) => {
eprintln!("runtime error: {message}");
}
other => {
println!("event: {other:?}");
}
}
}

Vastaanotin on jaettu

Jos käynnistät taustatason tehtävän tapahtumien kuluttamiseksi, älä kutsu myös try_iter pääsäikeestä. Tapahtumat jakautuvat ennakoimattomasti kahden kuluttajan välillä.

JS: Drain-metodi

JS-sidokset puskuroivat tapahtumat sisäisesti ja paljastavat ne drainEvents-metodin kautta. Jokainen kutsu palauttaa kaiken edellisen kutsun jälkeen kertyneen sisällön ja tyhjentää puskurin.

import { Surfnet } from "@solana/surfpool";
const surfnet = Surfnet.start();
try {
// ... do test setup that triggers events ...
const events = surfnet.drainEvents();
for (const event of events) {
switch (event.kind) {
case "transactionProcessed":
console.log("tx", event.transactionSignature, event.logs);
break;
case "errorLog":
console.error("runtime error:", event.message);
break;
default:
console.log(event.kind, event.message ?? "");
}
}
} finally {
surfnet.stop();
}

Rajoittamaton puskuri

Jos et koskaan kutsu drainEvents, puskuri kasvaa koko instanssin elinajan. Se sopii lyhyille testeille, mutta kutsu sitä säännöllisesti pitkäkestoisissa fixtureissa, jotta muisti ei turvoa.

SimnetEventValue-rakenne (JS)

JS-tapahtumatyyppi on litteä objekti, jossa on kind-diskriminaattori ja valinnaiset kentät. Kaikkia kenttiä ei ole asetettu jokaisessa variantissa — hajota rakenne kind-arvon perusteella.

interface SimnetEventValue {
kind: string; // discriminator, e.g. "TransactionProcessed"
message?: string; // human-readable message
timestamp?: string; // ISO timestamp
// startup
initialTransactionCount?: number;
clock?: ClockValue;
// slot / clock
epochInfo?: EpochInfoValue;
clockCommand?: string;
slotIntervalMs?: number;
// accounts
accountPubkey?: string;
// transactions
transactionSignature?: string;
logs?: string[];
computeUnitsConsumed?: number;
fee?: number;
// errors
errorMessage?: string;
// misc
tag?: string;
profileKey?: string;
profileSlot?: number;
runbookId?: string;
runbookErrors?: string[];
}

Tapahtumatyypit

JS-puolen kind-merkkijonot ovat camelCase-muodossa; vastaava Rust-variantti käyttää PascalCase-muotoa. Täsmää näihin tarkkoihin merkkijonoihin — ne ovat kirjainkokoriippuvaisia ja pysyviä versioiden välillä.

JS kindRust-varianttiLähetetään kun
readySimnetEvent::ReadyAjoympäristö käynnistyy loppuun; sisältää initialTransactionCount.
connectedSimnetEvent::ConnectedYhdistetty etäiseen RPC-palvelimeen; sisältää message (URL).
abortedSimnetEvent::AbortedKäynnistys keskeytettiin; sisältää message (syy).
shutdownSimnetEvent::ShutdownHallittu sammutus alkaa.
systemClockUpdatedSimnetEvent::SystemClockUpdatedJärjestelmäkello eteni; sisältää clock.
clockUpdateSimnetEvent::ClockUpdateKellokäsky suoritettiin (tauko/jatka/päivitä väli); sisältää clockCommand ja valinnaisesti slotIntervalMs.
epochInfoUpdateSimnetEvent::EpochInfoUpdateUusi epoch-tietokuva on saatavilla; sisältää epochInfo.
blockHashExpiredSimnetEvent::BlockHashExpiredKäytössä ollut lohkohajautusarvo on vanhentunut.
transactionReceivedSimnetEvent::TransactionReceivedTransaktio lisättiin jonoon; sisältää timestamp, transactionSignature.
transactionProcessedSimnetEvent::TransactionProcessedTransaktio suoritettiin; sisältää timestamp, transactionSignature, logs, computeUnitsConsumed, fee ja epäonnistumisen yhteydessä errorMessage.
accountUpdateSimnetEvent::AccountUpdateTili muuttui — kattaa virroitetut tilit ja cheatcode-ohjatut muutokset; sisältää timestamp ja accountPubkey.
infoLog / warnLog / errorLog / debugLogSimnetEvent::InfoLog / WarnLog / ErrorLog / DebugLogAjoympäristö lähetti lokirivin; sisältää timestamp ja message.
pluginLoadedSimnetEvent::PluginLoadedGeyser-lisäosa ladattiin; sisältää message (lisäosan nimi).
taggedProfileSimnetEvent::TaggedProfileProfilointitulos merkittiin; sisältää tag, profileKey, profileSlot, logs, computeUnitsConsumed.
runbookStarted / runbookCompletedSimnetEvent::RunbookStarted / RunbookCompletedRunbook käynnistyi tai päättyi; sisältää runbookId ja (valmistumisen yhteydessä) valinnaisen runbookErrors.

Assertion-mallit

Varmista, että transaktio onnistui

import { Surfnet } from "@solana/surfpool";
const surfnet = Surfnet.start();
try {
const sig = await sendTransaction(surfnet.rpcUrl /* ... */);
// ... wait for confirmation via RPC ...
const landed = surfnet
.drainEvents()
.some(
(e) => e.kind === "transactionProcessed" && e.transactionSignature === sig
);
console.assert(landed, "expected transaction to land");
} finally {
surfnet.stop();
}

Varmista, ettei ajonaikaisia virheitä esiintynyt

use surfpool_sdk::{SimnetEvent, Surfnet};
let mut surfnet = Surfnet::start().await?;
// ... run the test ...
let errors: Vec<_> = surfnet
.events()
.try_iter()
.filter(|e| matches!(e, SimnetEvent::ErrorLog(_, _)))
.collect();
assert!(errors.is_empty(), "runtime errors: {errors:?}");
surfnet.stop()?;

Miksi tapahtumat ovat parempia kuin lokianalyysi

Suosi tapahtumavirta stdout:n sijaan

Ajoympäristö tulostaa jäsenneltyjä tapahtumia tracing:n kautta, mikä voi houkutella sieppaamaan ja jäsentämään niitä stdout:sta. Älä tee niin. Jäsennelty tapahtumavirta:

  • Selviää lokitasomuutoksista — tapahtumat lähetetään riippumatta RUST_LOG:stä.
  • Sisältää tyypitetyt hyötykuormat — ei merkkijonojen jäsennystä, ei muotomäärittelyjen ajautumista versioiden välillä.
  • Omaa vakaat tyypit — lokirivit on muotoiltu ihmisille ja voivat muuttua vapaasti; tapahtumatyypit ovat osa SDK-sopimusta.

Is this page helpful?

Sisällysluettelo

Muokkaa sivua
© 2026 Solana Foundation. Kaikki oikeudet pidätetään.