调用合约mint发送交易后如何获取交易哈希追踪上链状态
交易哈希获取与状态追踪实现方案
你当前使用的Web3.js合约实例send方法本身就内置了交易全生命周期的事件回调,不需要额外引入其他工具,就可以在用户钱包确认签名、交易广播后立刻拿到交易哈希,同时可以直接监听交易上链结果,不需要单独写轮询逻辑查哈希状态。
核心实现逻辑
contract.methods.xxx.send() 执行时会按交易生命周期触发对应事件:
transactionHash:用户在钱包完成签名、交易被广播到链节点内存池时触发,回调参数就是你需要的交易哈希,这个时机早于交易打包上链receipt:交易被区块打包、执行完成时触发,回调参数包含交易执行结果、区块高度、gas消耗等信息,是判断交易是否真正成功的唯一可靠依据error:交易全流程任意环节出错时触发,包括用户拒绝签名、gas不足、合约执行回滚、交易广播失败等场景
注意:绝对不要在拿到
transactionHash的阶段就执行白名单移除操作,此时交易尚未被打包,存在被节点丢弃、gas不足被回滚的可能,必须等receipt返回且状态为成功时再修改白名单状态。
修改后的完整代码
const mint = async function (amount) { const id = await ethereum.request({ method: 'eth_chainId' }); if (mintAcc != "") { var totalCost = WEI_COST * amount; if (mintAcc.length > 0 && id == CHAIN_ID) { contract.methods.mint(amount).send({ from: mintAcc[0], to: CONTRACT_ADDRESS, value: String(totalCost), }) .on('transactionHash', (txHash) => { // 此处即可拿到交易哈希,可存储用于后续状态展示 console.log('交易已广播,哈希:', txHash); // 可在此处更新UI,提示用户"交易提交中,请等待链上确认" }) .on('receipt', (receipt) => { // 交易已打包上链,判断执行状态 if (receipt.status === true) { // 交易执行成功,再执行白名单移除逻辑 allowlist.delete(mintAcc[0]); alert(`铸造成功!交易哈希:${receipt.transactionHash}`); } else { alert('铸造失败,交易已回滚'); } }) .on('error', (err, receipt) => { console.error('交易异常:', err); if (receipt) { // 交易已上链但执行失败 alert('铸造失败,合约执行回滚'); } else { // 交易未广播,通常是用户拒绝钱包签名 alert('交易已取消'); } }); } } else { alert("Connect wallet first") } }
补充说明
- 如果需要额外的交易确认数校验(比如等1-2个区块确认后再判定最终成功,避免链上重组),可以在拿到
receipt后,再通过web3.eth.getBlockNumber()获取当前最新区块高度,和receipt.blockNumber做差值判断,确认数满足要求后再执行白名单移除操作,安全性更高。 - 如果你的项目用的是ethers.js,逻辑类似,
contract.mint().send()返回的交易对象会直接包含hash属性,等待tx.wait()即可拿到上链收据。
内容的提问来源于stack exchange,提问作者Zikkah
相关产品推荐
相关产品推荐

