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/* ).
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.
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.
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.
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.
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
- Structure des transactions - l'anatomie de la réponse décodée par ce package
- Transactions versionnées - comment les tables de recherche d'adresses répartissent les comptes en groupes statiques et chargés
getTransaction- la méthode RPC qui retourne la transaction
Is this page helpful?