web3py监听以太坊pending交易报错交易不存在解决方案咨询
Web3py流式获取以太坊pending交易报错解决方案
错误原因
- 代码中调用了
getTransactionReceipt接口,该接口仅能返回已经被打包上链的交易收据,pending状态的交易还未上链,不存在交易收据,这是最直接的报错原因 - 你用WS连接监听pending哈希,却用HTTP连接的RPC实例查询交易,两次请求大概率落到公共RPC(如Infura)的不同节点上,不同节点的交易池不同步,会出现哈希已监听到但交易未同步到查询节点的情况
- 公共RPC节点普遍对pending交易池做了限制,仅同步高gas或公开广播的交易,部分私有池、低gas的pending交易不会存入公共节点缓存,天然查不到
- 监听到交易哈希的瞬间,节点还未完成交易在本地内存池的写入,立即查询会触发不存在报错
可行实现方案
方案1:优化现有代码逻辑(无需更换实现方式)
修改核心逻辑:
- 统一用同一个WS连接的实例做监听和交易查询,避免跨节点不同步
- 将
getTransactionReceipt替换为get_transaction接口,专门查询交易本体信息 - 增加重试延迟逻辑,等待节点完成交易池写入再查询
- 对多次重试失败的交易直接跳过,避免无效报错
优化后代码示例:
from web3 import Web3 import asyncio from hexbytes import HexBytes # 替换为你的WS服务商地址 Infura_WS = 'YOUR_WS_PROVIDER' # 统一用同一个WS实例做监听和查询,避免跨节点不同步 w3_ws = Web3(Web3.WebsocketProvider(Infura_WS)) async def handle_event(tx_hash): tx_hash_hex = HexBytes.hex(tx_hash) # 最多重试3次,每次间隔1s,等待节点同步交易 retry_count = 3 for i in range(retry_count): try: tx = w3_ws.eth.get_transaction(tx_hash_hex) # 按需提取交易字段 print(f"交易哈希: {tx_hash_hex}, 发送方: {tx['from']}, 接收方: {tx.get('to', '合约创建')}, 交易数据: {tx['input']}") break except Exception as e: if i == retry_count -1: # 最后一次重试失败直接跳过,部分交易本来就无法公开查询 pass await asyncio.sleep(1) async def log_loop(event_filter, poll_interval): while True: try: for event in event_filter.get_new_entries(): await handle_event(event) await asyncio.sleep(poll_interval) except Exception as e: print(e) def main(): block_filter = w3_ws.eth.filter('pending') loop = asyncio.get_event_loop() try: loop.run_until_complete( asyncio.gather( log_loop(block_filter, 2))) finally: loop.close() if __name__ == '__main__': main()
方案2:直接订阅全量pending交易(效率更高)
如果你的RPC服务商支持eth_subscribe接口的全交易返回,可以直接订阅完整的pending交易体,不用后续单独查哈希,大幅降低查询失败概率,适合高频率的pending交易监听场景。
注意事项
- Infura免费层对pending交易的查询和订阅都有频率限制,高并发场景建议升级付费计划或更换其他支持完整交易池的RPC服务商
- 始终存在部分无法查询到的pending交易,属于以太坊网络的正常情况,无需额外处理
- 若需要100%的pending交易覆盖率,建议自建以太坊全节点并开启交易池公开访问权限
内容的提问来源于stack exchange,提问作者JayK23
相关产品推荐
相关产品推荐

