如何通过以太坊节点查询指定TOKEN的交易列表
基于Web3 + 以太坊节点查询指定ERC20代币最新交易实现方案
前置准备
- 安装Web3.js依赖:
npm install web3 - 准备可用的以太坊RPC节点地址(支持
eth_getLogs接口调用即可)
实现逻辑说明
ERC20标准代币的所有转账操作都会触发固定的Transfer(address from, address to, uint256 value)事件,该事件的固定topic0为0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef,我们可以通过查询以太坊日志的方式,筛选指定合约地址下的Transfer事件,得到和Etherscantokentx接口完全一致的交易数据。
代码实现示例
const { Web3 } = require('web3'); // 1. 初始化Web3实例,填入你的RPC节点地址 const web3 = new Web3('你的以太坊RPC节点地址'); // 2. 配置参数 const TOKEN_CONTRACT = '0xc748673057861a797275cd8a068abb95a902e8de'; // 目标代币合约地址 const TRANSFER_EVENT_TOPIC = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'; const QUERY_LIMIT = 10; // 要获取的最新交易数量 const BLOCK_RANGE = 2000; // 单次查询的块范围,可根据节点支持情况调整 // 3. Transfer事件ABI片段,用于解码日志 const erc20TransferAbi = [ { anonymous: false, inputs: [ { indexed: true, name: 'from', type: 'address' }, { indexed: true, name: 'to', type: 'address' }, { indexed: false, name: 'value', type: 'uint256' }, ], name: 'Transfer', type: 'event', }, ]; const transferInterface = new web3.eth.Contract(erc20TransferAbi); // 4. 查询交易逻辑 async function getLatestTokenTx() { // 获取当前最新块号 const latestBlock = await web3.eth.getBlockNumber(); const fromBlock = latestBlock - BigInt(BLOCK_RANGE); // 查询对应Transfer事件日志 const logs = await web3.eth.getLogs({ address: TOKEN_CONTRACT, topics: [TRANSFER_EVENT_TOPIC], fromBlock: fromBlock, toBlock: 'latest' }); // 解码日志,转换为可读格式 const parsedTxs = logs.map(log => { const decoded = transferInterface._parseLog(log); return { blockNumber: Number(log.blockNumber), timeStamp: Number((await web3.eth.getBlock(log.blockNumber)).timestamp), hash: log.transactionHash, from: decoded.args.from, to: decoded.args.to, value: decoded.args.value.toString(), contractAddress: TOKEN_CONTRACT, gasPrice: (await web3.eth.getTransaction(log.transactionHash)).gasPrice.toString(), gasUsed: (await web3.eth.getTransactionReceipt(log.transactionHash)).gasUsed.toString() // 可按需补充其他Etherscan接口返回的字段 }; }); // 按块号倒序,取指定数量的最新交易 parsedTxs.sort((a, b) => b.blockNumber - a.blockNumber); return parsedTxs.slice(0, QUERY_LIMIT); } // 调用测试 getLatestTokenTx().then(console.log).catch(console.error);
注意事项
- 若单次查询的块范围内日志数量不足要求的
QUERY_LIMIT,可扩大BLOCK_RANGE数值重试 - 多数公共RPC节点对单次日志查询的块范围有上限限制,建议不要超过10000块,避免请求被拒绝
- 如需提升查询效率,可缓存块号对应时间戳,避免重复调用
getBlock接口
内容的提问来源于stack exchange,提问作者JD BD
相关产品推荐
相关产品推荐

