Introspecção de Transações

Resumo

@solana/transaction-introspection transforma uma resposta RPC getTransaction em uma lista de instruções com endereços reais. Ele resolve índices de contas (incluindo endereços de tabelas de consulta), decodifica instruções CPI internas e percorre a árvore completa de instruções na ordem do explorador.

Procurando como um programa inspeciona instruções irmãs on-chain em tempo de execução? Esse é o sysvar de Instruções - veja Introspecção de Instruções. Esta página é sobre decodificar uma transação off-chain a partir de uma resposta RPC.

Uma resposta getTransaction não fornece diretamente uma lista de instruções pronta para uso. As contas são armazenadas como índices numéricos, transações versionadas dividem essas contas em chaves estáticas mais endereços carregados de Tabelas de Consulta de Endereços, e as instruções internas de Cross Program Invocation (CPIs) chegam como blobs codificados nos metadados da transação.

@solana/transaction-introspection faz essa resolução por você. Ele decodifica a transação wire, mapeia cada índice de conta de volta ao seu Address, normaliza as instruções internas e retorna as instruções na mesma ordem externa-então-interna que um explorador de blocos exibe. As instruções retornadas se conectam diretamente aos helpers parseXInstruction dos clientes gerados pelo codama (ex.: @solana-program/* ).

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

Decodificar a resposta

Busque a transação com uma codificação wire-format e passe a resposta para 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);

Os trechos restantes reutilizam rpcTx, compiledMessage e loadedAddresses desta etapa.

Busque com codificação base64, base58 ou json. decodeTransactionFromRpcResponse rejeita respostas jsonParsed - essa codificação solicita ao nó RPC que analise as instruções no lado do servidor, portanto não há nada a decodificar no cliente.

Percorrer as instruções

walkInstructions retorna todas as instruções - externas e internas - como um array na ordem em que um explorador de blocos exibe: cada instrução externa seguida imediatamente pelas instruções internas que seus CPIs produziram. Cada instrução possui um campo trace que descreve sua posição na hierarquia de chamadas.

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

O trace é uma união discriminada: { kind: "outer", index } para uma instrução de nível superior, ou { kind: "inner", outerIndex, innerIndex, stackHeight? } para uma instrução CPI aninhada sob uma externa.

meta é opcional - passe rpcTx.meta diretamente mesmo quando puder ser null. Sem metadados, walkInstructions retorna apenas as instruções externas.

Analisar com um cliente de programa

Cada instrução de walkInstructions é um ResolvedInstruction, portanto funciona diretamente com os predicados de @solana/instructions e os auxiliares identifyXInstruction / parseXInstruction gerados pelos clientes @solana-program/* - sem etapa de conversão.

Este exemplo audita cada instrução SyncNative do Token Program em uma transação, seja ela executada no nível superior ou dentro de um 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);
}

Auxiliares de nível inferior

walkInstructions cobre a maioria das necessidades, mas o pacote também expõe os componentes sobre os quais é construído:

  • getInstructionsFromCompiledTransactionMessage(compiledMessage, loadedAddresses?) retorna apenas as instruções externas, com contas resolvidas e dados decodificados.
  • getInnerInstructionsFromMeta(meta, accountMetas) decodifica as instruções CPI internas a partir dos metadados da transação.
  • getAccountMetasFromCompiledTransactionMessage(compiledMessage, loadedAddresses?) retorna a lista completa de contas na ordem da transação - a entrada que o auxiliar anterior necessita para resolver os índices de contas das instruções internas.
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);

Usando Rust?

Não existe um equivalente em Rust para este pacote. Para obter instruções analisadas a partir do Rust, solicite UiTransactionEncoding::JsonParsed de getTransaction e deixe o nó RPC resolver as contas e instruções internas para você.

Veja também

Is this page helpful?

Índice

Editar Página
© 2026 Fundação Solana. Todos os direitos reservados.