Web3.js@1.7.5如何检测交易Pending状态?求加速交易可靠方案
可靠检测Pending交易并实现加速交易的方案
核心思路
加速交易的本质是替换同nonce、更高gasPrice的交易,前提是精准判断原交易是否处于Pending状态。以下是经过验证的可行方法:
1. 直接查询交易哈希的状态(最可靠)
通过web3.eth.getTransaction(txHash)直接获取交易详情,根据blockNumber字段判断状态:
blockNumber === null:交易处于Pending状态(已进入节点内存池,未上链)blockNumber !== null:交易已上链,可进一步通过交易收据确认是否成功
代码示例:
async function checkTransactionStatus(txHash) { try { const tx = await web3.eth.getTransaction(txHash); if (!tx) return 'unknown'; // 交易暂未被节点接收 if (tx.blockNumber === null) { return 'pending'; } else { // 验证上链后的交易结果 const receipt = await web3.eth.getTransactionReceipt(txHash); return receipt.status ? 'success' : 'failed'; } } catch (err) { console.error('查询交易状态失败:', err); return 'error'; } }
这个方法不依赖节点内存池的同步状态,只要交易被任何节点接收,就能精准判断Pending状态,是最稳定的方案。
2. 正确使用Web3.js的Pending交易过滤器
之前的过滤器用法可能有误,正确的Pending交易监听方式如下:
// 创建Pending交易过滤器 const pendingFilter = web3.eth.filter('pending'); // 监听新进入内存池的交易 pendingFilter.watch((error, txHash) => { if (!error) { // 判断是否是目标交易 if (txHash === yourTargetTxHash) { console.log('目标交易进入Pending状态'); // 这里可以触发加速逻辑 } } }); // 停止监听(记得在组件卸载时调用) // pendingFilter.stopWatching();
注意:该方法要求连接的节点支持内存池访问,部分免费公共节点(如Infura免费版)会限制此功能,建议使用付费节点或自行部署的以太坊节点。
3. 直接调用节点的txpool_content RPC方法
如果使用的节点开启了内存池API,可以通过txpool_content直接查询内存池中的所有交易:
async function isTxInPendingPool(txHash) { try { const response = await web3.currentProvider.send({ jsonrpc: '2.0', method: 'txpool_content', params: [], id: Math.floor(Math.random() * 1000) }); // 遍历Pending队列查找目标交易 const pendingTxs = response.result.pending; for (const account in pendingTxs) { for (const nonce in pendingTxs[account]) { const tx = pendingTxs[account][nonce]; if (tx.hash === txHash) { return true; } } } return false; } catch (err) { console.error('查询内存池失败:', err); return false; } }
此方法适合自行部署的节点,公共节点大概率不支持该RPC调用。
4. 加速交易的实现逻辑
确认交易处于Pending状态后,通过相同nonce、更高gasPrice重新发送交易即可实现加速:
async function accelerateTx(originalTxHash, newGasPriceGwei) { const originalTx = await web3.eth.getTransaction(originalTxHash); if (!originalTx || originalTx.blockNumber !== null) { throw new Error('交易不处于Pending状态,无法加速'); } // 构建新交易:nonce必须与原交易一致,gasPrice需高于原交易(建议高10%-20%) const newTxParams = { from: originalTx.from, to: originalTx.to, value: originalTx.value, data: originalTx.input, // 原交易的调用数据 nonce: originalTx.nonce, gasPrice: web3.utils.toWei(newGasPriceGwei.toString(), 'gwei'), gasLimit: originalTx.gas // 可保持原gasLimit或适当提高 }; // 通过MetaMask签名并发送交易 const acceleratedTxHash = await web3.eth.sendTransaction(newTxParams); return acceleratedTxHash; }
常见问题说明
- 之前
getBlock('pending')不可靠的原因:不同节点的内存池交易列表不一致,MetaMask发送的交易可能未同步到你连接的节点,导致无法在pending区块中查到。 - 交易收据的
status字段:true表示交易成功,false表示失败,仅当交易上链后才会返回,无法判断Pending状态。
内容的提问来源于stack exchange,提问作者mynameisConan
相关产品推荐
相关产品推荐

