如何在 Solana 上获取交易日志

  • QuickNode
  • 发布于 2024-08-08 17:18
  • 阅读 34

文章介绍了如何使用 Solana 的 getSignaturesForAddress 方法查询钱包、NFT、Candy Machine 等地址的交易历史,并详细讲解了如何设置环境、连接 QuickNode RPC 节点、编写交易查询脚本以及解析交易信息。

概述

需要提取与钱包关联的所有交易吗?想查看与糖果机关联的所有铸币交易?或者查看NFT的交易历史?Solana的 getSignaturesForAddress 方法是一个多功能工具,使获取交易历史变得轻而易举。

喜欢视频教程吗?跟随 Noah 学习如何使用 Solana web3.js 在 15 分钟内获取 Solana 交易日志

你将做什么

在本指南中,你将深入了解 Solana 交易的精彩世界!你将构建一个简单的脚本,可以查询一个地址(钱包、程序 ID、代币铸币等),并找到与之关联的所有交易历史。

你需要的条件

让我们开始吧!

设置你的环境

在终端中创建一个新的项目目录和文件 log.js

mkdir get_sol_tx
cd get_sol_tx
echo > log.js

安装 Solana web3 依赖项:

yarn init -y
yarn add @solana/web3.js@1

或者

npm init -y
npm install --save @solana/web3.js@1

在你选择的代码编辑器中打开 log.js,并在第 1 行引入 @solana/web3.js 并将其存储在一个常量 solanaWeb3 中:

**

const solanaWeb3 = require('@solana/web3.js');

声明一个你想要搜索的地址:

const searchAddress = 'YOUR_ADDRESS_HERE'; // 示例 'vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg'

注意:这可以是 Solana 上的任意有效地址(例如,钱包地址、铸币地址、程序地址)。如果你还没有地址,可以使用 'vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg' 作为示例。

好吧,我们准备开始了!

建立与 QuickNode RPC 的连接

要在 Solana 上构建,你需要一个 API 端点来连接网络。你可以使用公共节点或自己部署和管理基础设施;然而,如果你希望响应时间快 8 倍,你可以将繁重的工作留给我们。

我们将启动我们的节点在 Solana Devnet 下,但你可以启动符合你需求的节点。复制 HTTP 提供程序链接:

New Node

返回 log.js,创建一个常量 endpoint并将其分配给你的 QuickNode url。在下一行,将此常量作为参数传递给 Connection 函数,并将其存储在另一个常量叫 solanaConnection 中:

const endpoint = 'https://example.solana-devnet.quiknode.pro/000000/';
const solanaConnection = new solanaWeb3.Connection(endpoint);

太好了!你准备好构建你的搜索功能了。

创建交易查询

getSignaturesForAddress 方法将会在这里做大量的繁重工作。它的工作原理如下:

它将接受两个参数:

  • 要搜索的地址(必需):你想要查询的 公钥
  • 选项(可选):包含 3 个可选条目的对象:

    • before:在特定交易签名之前开始向后搜索

    • after:在特定交易签名之后开始向前搜索

    • limit:返回的最大交易数量 (请注意,最大和默认值为1,000)

它将返回一个 Promise,包含一个 ConfirmedSignatureInfo 的数组,这是一个包含关键交易信息的对象:

  • signature(交易 ID),

  • slot 和 blockTime(查看交易处理的时间),

  • err(如果有错误),以及

  • memo(如果与交易相关的任何备注)

定义一个新的 async 函数 getTransactions,该函数接受两个参数:addressnumTx

在我们的函数内部,调用 getSignaturesForAddress 方法,在 solanaConnection 的新实例上,并将输出保存到变量 transactionList

const getTransactions = async(address, numTx) => {
    const pubKey = new solanaWeb3.PublicKey(address);
    let transactionList = await solanaConnection.getSignaturesForAddress(pubKey, {limit:numTx});
}

这应该会给我们一个满足搜索条件的所有交易历史的数组。让我们以易于阅读的方式记录结果。

getTransactions 内部,创建一个 forEach 循环以记录每笔交易的信息:

const getTransactions = async(address, numTx) => {
    const pubKey = new solanaWeb3.PublicKey(address);
    let transactionList = await solanaConnection.getSignaturesForAddress(pubKey, {limit:numTx});
    transactionList.forEach((transaction, i) => {
        const date = new Date(transaction.blockTime*1000);
        console.log(`交易编号: ${i+1}`);
        console.log(`签名: ${transaction.signature}`);
        console.log(`时间: ${date}`);
        console.log(`状态: ${transaction.confirmationStatus}`);
        console.log(("-").repeat(20));
    })
}

运行你的代码!

如果一切设置正确,你应该可以调用你的函数并看到一些结果!将以下内容添加到 log.js 的末尾:

getTransactions(searchAddress,3);

现在在你的终端中输入:

node log.js

你应该看到类似这样的内容:

Transaction Search

哇!好简单,对吧?随便测试几种不同的钱包、NFT 代币地址和糖果机 ID。你可以看到,这个方法应该会产生类似的结果,这使得它在许多不同应用中非常方便。

恭喜!你成功地获取了交易……你可以到此为止,但如果你想看看我们还可以用交易签名做些什么,请继续阅读! 👇

解析交易

所以我们获得了一些关于交易历史的有用基本信息,但每笔交易做了什么呢?我们可以使用 Solana 的 getParsedTransaction 方法来提供更多详细信息。

getParsedTransaction 方法将接受一个已确认或已完成的交易签名,并返回一个 ParsedTransactionWithMeta 对象:

export type ParsedTransactionWithMeta = {
    /** 交易被处理时的插槽 */
    slot: number;
    /** 交易的详细信息 */
    transaction: ParsedTransaction;
    /** 交易产生的元数据 */
    meta: ParsedTransactionMeta | null;
    /** 处理交易时的 Unix 时间戳 */
    blockTime?: number | null;
    /** 交易消息的版本 */
    version?: TransactionVersion;
  };

这里有很多信息,我们在这个初级指南中不会进行详细说明,但我们确实想给出一个如何与这些对象互动的示例。

在你的 getTransactions 函数中,我们将声明两个新变量:signatureListtransactionDetails。我们将通过映射我们的 transactionList 来生成签名列表,并通过调用这些签名到 getParsedTransactions 来生成每笔交易的详细信息:

const getTransactions = async(address, numTx) => {
    const pubKey = new solanaWeb3.PublicKey(address);
    let transactionList = await solanaConnection.getSignaturesForAddress(pubKey, {limit:numTx});

    //添加此代码
    let signatureList = transactionList.map(transaction=>transaction.signature);
    let transactionDetails = await solanaConnection.getParsedTransactions(signatureList, {maxSupportedTransactionVersion:0});
    //--新代码结束

    transactionList.forEach((transaction, i) => {
        const date = new Date(transaction.blockTime*1000);
        console.log(`交易编号: ${i+1}`);
        console.log(`签名: ${transaction.signature}`);
        console.log(`时间: ${date}`);
        console.log(`状态: ${transaction.confirmationStatus}`);
        console.log(("-").repeat(20));
    })
}

当我们的 Promise 返回时,transactionDetails 将生成一个 ParsedTransactionWithMeta 对象的数组。让我们尝试查找一些有用的信息。

假设我们有兴趣找出针对特定交易我们交互的所有程序或智能合约。在我们原来的 forEach 循环中,在 date 声明后,创建一个新变量,transactionInstructions

        const transactionInstructions = transactionDetails[i].transaction.message.instructions;

这将利用我们的索引 i 来查找与循环中正在查询的相同交易的详细交易信息。由于每笔交易可以有多个指令或程序迭代,我们需要另一个循环来获取交易中的每个程序交互。在我们的循环中,在 确认状态 日志后,添加以下内容:

        transactionInstructions.forEach((instruction, n)=>{
            console.log(`---指令 ${n+1}: ${instruction.programId.toString()}`);
        })

我们在这里要做的是,对于每笔交易,查看每个交易指令并记录程序名称(如果存在)和程序 ID。

最终的函数应该如下所示:

const getTransactions = async(address, numTx) => {
    const pubKey = new solanaWeb3.PublicKey(address);
    let transactionList = await solanaConnection.getSignaturesForAddress(pubKey, {limit:numTx});

    let signatureList = transactionList.map(transaction=>transaction.signature);
    let transactionDetails = await solanaConnection.getParsedTransactions(signatureList, {maxSupportedTransactionVersion:0});

    transactionList.forEach((transaction, i) => {
        const date = new Date(transaction.blockTime*1000);
        const transactionInstructions = transactionDetails[i].transaction.message.instructions;
        console.log(`交易编号: ${i+1}`);
        console.log(`签名: ${transaction.signature}`);
        console.log(`时间: ${date}`);
        console.log(`状态: ${transaction.confirmationStatus}`);
        transactionInstructions.forEach((instruction, n)=>{
            console.log(`---指令 ${n+1}: ${instruction.programId.toString()}`);
        })
        console.log(("-").repeat(20));
    })
}

现在,再次运行你的脚本。在你的终端中输入:

node log.js

你应该看到类似这样的内容:

Transaction Search Part 2

干得好!我们的交易结果现在包括了我们交互的不同程序的详细信息!

如果愿意,你可以通过 这里 在 Solana explorer 上比较你的结果(确保在页面右上角更改以搜索相同的网络)。

结束

干得好!你现在已经深入了解 Solana 交易的精彩世界!

我们将在未来的指南中进一步介绍这些内容;但如果你渴望继续探索,请尝试通过运行一些类似查询来对你的 transactionDetails 数组进行实验,查看:

  • transactionDetails[i].meta

  • transactionDetails[i].transaction.message.accountKeys

要将这些概念付诸实践,请查看我们其他 Solana 教程 这里

订阅我们的 新闻通讯 以获取更多关于 Solana 的文章和指南。如果你有任何反馈,欢迎通过 Twitter 与我们联系。你也可以在我们的 Discord 社区服务器与我们聊天,这里有一些你见过的最酷的开发者 :)

  • 原文链接: quicknode.com/guides/sol...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
QuickNode
QuickNode
江湖只有他的大名,没有他的介绍。