Підсумок
@solana/transaction-introspection перетворює відповідь RPC getTransaction
на список інструкцій із реальними адресами. Він розв'язує індекси облікових
записів (включно з адресами таблиць пошуку), декодує внутрішні інструкції
Cross Program Invocation та обходить повне дерево інструкцій у порядку, який
використовує провідник.
Шукаєте інформацію про те, як програма перевіряє сусідні інструкції on-chain під час виконання? Це системна змінна Instructions — див. Інтроспекція інструкцій. Ця сторінка присвячена декодуванню транзакції off-chain з відповіді RPC.
Відповідь getTransaction не надає готового
списку інструкцій. Облікові записи зберігаються як числові індекси,
версійні транзакції розділяють
ці облікові записи на статичні ключі та адреси, завантажені з
таблиць пошуку адрес, а
внутрішні інструкції з Cross Program Invocation надходять як закодовані блоби у
метаданих транзакції.
@solana/transaction-introspection виконує це розв'язання за вас. Він декодує
дротову транзакцію, зіставляє кожен індекс облікового запису з його Address,
нормалізує внутрішні інструкції та повертає інструкції в тому самому порядку —
спочатку зовнішні, потім внутрішні — як показує провідник блоків. Повернуті
інструкції безпосередньо підключаються до згенерованих Codama клієнтів
(наприклад, @solana-program/*) за допомогою помічників parseXInstruction.
npm install @solana/transaction-introspection @solana/kit @solana/instructions @solana-program/token
Декодування відповіді
Отримайте транзакцію з кодуванням у форматі дроту та передайте відповідь до
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);
Наступні фрагменти повторно використовують rpcTx, compiledMessage та
loadedAddresses з цього кроку.
Отримуйте дані з кодуванням base64, base58 або json.
decodeTransactionFromRpcResponse відхиляє відповіді jsonParsed — це
кодування змушує вузол RPC розбирати інструкції на стороні сервера, тому на
клієнті не залишається нічого для декодування.
Обхід інструкцій
walkInstructions повертає кожну інструкцію — зовнішню та внутрішню — у вигляді
масиву в порядку, який показує блок-експлорер: кожна зовнішня інструкція, а
одразу після неї — внутрішні інструкції, породжені її CPI. Кожна інструкція
містить поле trace, що описує її місце в ієрархії викликів.
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);}
trace є дискримінованим об'єднанням: { kind: "outer", index } для інструкції
верхнього рівня або { kind: "inner", outerIndex, innerIndex, stackHeight? }
для інструкції CPI, вкладеної в зовнішню.
meta є необов'язковим — передавайте rpcTx.meta напряму, навіть якщо воно
може бути null. Без метаданих walkInstructions повертає лише зовнішні
інструкції.
Розбір за допомогою клієнта програми
Кожна інструкція з walkInstructions є ResolvedInstruction, тому вона
безпосередньо працює з предикатами з @solana/instructions та допоміжними
функціями identifyXInstruction / parseXInstruction, згенерованими клієнтами
@solana-program/*, — без жодного кроку перетворення.
Цей приклад перевіряє кожну інструкцію Token Program SyncNative у транзакції,
незалежно від того, чи виконувалась вона на верхньому рівні, чи всередині 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);}
Допоміжні функції нижнього рівня
walkInstructions охоплює більшість потреб, але пакет також надає компоненти,
на яких він побудований:
getInstructionsFromCompiledTransactionMessage(compiledMessage, loadedAddresses?)повертає лише зовнішні інструкції з розв'язаними акаунтами та декодованими даними.getInnerInstructionsFromMeta(meta, accountMetas)декодує внутрішні CPI-інструкції з метаданих транзакції.getAccountMetasFromCompiledTransactionMessage(compiledMessage, loadedAddresses?)повертає повний список акаунтів у порядку транзакції — вхідні дані, необхідні попередній допоміжній функції для розв'язання індексів акаунтів внутрішніх інструкцій.
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);
Використовуєте Rust?
Еквівалента цього пакету для Rust не існує. Щоб отримати розібрані інструкції
з Rust, запитайте UiTransactionEncoding::JsonParsed з
getTransaction і дозвольте вузлу RPC
розв'язати акаунти та внутрішні інструкції за вас.
Дивіться також
- Структура транзакції - анатомія відповіді, яку декодує цей пакет
- Версійні транзакції - як таблиці пошуку адрес розділяють акаунти на статичні та завантажені групи
getTransaction- метод RPC, який повертає транзакцію
Is this page helpful?