如何查询以太坊私有节点上自行部署的ERC-20代币持币地址与交易记录
ERC20代币交易记录与持币列表查询方案
ERC20标准本身没有提供查询全量交易、全量持币地址的内置接口,这类聚合数据需要通过扫描链上Transfer事件自行计算获得,具体实现方法如下:
1 查询所有代币交易记录
所有ERC20代币的转账操作都会触发Transfer事件,你可以通过web3直接过滤合约的该类事件获取全量交易记录,参考代码:
from web3 import Web3 w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545')) contract_address = "替换为你的ERC20合约地址" abi = "替换为你的ERC20合约ABI" contract_instance = w3.eth.contract(address=contract_address, abi=abi) # 计算Transfer事件的签名哈希 transfer_event_signature = w3.keccak(text="Transfer(address,address,uint256)").hex() # 过滤从创世块到最新块的所有Transfer事件 transfer_logs = w3.eth.get_logs({ "fromBlock": 0, "toBlock": "latest", "address": contract_address, "topics": [transfer_event_signature] }) # 解析日志得到交易详情 all_transactions = [] for log in transfer_logs: parsed_log = contract_instance.events.Transfer().process_log(log) all_transactions.append({ "交易哈希": parsed_log["transactionHash"].hex(), "转出地址": parsed_log["args"]["from"], "转入地址": parsed_log["args"]["to"], "转账金额": parsed_log["args"]["value"], "区块高度": parsed_log["blockNumber"] }) # 输出所有交易 for tx in all_transactions: print(tx)
2 查询所有代币持有者列表
基于上面获取的全量Transfer事件,自行维护余额映射,过滤掉余额为0的地址即可得到持币者列表,参考代码:
balances = {} for log in transfer_logs: parsed_log = contract_instance.events.Transfer().process_log(log) from_addr = parsed_log["args"]["from"] to_addr = parsed_log["args"]["to"] value = parsed_log["args"]["value"] # 处理转出地址余额 if from_addr in balances: balances[from_addr] -= value else: balances[from_addr] = -value # 处理转入地址余额 if to_addr in balances: balances[to_addr] += value else: balances[to_addr] = value # 过滤余额大于0的地址即为持币者列表 holders = [addr for addr, balance in balances.items() if balance > 0] print("所有持币地址:", holders)
注意事项
- 若你的私有节点做过状态剪枝,需要开启归档模式才能查询到早期的事件日志
- 如果链上数据量较大,建议将扫描得到的交易和余额数据存入本地数据库做增量更新,避免每次查询都全量扫块
- 若你的ERC20合约包含mint、burn等额外逻辑,需要对应处理相关事件,避免余额计算错误
内容的提问来源于stack exchange,提问作者Trimantra Software Solution
相关产品推荐
相关产品推荐

