如何使用流技术回填以太坊 ERC-20 代币转账数据

Posted by QTCGBY 链上情报站 on August 1, 2025

在以太坊上检索历史数据可能颇具挑战性,尤其是当你只需要特定子集的数据时。本指南将详细介绍如何利用流技术来回填历史以太坊数据,筛选出 ERC-20 代币转账记录,并将其发送至 Postgres 数据库以供进一步分析。

准备工作

在开始之前,请确保您已准备好以下内容:

  • 一个可用的账户(立即注册
  • 对以太坊及 ERC-20 代币的基本了解
  • 一个 Postgres 数据库(本指南将使用 Supabase)

核心步骤详解

第一步:创建数据流

从您的控制面板导航至“流”页面,点击“+ 创建流”按钮。

  1. 网络选择:在设置卡中选择“Ethereum”和“Mainnet”网络,数据集选择“Transactions”。
  2. 流配置
    • 可为您的流设置一个独特的名称,或使用自动生成的名称。
    • 设置批次大小(Batch Size):实时流处理默认值为 1,但对于历史数据回填,较大的批次大小通常更高效。建议本例设置为 10,您也可根据具体需求调整。
    • 流起始点:使用给定时间的最新区块号作为起始区块。若回填历史数据,通常需选择更早的区块号作为起点。
    • 流结束点:勾选切换框,将结束区块号设置为起始区块后 100 个区块。这为演示提供了可管理的样本量。您也可选择不结束流,但请注意这将导致持续的数据检索。
  3. 数据处理:选择“在流式传输前修改有效负载”,此步骤至关重要,可确保仅筛选所需数据,避免清理或为不必要的数据付费。

您将看到一个 JavaScript 代码编辑器,用于您的 main 函数。初始代码通常如下:

function main(stream) {
  const data = stream.data;
  return data;
}

若不进行数据过滤,您将收到指定区块范围内所有交易数据,这可能非常庞大且成本高昂。返回的交易数据是一个 JSON 对象。

第二步:筛选流数据(仅限 ERC-20 转账)

现在,调整过滤器代码,使其仅跟踪 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 参数,该参数包含有效负载数据(本例中为交易数组)和流的元数据。
  2. 初始化一个空数组 filteredTransactions 用于存储筛选结果。
  3. transferMethodId 设置为 “0xa9059cbb”,这是 ERC20 代币转账函数的方法 ID。
  4. 函数遍历 stream 数组中的每个交易: a. 检查交易是否为具有 input 属性(字符串类型)的有效对象。 b. 如果 input 以转账方法 ID 开头,则处理该交易:
    • 从输入数据中提取 toAddress(输入的字节 4-23,不包括方法 ID)。
    • 从输入数据中提取 value(转账金额,从字节 24 开始)并将其转换为 BigInt。 c. 然后构建一个包含相关交易详情的新对象,并将其添加到 filteredTransactions 数组中。
  5. 最后,返回 filteredTransactions 数组。
  6. 若在此过程中发生任何错误,则捕获错误并返回包含错误消息的对象。

点击“运行测试”,您应能看到一些类似的转账记录(假设测试的区块号包含代币转账交易)。您可以使用区块 20930625 进行测试以复现相同结果。

第三步:设置您的数据库

在设置流的目标之前,我们需要一个存储数据的地方。本指南使用 Postgres 数据库。如果您没有数据库,可以在 Supabase 上创建一个。请记住您的数据库密码,后续步骤需要用到。

我们的流将自动在您的数据库中创建一张表。我们只需向流提供连接详细信息。

如果您使用 Supabase,请在“项目设置”页面的“数据库”选项卡下找到您的连接信息。请准备好此信息。

第四步:设置流的目标

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

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

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

然后,点击“创建流”完成设置。

第五步:查看数据库与查询

流创建成功后,您应该在 Supabase 的表查看器中看到以太坊交易数据:

我们可以看到每行包含一个 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 跟踪 ERC-20 转账的数据管道。这仅仅是开始,您可以探索流的更多功能并实践自己有趣的想法。

拓展应用与进阶探索

想要在此基础上继续构建吗?请尝试以下操作:

  1. 扩展过滤器:以包含其他代币标准(例如 ERC-721, ERC-1155 等)。
  2. 获取额外元数据:例如每个代币合约的小数位数(用于准确表示代币数量)、代币名称和代币符号。
  3. 创建查询:以分析代币转账模式(例如趋势或巨鲸动向)。
  4. 构建仪表板:以可视化随时间变化的代币转账活动。

👉 探索更多区块链数据策略 以获取实时工具和进阶方法,助您深入了解链上数据。

常见问题

回填历史数据时,批次大小应如何设置?

对于历史数据回填,建议使用较大的批次大小(例如 10 或更高)以提高效率。实时流处理则通常使用较小的批次大小(如 1)。您应根据数据量、网络状况和处理能力进行调整。

除了 ERC-20,还可以筛选哪些类型的交易?

您可以筛选任何具有特定方法 ID 的交易。常见的包括 ERC-721 的 safeTransferFrom (0x42842e0e)、ERC-1155 的 safeBatchTransferFrom (0x2eb2c2d6) 等。只需在过滤代码中替换相应的 transferMethodId 即可。

如果遇到连接数据库失败的问题,该如何排查?

首先检查数据库连接字符串(主机、端口、数据库名、用户名、密码)是否正确无误。确保数据库允许从流服务所在网络的连接(检查防火墙或安全组设置)。此外,验证数据库服务是否正常运行。

如何准确处理代币金额?为什么需要小数位数?

原始链上数据中的代币金额是以最小单位(如 Wei)表示的整数。要获得实际金额,需要除以 10^(代币小数位数)。因此,获取并存储代币合约的小数位数信息对于准确表示金额至关重要。您可以通过调用代币合约的 decimals() 函数来获取该信息。

此方法是否适用于其他以太坊兼容链?

是的,此方法通常适用于任何与以太坊虚拟机(EVM)兼容的区块链网络(如 BNB Smart Chain, Polygon, Avalanche C-Chain 等)。在创建流时,只需选择相应的网络即可。请注意,不同网络的区块数据范围和历史可用性可能有所不同。


通过本指南,您不仅学会了回填特定 ERC-20 代币转账数据,还掌握了构建自定义区块链数据管道的基本方法。这将为您进行链上数据分析、监控和应用开发奠定坚实的基础。