Introspezione delle Transazioni

Riepilogo

@solana/transaction-introspection trasforma una risposta RPC getTransaction in un elenco di istruzioni con indirizzi reali. Risolve gli indici degli account (inclusi gli indirizzi delle lookup table), decodifica le istruzioni CPI interne e scorre l'intero albero delle istruzioni nell'ordine dell'explorer.

Stai cercando come un programma ispeziona le istruzioni adiacenti on-chain in fase di esecuzione? Questo è il sysvar Instructions - consulta Introspezione delle Istruzioni. Questa pagina riguarda la decodifica di una transazione off-chain da una risposta RPC.

Una risposta getTransaction non fornisce direttamente un elenco di istruzioni pronto all'uso. Gli account sono memorizzati come indici numerici, le transazioni con versione suddividono quegli account in chiavi statiche e indirizzi caricati dalle Address Lookup Table, e le istruzioni interne provenienti da Cross Program Invocation (CPI) arrivano come blob codificati nei metadati della transazione.

@solana/transaction-introspection esegue questa risoluzione automaticamente. Decodifica la transazione in formato wire, mappa ogni indice di account al suo Address corrispondente, normalizza le istruzioni interne e restituisce le istruzioni nello stesso ordine esterno-poi-interno visualizzato da un block explorer. Le istruzioni restituite si integrano direttamente con gli helper parseXInstruction dei client generati da codama (ad es., @solana-program/* ).

Terminal
npm install @solana/transaction-introspection @solana/kit @solana/instructions @solana-program/token

Decodifica la risposta

Recupera la transazione con una codifica in formato wire e passa la risposta a decodeTransactionFromRpcResponse.

Decode a transaction
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);

I frammenti di codice successivi riutilizzano rpcTx, compiledMessage e loadedAddresses da questo passaggio.

Effettua il fetch con la codifica base64, base58 o json. decodeTransactionFromRpcResponse rifiuta le risposte jsonParsed - quella codifica chiede al nodo RPC di analizzare le istruzioni lato server, quindi non rimane nulla da decodificare sul client.

Scorri le istruzioni

walkInstructions restituisce ogni istruzione - esterna e interna - come array nell'ordine mostrato da un block explorer: ogni istruzione esterna seguita immediatamente dalle istruzioni interne prodotte dai suoi CPI. Ogni istruzione contiene un campo trace che descrive la sua posizione nella gerarchia delle chiamate.

Walk every instruction
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);
}

Il campo trace è un'unione discriminata: { kind: "outer", index } per un'istruzione di primo livello, oppure { kind: "inner", outerIndex, innerIndex, stackHeight? } per un'istruzione CPI annidata sotto una esterna.

meta è opzionale - passa rpcTx.meta direttamente anche quando potrebbe essere null. Senza meta, walkInstructions restituisce solo le istruzioni esterne.

Analizza con un client di programma

Ogni istruzione restituita da walkInstructions è un ResolvedInstruction, quindi funziona direttamente con i predicati di @solana/instructions e con gli helper identifyXInstruction / parseXInstruction generati dai client @solana-program/* - senza alcun passaggio di conversione.

Questo esempio verifica ogni istruzione SyncNative del Token Program in una transazione, sia che sia stata eseguita al livello superiore sia all'interno di un CPI.

Find and parse SyncNative instructions
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);
}

Helper di livello inferiore

walkInstructions copre la maggior parte delle esigenze, ma il pacchetto espone anche i componenti su cui si basa:

  • getInstructionsFromCompiledTransactionMessage(compiledMessage, loadedAddresses?) restituisce solo le istruzioni esterne, con account risolti e dati decodificati.
  • getInnerInstructionsFromMeta(meta, accountMetas) decodifica le istruzioni CPI interne dai metadati della transazione.
  • getAccountMetasFromCompiledTransactionMessage(compiledMessage, loadedAddresses?) restituisce l'elenco completo degli account nell'ordine della transazione - l'input necessario all'helper precedente per risolvere gli indici degli account delle istruzioni interne.
Resolve outer and inner instructions separately
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);

Stai usando Rust?

Non esiste un equivalente Rust di questo pacchetto. Per ottenere istruzioni analizzate da Rust, richiedi UiTransactionEncoding::JsonParsed da getTransaction e lascia che il nodo RPC risolva gli account e le istruzioni interne per te.

Vedi anche

Is this page helpful?

Indice dei contenuti

Modifica pagina
© 2026 Solana Foundation. Tutti i diritti riservati.