如何配置web3参数监听查询ETH/BSC原生代币转账日志事件
ETH/BSC原生代币转账事件监听正确配置方案
核心误区说明
web3.eth.subscribe('logs')、web3.eth.get_filter_logs 这类日志接口无法直接捕获原生代币(ETH/BNB)转账:
- 日志接口的数据源是EVM执行合约时触发的事件日志,原生代币转账是链上基础交易行为,不会生成对应的EVM日志,不存在可匹配的topic、合约地址参数,无论怎么配置address、topics字段都无法筛出原生转账。
- 所有区块浏览器展示的原生转账记录,都是通过遍历区块内全量交易、按规则筛选得到的,不是通过日志接口抓取的。
- 你要求的「address不限制、转账value大于0」的筛选规则,需要在遍历区块交易时实现。
web3.js 实现代码
用新区块订阅替代logs订阅,拿到区块全量交易后做筛选:
const Web3 = require('web3'); // 替换为你使用的以太坊/BSC节点RPC地址,仅websocket协议支持订阅能力,http协议不支持 const web3 = new Web3('wss://你的节点RPC地址'); // 订阅新出区块头 const nativeTransferSub = web3.eth.subscribe('newBlockHeaders', async (err, header) => { if (err) { console.error('区块订阅异常', err); return; } // 拉取区块全量交易详情 const block = await web3.eth.getBlock(header.number, true); for (const tx of block.transactions) { // 筛选规则:value>0 且 input字段为0x(纯原生转账,无合约调用数据) const isNativeTransfer = web3.utils.toBN(tx.value).gt(web3.utils.toBN(0)) && tx.input === '0x'; if (isNativeTransfer) { // 此处处理匹配到的原生转账交易 console.log('原生转账捕获', { hash: tx.hash, from: tx.from, to: tx.to, amount: web3.utils.fromWei(tx.value, 'ether') }) } } })
web3.py 实现代码
不要使用日志过滤器,改用区块扫描/新区块订阅逻辑,遍历交易做筛选:
from web3 import Web3 # 初始化web3实例,替换为对应链的RPC地址 w3 = Web3(Web3.WebsocketProvider('wss://你的节点RPC地址')) def is_native_transfer(tx): # 筛选规则:value大于0,input为空(无合约调用calldata) return tx.value > 0 and tx.input == b"" # 扫描指定区块内的原生转账 def scan_block(block_number: int): block = w3.eth.get_block(block_number, full_transactions=True) matched_txs = [tx for tx in block.transactions if is_native_transfer(tx)] for tx in matched_txs: print("原生转账捕获", { "hash": tx.hash.hex(), "from": tx["from"], "to": tx["to"], "amount": w3.fromWei(tx.value, "ether") }) # 调用示例:扫描最新区块 scan_block(w3.eth.block_number)
补充说明
- 如果需要捕获合约内部发起的原生代币转账(即内部交易),上述逻辑无法覆盖,需要额外遍历每笔交易的trace数据(节点需要开启debug/trace模块支持),按内部交易的value字段做筛选。
- 如果使用http协议的RPC节点,无法使用订阅接口,需要自行实现轮询逻辑定时拉取最新区块做扫描。
内容的提问来源于stack exchange,提问作者Tho Bui Ngoc
相关产品推荐
相关产品推荐

