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

使用Golang调用智能合约方法时如何确认交易状态

Golang 等待链上交易确认、查询交易最终状态实现方案

核心逻辑说明

  • 你调用Mint方法拿到的transaction实例,仅代表交易已经在本地完成签名、提交到RPC节点的交易池,此时交易并未完成上链,和JS版本里拿到transactionHash时的状态一致
  • JS里await等待交易返回的效果,本质是SDK封装了后台轮询逻辑:持续向节点查询交易对应收据,直到交易被打包进区块、达到设定的区块确认数阈值后,才返回最终结果
  • 交易最终状态以交易收据的Status字段为准:值为1代表交易执行成功,值为0代表交易执行失败(触发合约回滚、Gas不足等)

通用等待交易确认实现

直接封装可复用的轮询等待函数,内置超时控制、确认数计算逻辑:

import (
	"context"
	"fmt"
	"math/big"
	"time"

	"github.com/ethereum/go-ethereum"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/ethclient"
)

// WaitTxConfirm 等待交易上链完成确认
// 参数: RPC客户端实例、交易哈希、要求的最小确认区块数、轮询查询间隔
// 返回: 交易执行收据、错误信息
func WaitTxConfirm(client *ethclient.Client, txHash common.Hash, minConfirm int64, pollInterval time.Duration) (*types.Receipt, error) {
	// 设置总超时时间,避免交易长期卡在交易池导致程序无限阻塞,可根据链类型调整
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
	defer cancel()

	ticker := time.NewTicker(pollInterval)
	defer ticker.Stop()

	for {
		select {
		case <-ctx.Done():
			return nil, fmt.Errorf("wait tx %s confirm timeout", txHash.Hex())
		case <-ticker.C:
			// 查询交易收据,返回NotFound说明交易还在交易池排队,继续下一轮查询
			receipt, err := client.TransactionReceipt(ctx, txHash)
			if err != nil {
				if err == ethereum.NotFound {
					continue
				}
				return nil, err
			}

			// 查询当前链上最新区块高度
			latestHeader, err := client.HeaderByNumber(ctx, nil)
			if err != nil {
				return nil, err
			}
			latestBlockNum := latestHeader.Number.Int64()
			txBlockNum := receipt.BlockNumber.Int64()

			// 计算当前交易的区块确认数
			curConfirm := latestBlockNum - txBlockNum
			if curConfirm >= minConfirm {
				return receipt, nil
			}
		}
	}
}

原有Mint逻辑改造示例

把等待逻辑接入你现有的Mint代码即可实现和JS版本一致的等待效果:

// 初始化RPC客户端,替换为你实际使用的节点RPC地址
client, err := ethclient.Dial("你的节点RPC地址")
if err != nil {
	panic(fmt.Sprintf("connect rpc failed: %v", err))
}

// 原有Mint发交易逻辑
transaction, err := erc721.Mint(trx, common.HexToAddress("my account"), big.NewInt(int64(i)))
if err != nil {
	fmt.Println("send mint tx failed: ", err)
	return
}
txHash := transaction.Hash()
fmt.Println("tx submitted, hash: ", txHash.String())

// 等待交易确认:私链/测试链可设1个确认,公链建议设6~12个确认避免链重组,轮询间隔建议2秒左右
receipt, err := WaitTxConfirm(client, txHash, 1, 2*time.Second)
if err != nil {
	fmt.Println("wait tx confirm failed: ", err)
	return
}

// 判断最终交易状态
if receipt.Status == types.ReceiptStatusSuccessful {
	fmt.Printf("mint success, packed in block %d\n", receipt.BlockNumber.Uint64())
} else {
	fmt.Printf("mint failed on chain, packed in block %d\n", receipt.BlockNumber.Uint64())
}

注意事项

  • 确认数阈值根据链类型调整:以太坊主网等公链建议设置6~12个确认,规避链重组导致的交易回滚风险;私有链、测试链无重组风险时可设为1,缩短等待时间
  • 轮询间隔不要设置过短,避免给RPC节点造成过大请求压力,公链建议25秒,私链可设为500ms1秒
  • 不要拿到交易哈希就判定交易成功,也不要查到收据就判定交易成功,必须校验收据的Status字段,交易执行失败时同样会被打包进区块生成收据
  • 总超时时间可根据实际场景调整,如果发的是低Gas交易可能需要更长等待时间,避免正常排队的交易被误判超时

内容的提问来源于stack exchange,提问作者Mr.c

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 22:36:20