如何回填以太坊ERC-20代币转账数据

  • QuickNode
  • 发布于 2024-04-21 21:32
  • 阅读 42

本文介绍了如何使用QuickNode的Streams功能来获取以太坊历史数据,特别是ERC-20代币转移数据,并将其存储到Postgres数据库中进行进一步分析。文章详细说明了如何创建Stream、过滤数据、设置数据库以及查询数据。

概述

在以太坊上检索历史数据可能具有挑战性,尤其是当你只需要特定的数据子集时。本指南将向你展示如何使用 QuickNode 的 Streams 来回溯填充历史以太坊数据,过滤出 ERC-20 代币转账,并将其发送到 Postgres 数据库以进行进一步分析。

让我们开始吧!

你将完成的任务

  • 在 QuickNode 上创建一个 Stream
  • 过滤指定历史范围内的以太坊区块以检索 ERC-20 代币转账
  • 创建一个 Supabase Postgres 数据库来存储过滤后的数据
  • 将过滤后的数据路由到你的数据库
  • 在你的数据库中创建一个包含解析后交易数据的表
  • 编写 SQL 查询以分析代币转账历史

在本指南结束时,你将拥有一个包含过滤后的以太坊 ERC-20 代币转账数据的 Postgres 数据库:

代币转账 Streams 数据库

你将需要的内容

  • 一个 QuickNode 账户
  • 对以太坊和 ERC-20 代币的基本了解
  • 一个 Postgres 数据库——在本指南中我们将使用 Supabase

步骤 1:创建一个 Stream

从你的 QuickNode 仪表板导航到 Streams 页面,点击“+ 创建 Stream”按钮,或直接在此处创建

在设置卡片中选择“以太坊”和“主网”网络,并选择“交易”作为数据集:

EVM Stream 设置

你可以选择为你的 Stream 起一个独特的名称,或使用自动生成的名称。你还会看到一个选项来设置 Stream 数据的批量大小。默认设置为 1,这适用于实时流。然而,对于历史数据回溯填充,更大的批量大小可能更高效。在本示例中,考虑将批量大小设置为 10,但请根据你的具体需求和用例进行调整。

对于“Stream 开始”选项,我们将使用当前时间的最新区块号作为起始区块。然而,如果你要回溯填充历史数据,你通常会选择一个更早的区块号作为起点。对于“Stream 结束”选项,勾选切换框并将结束区块号设置为比起始区块号多 100 个区块。这为我们提供了一个可管理的样本大小用于演示。可选地,你可以将 Stream 设置为不结束,但请注意这将导致持续的数据检索。

接下来,选择“在流式传输之前修改有效负载”,这一步至关重要,因为你将只过滤你需要的数据,而不必处理或为不需要的数据付费。

你现在应该会看到你的 main 函数的 JavaScript 代码编辑器。

function main(stream) {
  const data = stream.data

  return data;
}

如果你不过滤数据,你将收到指定区块范围内每个区块的所有交易数据,这可能会非常庞大且可能昂贵。返回的交易数据来自 QuickNode 的交易数据集,并为每笔交易返回一个 JSON 对象。以下是一个未过滤的交易对象的示例:

{
  "blockNumber": "17528802",
  "timeStamp": "1686787319",
  "hash": "0x9d8a0c70d50e3a6dd742264eba6eedc233715b28e1801dd4fbc504beb09d1465",
  "nonce": "1563",
  "blockHash": "0x9ef846bd228c7d11c5e7b63758ed1fda0c2d95b536f4e0bb37568f510e7d2ee1",
  "transactionIndex": "38",
  "from": "0x06fda0758c17416726f77cb11305eac4c6dc4ae1",
  "to": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
  "value": "0",
  "gas": "65428",
  "gasPrice": "14704923731",
  "isError": "0",
  "txreceipt_status": "1",
  "input": "0xa9059cbb000000000000000000000000d6df932a45c0f255f85145f286ea0b292b21c90b000000000000000000000000000000000000000000000000000000006b9aa980",
  "contractAddress": "",
  "cumulativeGasUsed": "2392341",
  "gasUsed": "52379",
  "confirmations": "2504025",
  "methodId": "0xa9059cbb",
  "functionName": "transfer(address _to, uint256 _value)"
}

在下一部分中,我们将深入修改过滤代码,使其仅跟踪 ERC-20 转账。

步骤 2:过滤 Stream 数据

现在,让我们调整过滤代码,使其仅跟踪具有 ERC-20 转账的交易。更新代码以匹配以下内容:

function main(stream) {
    try {
        const data = stream.data
        const transactions = data[0];
        const filteredTransactions = [];
        const transferMethodId = "0xa9059cbb";

        transactions.forEach(transaction => {
            if (typeof transaction === 'object' && transaction !== null && typeof transaction.input === 'string') {
                if (transaction.input.startsWith(transferMethodId)) {
                    const toAddress = "0x" + transaction.input.substr(34, 40);
                    const value = BigInt("0x" + transaction.input.substr(74));

                    filteredTransactions.push({
                        txHash: transaction.hash,
                        fromAddress: transaction.from,
                        toAddress: toAddress,
                        amount: value.toString(),
                        tokenContract: transaction.to,
                        blockNumber: transaction.blockNumber,
                    });
                }
            }
        });

        return filteredTransactions;
    } catch (e) {
        return {error: e.message};
    }
}

以下是过滤代码的回顾:

  1. main 函数接受一个 stream 参数,该参数预计包含有效负载数据(在本例中为交易数组)和 Stream 的元数据。
  2. 它初始化一个空数组 filteredTransactions 来存储过滤后的结果。
  3. transferMethodId 设置为 "0xa9059cbb",这是 ERC20 代币转账函数的方法 ID。
  4. 函数遍历 stream 数组中的每笔交易: a. 它检查交易是否是一个具有 input 属性的有效对象,并且 input 是一个字符串。 b. 如果 input 以转账方法 ID 开头,则处理该交易:
    • 从输入数据中提取 toAddress(输入的 4-23 字节,不包括方法 ID)。
    • 从输入数据中提取 value(转账金额)(从第 24 字节开始)并将其转换为 BigInt。 c. 然后,它构建一个包含相关交易详情的新对象,并将其添加到 filteredTransactions 数组中。
  5. 最后,它返回 filteredTransactions 数组。
  6. 如果在此过程中发生任何错误,它会捕获错误并返回一个包含错误消息的对象。

如果你点击“运行测试”,你应该会看到一些类似于以下的转账(假设你测试的区块号有代币转账交易)。你可以使用区块 20930625 进行测试以复制相同的结果:

过滤交易

现在,点击右下角的下一步,进入 Stream 目标设置。

步骤 3:设置你的数据库

在我们设置 Stream 的目标之前,我们需要一个地方来存储数据。在本指南中,我们将使用 Postgres 数据库。如果你没有数据库,可以在 Supabase 上创建一个。记住你的数据库密码,因为你稍后会需要它。

我们的 Stream 会自动在你的数据库中创建一个表。我们只需要向我们的 Stream 提供连接详细信息。

如果你使用的是 Supabase,请在“项目设置”页面的“数据库”选项卡下找到你的连接信息:

Supabase 数据库设置

准备好这些信息。现在,让我们回到我们的 Stream 设置页面。

步骤 4:设置你的 Stream 的目标

现在我们将告诉我们的 Stream 将数据发送到哪里:

  1. 转到你的 Stream 配置页面。
  2. 在“目标类型”中,选择“PostgreSQL”。
  3. 输入你的数据库连接详细信息(来自步骤 3)并为你的表命名——我们将使用 erc20-token-transfers

填写详细信息后,点击“测试目标”按钮测试连接。如果成功,你会看到一个绿色的弹出窗口:

Stream 配置

然后,点击“创建 Stream”以完成。

步骤 5:查看数据库并查询

现在你的 Stream 已创建,你应该在 Supabase 的表查看器中看到以太坊交易数据:

Supabase 表查看器 - 第 1 部分

我们可以看到每一行都包含 data 字段中的 JSON 对象。由于这些转账涵盖了所有类型的地址,你可能希望专注于特定的钱包地址。让我们设置一个新表,其中仅包含与特定地址匹配的转账。在我们这样做之前,我们需要找到一个要查找的地址。

回到你的“erc20-token-transfers”表,找到一个你想要调查的地址(即,在 data 列中,查找 fromAddresstoAddress 字段)。一旦你确定了一个你想要为其创建单独代币转账表的地址,你可以继续。

现在,导航到 Supabase 的“SQL 编辑器”选项卡。我们将一起输入以下查询(即,步骤 1 和步骤 2),然后点击“运行”来执行它们。

1. 创建表

CREATE TABLE specific_address_transfers (
    block_number BIGINT,
    network TEXT,
    tx_hash TEXT,
    amount NUMERIC,
    to_address TEXT,
    from_address TEXT,
    token_contract TEXT
);

这将创建一个名为 specific_address_transfers 的新表,其中包含转账详情的列。

2. 插入数据

INSERT INTO specific_address_transfers (
    block_number,
    network,
    tx_hash,
    amount,
    to_address,
    from_address,
    token_contract
)
SELECT
    (('x' || LTRIM(transfer->>'blockNumber', '0x'))::bit(64)::bigint),
    network,
    transfer->>'txHash',
    (transfer->>'amount')::NUMERIC,
    transfer->>'toAddress',
    transfer->>'fromAddress',
    transfer->>'tokenContract'
FROM
    "erc20-token-transfers",
    jsonb_array_elements(data::jsonb) AS transfer
WHERE
    transfer->>'fromAddress' = 'ETHEREUM_ADDRESS'
    OR transfer->>'toAddress' = 'ETHEREUM_ADDRESS';

SELECT COUNT(*) FROM specific_address_transfers;

这将通过以下方式将数据插入新表:

  • 从“erc20-token-transfers”表中选择(如果需要,请更新此表)
  • 解析 'data' 列中的 JSON 数据
  • 将十六进制区块号转换为 bigint
  • 过滤出指定地址是发送方或接收方的转账(你需要将 ETHEREUM_ADDRESS 值更新为有效的地址)
  • 计算给定地址的转账次数

重要提示:如果你使用的是不同的表名,你需要将表名 erc20-token-transfers 更新为你的表名。此外,将 ETHEREUM_ADDRESS 更新为你想要创建单独表以跟踪转账的有效以太坊地址。

现在,将两个查询都放入编辑器中,点击“运行”按钮以执行查询。你应该会看到“成功。没有返回行”或“计数:{数字}”的结果,并且在导航回“表编辑器”选项卡后,你会看到一个新表:

Supabase 表查看器 - 第 2 部分

现在就这样!你已经成功创建了一个用于跟踪 ERC-20 转账的数据管道,使用 Streams 和 Supabase。这只是你可以做的事情的开始。继续练习并实现你自己的有趣想法,同时探索更多 Streams 的功能。

下一步

想要继续构建这个想法吗?尝试以下操作:

  1. 扩展你的过滤器以包括其他代币标准(例如,ERC-721、ERC-1155 等),查看此指南以获取更多信息:使用 QuickNode Streams 和 Functions 的代币转账索引器
  2. 考虑为每个代币合约获取额外的元数据,例如代币小数(用于准确表示代币金额)、代币名称和代币符号。
  3. 创建查询以分析代币转账模式(如趋势或鲸鱼动向)
  4. 构建一个仪表板以可视化代币转账活动随时间的变化

查看这些额外资源,了解如何使用其他 QuickNode 产品构建在你新发现的知识之上:

无论你在构建什么,我们都希望听到你的声音。在 DiscordTwitter 上给我们留言,让我们知道你在做什么!

我们 ❤️ 反馈!

告诉我们 如果你有任何反馈或对新主题的请求。我们很乐意听取你的意见。

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

0 条评论

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