Zusammenfassung
@solana/transaction-introspection wandelt eine getTransaction RPC-Antwort
in eine Liste von Anweisungen mit echten Adressen um. Es löst Kontenindizes
(einschließlich Lookup-Table-Adressen) auf, dekodiert innere CPI-Anweisungen
und durchläuft den vollständigen Anweisungsbaum in Explorer-Reihenfolge.
Suchen Sie nach der Möglichkeit, wie ein Programm Geschwister- Anweisungen on-chain zur Laufzeit inspiziert? Das ist der Instructions-Sysvar – siehe Instruction Introspection. Diese Seite behandelt das Dekodieren einer Transaktion off-chain aus einer RPC-Antwort.
Eine getTransaction-Antwort liefert Ihnen
keine fertige Liste von Anweisungen. Konten werden als numerische Indizes
gespeichert,
versionierte Transaktionen
unterteilen diese Konten in statische Schlüssel sowie Adressen, die aus
Address Lookup Tables geladen
werden, und innere Anweisungen aus Cross Program Invocation (CPIs) kommen als
kodierte Blobs in den Transaktionsmetadaten an.
@solana/transaction-introspection übernimmt diese Auflösung für Sie. Es
dekodiert die Wire-Transaktion, ordnet jeden Kontenindex seiner Address zu,
normalisiert die inneren Anweisungen und gibt Anweisungen in derselben
Reihenfolge von außen nach innen zurück, wie sie ein Block-Explorer anzeigt. Die
zurückgegebenen Anweisungen lassen sich direkt in die von Codama generierten
Client-Hilfsmethoden (z. B. @solana-program/*) parseXInstruction einfügen.
npm install @solana/transaction-introspection @solana/kit @solana/instructions @solana-program/token
Antwort dekodieren
Rufen Sie die Transaktion mit einer Wire-Format-Kodierung ab und übergeben Sie
die Antwort an decodeTransactionFromRpcResponse.
import { createSolanaRpc, signature } from "@solana/kit";import { decodeTransactionFromRpcResponse } from "@solana/transaction-introspection";const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");const txid ="3jUKrQp1UGq5ih6FTDUUt2kkqUfoG2o4kY5T1DoVHK2tXXDLdxJSXzuJGY4JPoRivgbi45U2bc7LZfMa6C4R3szX";const rpcTx = await rpc.getTransaction(signature(txid), {commitment: "confirmed",encoding: "base64",maxSupportedTransactionVersion: 0}).send();if (!rpcTx) throw new Error(`Transaction ${txid} not found`);const { compiledMessage, loadedAddresses } =decodeTransactionFromRpcResponse(rpcTx);
Die verbleibenden Codeausschnitte verwenden rpcTx, compiledMessage und
loadedAddresses aus diesem Schritt wieder.
Abrufen mit base64, base58 oder json Kodierung.
decodeTransactionFromRpcResponse lehnt jsonParsed-Antworten ab – diese
Kodierung weist den RPC-Knoten an, Anweisungen serverseitig zu analysieren,
sodass auf dem Client nichts mehr zu dekodieren übrig bleibt.
Die Anweisungen durchlaufen
walkInstructions gibt jede Anweisung – äußere und innere – als Array in der
Reihenfolge zurück, die ein Block-Explorer anzeigt: jede äußere Anweisung
gefolgt von den inneren Anweisungen, die ihre CPIs erzeugt haben. Jede Anweisung
enthält ein trace-Feld, das beschreibt, wo sie sich in der Aufrufhierarchie
befindet.
import { walkInstructions } from "@solana/transaction-introspection";for (const ix of walkInstructions({compiledMessage,loadedAddresses,meta: rpcTx.meta})) {const location =ix.trace.kind === "outer"? `outer[${ix.trace.index}]`: `inner[${ix.trace.outerIndex}/${ix.trace.innerIndex}]`;console.log(location, ix.programAddress, ix.accounts?.length ?? 0);}
Das trace ist eine diskriminierte Union: { kind: "outer", index } für eine
Anweisung der obersten Ebene oder
{ kind: "inner", outerIndex, innerIndex, stackHeight? } für eine
CPI-Anweisung, die einer äußeren untergeordnet ist.
meta ist optional – übergeben Sie rpcTx.meta direkt, auch wenn es null
sein kann. Ohne Metadaten gibt walkInstructions nur die äußeren Anweisungen
zurück.
Mit einem Programm-Client parsen
Jede Anweisung von walkInstructions ist ein ResolvedInstruction und
funktioniert daher direkt mit den Prädikaten aus @solana/instructions sowie
den Hilfsfunktionen identifyXInstruction / parseXInstruction, die von den
@solana-program/*-Clients generiert werden – ohne Konvertierungsschritt.
Dieses Beispiel prüft jede Token Program SyncNative-Anweisung in einer
Transaktion, unabhängig davon, ob sie auf der obersten Ebene oder innerhalb
eines CPI ausgeführt wurde.
import {isInstructionForProgram,isInstructionWithAccounts,isInstructionWithData} from "@solana/instructions";import { walkInstructions } from "@solana/transaction-introspection";import {identifyTokenInstruction,parseSyncNativeInstruction,TOKEN_PROGRAM_ADDRESS,TokenInstruction} from "@solana-program/token";for (const ix of walkInstructions({compiledMessage,loadedAddresses,meta: rpcTx.meta})) {if (!isInstructionForProgram(ix, TOKEN_PROGRAM_ADDRESS)) continue;if (!isInstructionWithData(ix) || !isInstructionWithAccounts(ix)) continue;if (identifyTokenInstruction(ix) !== TokenInstruction.SyncNative) continue;const parsed = parseSyncNativeInstruction(ix);console.log(ix.trace, parsed);}
Hilfsfunktionen auf niedrigerer Ebene
walkInstructions deckt die meisten Anforderungen ab, aber das Paket stellt
auch die zugrunde liegenden Bausteine bereit:
getInstructionsFromCompiledTransactionMessage(compiledMessage, loadedAddresses?)gibt nur die äußeren Anweisungen mit aufgelösten Konten und dekodierten Daten zurück.getInnerInstructionsFromMeta(meta, accountMetas)dekodiert die inneren CPI-Anweisungen aus den Transaktionsmetadaten.getAccountMetasFromCompiledTransactionMessage(compiledMessage, loadedAddresses?)gibt die vollständige Kontoliste in Transaktionsreihenfolge zurück – die Eingabe, die der vorherige Helfer benötigt, um Kontoindizes innerer Anweisungen aufzulösen.
import {getAccountMetasFromCompiledTransactionMessage,getInnerInstructionsFromMeta,getInstructionsFromCompiledTransactionMessage} from "@solana/transaction-introspection";const outer = getInstructionsFromCompiledTransactionMessage(compiledMessage,loadedAddresses);const accountMetas = getAccountMetasFromCompiledTransactionMessage(compiledMessage,loadedAddresses);if (!rpcTx.meta) throw new Error("Transaction metadata missing");const inner = getInnerInstructionsFromMeta(rpcTx.meta, accountMetas);
Rust verwenden?
Es gibt kein Rust-Äquivalent dieses Pakets. Um geparste Anweisungen aus Rust
zu erhalten, fordern Sie UiTransactionEncoding::JsonParsed von
getTransaction an und lassen Sie den
RPC-Knoten Konten und innere Anweisungen für Sie auflösen.
Siehe auch
- Transaktionsstruktur - die Anatomie der Antwort, die dieses Paket dekodiert
- Versionierte Transaktionen - wie Address Lookup Tables Konten in statische und geladene Gruppen aufteilen
getTransaction- die RPC-Methode, die die Transaktion zurückgibt
Is this page helpful?