本文介绍了如何使用QuickNode的Streams功能来获取以太坊历史数据,特别是ERC-20代币转移数据,并将其存储到Postgres数据库中进行进一步分析。文章详细说明了如何创建Stream、过滤数据、设置数据库以及查询数据。
在以太坊上检索历史数据可能具有挑战性,尤其是当你只需要特定的数据子集时。本指南将向你展示如何使用 QuickNode 的 Streams 来回溯填充历史以太坊数据,过滤出 ERC-20 代币转账,并将其发送到 Postgres 数据库以进行进一步分析。
让我们开始吧!
在本指南结束时,你将拥有一个包含过滤后的以太坊 ERC-20 代币转账数据的 Postgres 数据库:
从你的 QuickNode 仪表板导航到 Streams 页面,点击“+ 创建 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 转账。
现在,让我们调整过滤代码,使其仅跟踪具有 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};
}
}
以下是过滤代码的回顾:
main
函数接受一个 stream
参数,该参数预计包含有效负载数据(在本例中为交易数组)和 Stream 的元数据。filteredTransactions
来存储过滤后的结果。transferMethodId
设置为 "0xa9059cbb",这是 ERC20 代币转账函数的方法 ID。stream
数组中的每笔交易:
a. 它检查交易是否是一个具有 input
属性的有效对象,并且 input
是一个字符串。
b. 如果 input
以转账方法 ID 开头,则处理该交易:
toAddress
(输入的 4-23 字节,不包括方法 ID)。value
(转账金额)(从第 24 字节开始)并将其转换为 BigInt。
c. 然后,它构建一个包含相关交易详情的新对象,并将其添加到 filteredTransactions
数组中。filteredTransactions
数组。如果你点击“运行测试”,你应该会看到一些类似于以下的转账(假设你测试的区块号有代币转账交易)。你可以使用区块 20930625
进行测试以复制相同的结果:
现在,点击右下角的下一步,进入 Stream 目标设置。
在我们设置 Stream 的目标之前,我们需要一个地方来存储数据。在本指南中,我们将使用 Postgres 数据库。如果你没有数据库,可以在 Supabase 上创建一个。记住你的数据库密码,因为你稍后会需要它。
我们的 Stream 会自动在你的数据库中创建一个表。我们只需要向我们的 Stream 提供连接详细信息。
如果你使用的是 Supabase,请在“项目设置”页面的“数据库”选项卡下找到你的连接信息:
准备好这些信息。现在,让我们回到我们的 Stream 设置页面。
现在我们将告诉我们的 Stream 将数据发送到哪里:
erc20-token-transfers
。填写详细信息后,点击“测试目标”按钮测试连接。如果成功,你会看到一个绿色的弹出窗口:
然后,点击“创建 Stream”以完成。
现在你的 Stream 已创建,你应该在 Supabase 的表查看器中看到以太坊交易数据:
我们可以看到每一行都包含 data
字段中的 JSON 对象。由于这些转账涵盖了所有类型的地址,你可能希望专注于特定的钱包地址。让我们设置一个新表,其中仅包含与特定地址匹配的转账。在我们这样做之前,我们需要找到一个要查找的地址。
回到你的“erc20-token-transfers”表,找到一个你想要调查的地址(即,在 data
列中,查找 fromAddress
或 toAddress
字段)。一旦你确定了一个你想要为其创建单独代币转账表的地址,你可以继续。
现在,导航到 Supabase 的“SQL 编辑器”选项卡。我们将一起输入以下查询(即,步骤 1 和步骤 2),然后点击“运行”来执行它们。
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
的新表,其中包含转账详情的列。
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;
这将通过以下方式将数据插入新表:
ETHEREUM_ADDRESS
值更新为有效的地址)重要提示:如果你使用的是不同的表名,你需要将表名
erc20-token-transfers
更新为你的表名。此外,将ETHEREUM_ADDRESS
更新为你想要创建单独表以跟踪转账的有效以太坊地址。
现在,将两个查询都放入编辑器中,点击“运行”按钮以执行查询。你应该会看到“成功。没有返回行”或“计数:{数字}”的结果,并且在导航回“表编辑器”选项卡后,你会看到一个新表:
现在就这样!你已经成功创建了一个用于跟踪 ERC-20 转账的数据管道,使用 Streams 和 Supabase。这只是你可以做的事情的开始。继续练习并实现你自己的有趣想法,同时探索更多 Streams 的功能。
想要继续构建这个想法吗?尝试以下操作:
查看这些额外资源,了解如何使用其他 QuickNode 产品构建在你新发现的知识之上:
无论你在构建什么,我们都希望听到你的声音。在 Discord 或 Twitter 上给我们留言,让我们知道你在做什么!
告诉我们 如果你有任何反馈或对新主题的请求。我们很乐意听取你的意见。
- 原文链接: quicknode.com/guides/qui...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!