Introspection de transaction

Résumé

@solana/transaction-introspection transforme une réponse RPC getTransaction en une liste d'instructions avec de vraies adresses. Il résout les indices de comptes (y compris les adresses de tables de correspondance), décode les instructions CPI internes, et parcourt l'arbre d'instructions complet dans l'ordre de l'explorateur.

Vous cherchez comment un programme inspecte les instructions sœurs on-chain à l'exécution ? Il s'agit du sysvar Instructions - voir Introspection d'instruction. Cette page concerne le décodage d'une transaction off-chain à partir d'une réponse RPC.

Une réponse getTransaction ne vous fournit pas directement une liste d'instructions prête à l'emploi. Les comptes sont stockés sous forme d'indices numériques, les transactions versionnées divisent ces comptes en clés statiques et en adresses chargées depuis les tables de correspondance d'adresses, et les instructions internes issues des Cross Program Invocation (CPI) arrivent sous forme de blobs encodés dans les métadonnées de la transaction.

@solana/transaction-introspection effectue cette résolution pour vous. Il décode la transaction filaire, associe chaque index de compte à son Address, normalise les instructions internes, et retourne les instructions dans le même ordre externe-puis-interne qu'un explorateur de blocs affiche. Les instructions retournées s'intègrent directement aux helpers parseXInstruction des clients générés par codama (par ex., @solana-program/* ).

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

Décoder la réponse

Récupérez la transaction avec un encodage au format filaire et passez la réponse à 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);

Les extraits suivants réutilisent rpcTx, compiledMessage, et loadedAddresses de cette étape.

Récupérez avec l'encodage base64, base58, ou json. decodeTransactionFromRpcResponse rejette les réponses jsonParsed - cet encodage demande au nœud RPC d'analyser les instructions côté serveur, il ne reste donc rien à décoder côté client.

Parcourir les instructions

walkInstructions retourne chaque instruction — externe et interne — sous forme de tableau dans l'ordre affiché par un explorateur de blocs : chaque instruction externe suivie immédiatement par les instructions internes produites par ses CPI. Chaque instruction contient un champ trace décrivant sa position dans la hiérarchie d'appels.

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);
}

Le trace est une union discriminée : { kind: "outer", index } pour une instruction de premier niveau, ou { kind: "inner", outerIndex, innerIndex, stackHeight? } pour une instruction CPI imbriquée sous une instruction externe.

meta est optionnel — passez rpcTx.meta directement même s'il peut être null. Sans métadonnées, walkInstructions retourne uniquement les instructions externes.

Analyser avec un client de programme

Chaque instruction issue de walkInstructions est une ResolvedInstruction, elle fonctionne donc directement avec les prédicats de @solana/instructions et les assistants identifyXInstruction / parseXInstruction générés par les clients @solana-program/* — sans étape de conversion.

Cet exemple audite chaque instruction Token Program SyncNative dans une transaction, qu'elle soit exécutée au niveau supérieur ou à l'intérieur d'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);
}

Assistants de bas niveau

walkInstructions couvre la plupart des besoins, mais le package expose également les éléments sur lesquels ilss'appuie :

  • getInstructionsFromCompiledTransactionMessage(compiledMessage, loadedAddresses?) retourne uniquement les instructions externes, avec les comptes résolus et les données décodées.
  • getInnerInstructionsFromMeta(meta, accountMetas) décode les instructions CPI internes à partir des métadonnées de la transaction.
  • getAccountMetasFromCompiledTransactionMessage(compiledMessage, loadedAddresses?) retourne la liste complète des comptes dans l'ordre de la transaction — l'entrée dont l'assistant précédent a besoin pour résoudre les indices de comptes des instructions internes.
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);

Vous utilisez Rust ?

Il n'existe pas d'équivalent Rust pour ce package. Pour obtenir des instructions analysées depuis Rust, demandez UiTransactionEncoding::JsonParsed auprès de getTransaction et laissez le nœud RPC résoudre les comptes et les instructions internes pour vous.

Voir aussi

Is this page helpful?

Table des matières

Modifier la page
© 2026 Fondation Solana. Tous droits réservés.