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/* ).
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.
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.
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.
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.
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
- Estrutura de Transação - a anatomia da resposta que este pacote decodifica
- Transações Versionadas - como as Tabelas de Pesquisa de Endereços dividem as contas em grupos estáticos e carregados
getTransaction- o método RPC que retorna a transação
Is this page helpful?