解析Solana交易指令

本文将展示如何使用它们各自的IDL解析用Anchor框架编写的Solana上的原始交易。

解析Solana交易指令
一键发币: SUI | SOL | BNB | ETH | BASE | ARB | OP | POLYGON | AVAX | FTM | OK

你是否好奇过Shyft Translator和其他Solana浏览器是如何解析你的交易并以人类可读的格式显示的?在本文中,我们将向你展示如何解析一个使用Anchor框架编写的程序的交易,并将其转换为人类可读的格式。

1、获取IDL

要开始解析Anchor程序的交易,首先需要该程序的IDL。在Solana编程中,接口定义语言(IDL)指定了程序的公共接口,包括Solana程序的账户结构、指令和错误代码的定义。 IDL是.json文件,用于生成客户端代码,使用户能够方便地与Solana程序交互。

本文将演示如何解析来自Metaplex Candy Machine V2的交易。你可以通过点击这里查看该程序的IDL。要找到你程序的IDL,请执行anchor build命令来构建你的程序。构建过程完成后,IDL文件可以在以下路径找到:<your-program-root-folder>/target/idl/<your-program-name>.json

{
  "version": "0.1.0",
  "name": "demo_anchor",
  "instructions": [
    {
      "name": "initialize",
      "accounts": [
        {
          "name": "newAccount",
          "isMut": true,
          "isSigner": true
        },
        {
          "name": "signer",
          "isMut": true,
          "isSigner": true
        },
        {
          "name": "systemProgram",
          "isMut": false,
          "isSigner": false
        }
      ],
      "args": [
        {
          "name": "data",
          "type": "u64"
        }
      ]
    }
  ],
  "accounts": [
    {
      "name": "NewAccount",
      "type": {
        "kind": "struct",
        "fields": [
          {
            "name": "data",
            "type": "u64"
          }
        ]
      }
    }
  ]
}

2、使用BorshCoder解码交易指令

一旦你获得了IDL文件,就可以开始解析交易了。下面的代码片段展示了如何实现这一点:

const { clusterApiUrl, Connection } = require('@solana/web3.js');
const fs = require('fs/promises');
const { BorshCoder } = require('@coral-xyz/anchor')

const connection = new Connection(
  clusterApiUrl('mainnet-beta'), 'confirmed',
)

async function main() {
  // 加载IDL文件
  const fileContent = await fs.readFile('candy-machine-v2.json', 'utf-8');
  const borshCoder = new BorshCoder(JSON.parse(fileContent));

  // 示例签名
  const txn = await connection.getTransaction('2zvo8i6VqcN9D9kZeqDJZCDC4FMak7HBfZXLGieFNhLi5aPWmoGMmnZtG14xPptdGtKP8uDemiSdmsxXC9WMz44Y');

  // `4` 是与Candy Machine V2交互的指令索引
  const instruction = txn.transaction.message.instructions[4]
  const decodedIx = borshCoder.instruction.decode(instruction.data, 'base58')
  const accountMetas = instruction.accounts.map(
    (idx) => ({
      pubkey: txn.transaction.message.accountKeys[idx],
      isSigner: txn.transaction.message.isAccountSigner(idx),
      isWritable: txn.transaction.message.isAccountWritable(idx),
    }),
  );
  const formatted = borshCoder.instruction.format(decodedIx, accountMetas);

  console.log({ name: decodedIx.name, ...formatted });
}

main();

执行上述代码后,结果将如下所示。name字段表示函数名称,args字段包含函数所需的参数列表,accounts字段列出了此函数所需的账户。

{
  name: 'mintNft',
  args: [ { name: 'creatorBump', type: 'u8', data: '254' } ],
  accounts: [
    {
      name: 'Candy Machine',
      pubkey: [PublicKey [PublicKey(AcR4Hi7hxnyJdXY4HkcL2P94QrNYdkr4NNnfPPFK15Pg)]],
      isSigner: false,
      isWritable: true
    },
    {
      name: 'Candy Machine Creator',
      pubkey: [PublicKey [PublicKey(5TK4BXYVUQrpgxKHNn89kExpGnZSjoFQZ9w172oDv7Dq)]],
      isSigner: false,
      isWritable: false
    },
    {
      name: 'Payer',
      pubkey: [PublicKey [PublicKey(CNLE75xYtJXqiaYovC5gb7BGrKAzqXTLKNgdPskqTAtr)]],
      isSigner: true,
      isWritable: true
    },
    {
      name: 'Wallet',
      pubkey: [PublicKey [PublicKey(RTieWhhgy4j3Gr5FkUXX5MLpyEeaFJbquJ4xE8nsidE)]],
      isSigner: false,
      isWritable: true
    },
    {
      name: 'Metadata',
      pubkey: [PublicKey [PublicKey(EsW67JUMP8s5vRjNPVHGTJ5rHv9VvFxEkMzmRy91NS7o)]],
      isSigner: false,
      isWritable: true
    },
    {
      name: 'Mint',
      pubkey: [PublicKey [PublicKey(3nGmvv2zvm6JPe7THs56BZak3oUsqjYd7nvGypgBQZjH)]],
      isSigner: true,
      isWritable: true
    },
    {
      name: 'Mint Authority',
      pubkey: [PublicKey [PublicKey(CNLE75xYtJXqiaYovC5gb7BGrKAzqXTLKNgdPskqTAtr)]],
      isSigner: true,
      isWritable: true
    },
    {
      name: 'Update Authority',
      pubkey: [PublicKey [PublicKey(CNLE75xYtJXqiaYovC5gb7BGrKAzqXTLKNgdPskqTAtr)]],
      isSigner: true,
      isWritable: true
    },
    {
      name: 'Master Edition',
      pubkey: [PublicKey [PublicKey(9B3Q5ddBP7EZ6PAAmxSgf1ZoPQrjXhVsXDjYs79ZynFJ)]],
      isSigner: false,
      isWritable: true
    },
    {
      name: 'Token Metadata Program',
      pubkey: [PublicKey [PublicKey(metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s)]],
      isSigner: false,
      isWritable: false
    },
    {
      name: 'Token Program',
      pubkey: [PublicKey [PublicKey(TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA)]],
      isSigner: false,
      isWritable: false
    },
    {
      name: 'System Program',
      pubkey: [PublicKey [PublicKey(11111111111111111111111111111111)]],
      isSigner: false,
      isWritable: false
    },
    {
      name: 'Rent',
      pubkey: [PublicKey [PublicKey(SysvarRent111111111111111111111111111111111)]],
      isSigner: false,
      isWritable: false
    },
    {
      name: 'Clock',
      pubkey: [PublicKey [PublicKey(SysvarC1ock11111111111111111111111111111111)]],
      isSigner: false,
      isWritable: false
    },
    {
      name: 'Recent Blockhashes',
      pubkey: [PublicKey [PublicKey(SysvarS1otHashes111111111111111111111111111)]],
      isSigner: false,
      isWritable: false
    },
    {
      name: 'Instruction Sysvar Account',
      pubkey: [PublicKey [PublicKey(Sysvar1nstructions1111111111111111111111111)]],
      isSigner: false,
      isWritable: false
    }
  ]
}

值得一提的是,在这个例子中,我们解析了一个与多个程序交互的交易,例如系统程序、Candy Machine程序v2和Token Metadata程序。因此,如果你打算解析所有指令,你需要所有涉及程序的IDL。在我们的例子中,我们只使用了Candy Machine程序v2,解析了第4个指令。

3、结束语

本文帮助你了解如何自行构建解析管道。通过使用IDL,开发者可以与Solana程序通信并理解其交易的格式。然而,如果你不想自己管理这些方面,你可以使用Shyft的Transaction API,它为你处理复杂的可靠解析。


原文链接:How to parse Raw Transactions on Solana

DefiPlot翻译整理,转载请标明出处

免责声明:本站资源仅用于学习目的,也不应被视为投资建议,读者在采取任何行动之前应自行研究并对自己的决定承担全部责任。
通过 NowPayments 打赏