You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Web3获取交易收据:如何等待变量赋值,避免TransactionNotFound报错

问题描述

我写了一段代码用来等待加密货币交易成功后的收据并提取数据,但实时运行时程序会崩溃——因为交易提交后,交易哈希transaction_tx不会立即被链上节点查到,需要几秒时间。目前我是让程序固定sleep 10秒,但想找个更靠谱的方法,能一直等到receipt变量成功赋值。当前获取收据的代码为:

receipt = web3provider.eth.getTransactionReceipt(transaction_tx)

我对async/await理解不足,觉得它不适用这种等待变量赋值的场景,想到的方案是用try-catch捕获错误,配合time.sleep(1)循环重试。请问这个方案可行吗?有没有更优的实现方式?

附相关Python代码:

import json
from ast import literal_eval
import time
from web3 import Web3
bsc = 'https://bsc-dataseed.binance.org/'
web3provider = Web3(Web3.HTTPProvider(bsc))

def getTradedAmount(tokenAddress, transaction_tx):
    time.sleep(10)
    receipt = web3provider.eth.getTransactionReceipt(transaction_tx)
    tx_json = Web3.toJSON(receipt)
    json_obj = json.loads(tx_json)
    log = json_obj['logs']
    length = len(log)
    for t in range(length):
        dec = literal_eval(log[t]['data'])
        if log[t]['address'] == tokenAddress:
            amountData = log[t]['data']

    print(amountData)


tx = "0x76094c8541e318fd2fa4479d48184cd66323d63fd889a3f30b973242f55eabbe"
token ="0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56"

#transaction_tx = buy(tokenAddress, 0.001)

getTradedAmount(token, tx)

报错信息:

web3.exceptions.TransactionNotFound: Transaction with hash: '0xfb0460c094b55f718fdf9b7fc49087d6586bfbc4886fd64e01f5eee4d11d48d5' not found.

解决方案

你的方案完全可行

try-catch配合循环重试是链上开发中等待交易确认的常规操作,比固定sleep 10秒灵活得多——既不会浪费时间等待不必要的时长,也能应对网络波动导致的交易延迟。

优化后的手动重试实现

给重试逻辑加上次数上限,避免无限循环,同时简化日志解析步骤:

import json
from ast import literal_eval
import time
from web3 import Web3
from web3.exceptions import TransactionNotFound

bsc = 'https://bsc-dataseed.binance.org/'
web3provider = Web3(Web3.HTTPProvider(bsc))

def getTradedAmount(tokenAddress, transaction_tx, max_retries=30, retry_interval=1):
    receipt = None
    # 循环重试,最多等30秒
    for _ in range(max_retries):
        try:
            receipt = web3provider.eth.getTransactionReceipt(transaction_tx)
            break
        except TransactionNotFound:
            time.sleep(retry_interval)
    
    if not receipt:
        raise ValueError(f"交易 {transaction_tx} 超时未确认")
    
    # 直接遍历receipt的logs(无需转JSON解析,web3返回的已是字典)
    for log in receipt['logs']:
        if log['address'] == tokenAddress:
            amountData = log['data']
            print(amountData)
            return amountData
    
    raise ValueError(f"未找到与代币 {tokenAddress} 相关的交易日志")

tx = "0x76094c8541e318fd2fa4479d48184cd66323d63fd889a3f30b973242f55eabbe"
token ="0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56"

getTradedAmount(token, tx)

更优的内置工具方案

web3.py本身提供了专门等待交易收据的函数wait_for_transaction_receipt,比自己写循环更简洁可靠:

from web3 import Web3
from web3.exceptions import TransactionNotFound

bsc = 'https://bsc-dataseed.binance.org/'
web3provider = Web3(Web3.HTTPProvider(bsc))

def getTradedAmount(tokenAddress, transaction_tx):
    # 等待交易确认,默认最多等60秒,每1秒查询一次
    receipt = web3provider.eth.wait_for_transaction_receipt(
        transaction_tx, 
        timeout=60, 
        poll_latency=1
        # 可选:指定等待的区块确认数,比如confirmations=2,更稳妥
    )
    
    for log in receipt['logs']:
        if log['address'] == tokenAddress:
            amountData = log['data']
            print(amountData)
            return amountData
    
    raise ValueError(f"未找到与代币 {tokenAddress} 相关的交易日志")

tx = "0x76094c8541e318fd2fa4479d48184cd66323d63fd889a3f30b973242f55eabbe"
token ="0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56"

getTradedAmount(token, tx)

这个函数的优势:

  • 内置重试逻辑,无需手动写循环
  • 可自定义超时时间、查询间隔
  • 支持指定等待的区块确认数,进一步保证交易的最终性

关于async/await的说明

如果你的项目是异步架构(比如使用AsyncHTTPProvider),async/await完全适用,web3.py提供了异步版本的async_web3,可以用await web3.eth.wait_for_transaction_receipt(tx_hash)实现异步等待。但如果是同步代码,用上面的同步方案就足够了。

内容的提问来源于stack exchange,提问作者Soma Juice

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 17:09:32