
fuels-ts 重提已失败交易报 UTXO does not exist 错误怎么处理【免费下载链接】fuels-tsFuel Network Typescript SDK项目地址: https://gitcode.com/GitHub_Trending/fu/fuels-ts在使用 fuels-tsFuel Network TypeScript SDK发送交易时sendTransaction成功并不代表交易成功执行。当交易在节点处理阶段回滚后很多开发者会直接把同一个transactionRequest再提交一次这时会收到FuelError: Transaction is not inserted. UTXO does not exist: {{utxoId}}以上为文档给出的报错格式示例{{utxoId}}是实际交易中被消耗资源对应的 UTXO ID。这个错误说明交易请求里引用的资源UTXO已经不存在了。本文说明该错误的两种成因以及如何用从零重建请求的方式安全重试交易。先判断失败发生在哪一步fuels-ts 中提交交易分两个阶段两者的失败含义不同如果sendTransaction直接 reject说明交易未被网络接受也就没有进入处理队列如果waitForResultreject说明交易已被节点接受但在处理过程中回滚。只有第二种情况已接受但处理时失败才需要重提并且重提方式有讲究。文档给出的标准提交与确认流程如下import { Provider, Wallet } from fuels; // LOCAL_NETWORK_URL 为你部署/连接的 Fuel 节点地址 // WALLET_PVT_KEY 为钱包私钥 const provider new Provider(LOCAL_NETWORK_URL); const wallet Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); const baseAssetId await provider.getBaseAssetId(); const transferAmount 1000; const transactionRequest await wallet.createTransfer( wallet.address, transferAmount, baseAssetId ); const response await wallet.sendTransaction(transactionRequest);然后调用waitForResult判断交易是否真正被处理const result await response.waitForResult(); // result.isStatusSuccess 为 true 表示交易处理成功 console.log(success, result.isStatusSuccess);验证方式waitForResultresolve 后用result.isStatusSuccess判断交易处理是否成功reject 则代表交易被接受但在处理中回滚。为什么重提原请求会报 UTXO does not exist文档解释了失败交易的资源消耗规则如果交易在处理中被回滚Fuel VM 仍然会消耗已充值的资源来支付失败前已用掉的 gas扣除 gas 费用后剩余资金会进入一个新建的 UTXOUnspent Transaction Output。原交易引用的那些 UTXO 因此已经不存在再提交同一个请求自然会被节点拒绝产生上述UTXO does not exist错误。以文档中的示例为例它故意把gasLimit设为0让交易以OutOfGas回滚然后重试同一个请求const transactionRequest await wallet.createTransfer( wallet.address, transferAmount, baseAssetId ); // Set the gasLimit to 0 to force revert with OutOfGas error transactionRequest.gasLimit bn(0); // Transaction will be successfully submitted const response await wallet.sendTransaction(transactionRequest); try { await response.waitForResult(); } catch (error) { if (/OutOfGas/.test((FuelErrorerror).message)) { transactionRequest.gasLimit bn(1000); // Re-submission will fail await wallet.sendTransaction(transactionRequest).catch((error2) { console.log(error2, error2); // 此处会输出 UTXO does not exist 错误 }); } }正确的处理方式从零重建请求再提交文档给出的修复方式是不要复用原transactionRequest而是重新创建一笔新的交易请求再提交。SDK 在重建请求时会基于账户当前实际可用的资源重新选币、组装交易try { await response.waitForResult(); } catch (error) { if (/OutOfGas/.test((FuelErrorerror).message)) { // 用最新状态重新创建请求而不是复用失败的那个 const transactionRequest2 await wallet.createTransfer( wallet.address, transferAmount, baseAssetId ); await wallet.sendTransaction(transactionRequest2); } }即捕获到waitForResult的错误后按业务逻辑修正失败原因如示例中调大 gasLimit 所对应的实际修复然后调用wallet.createTransfer或对应业务的请求创建方法生成新请求并提交。新请求引用的是失败后生成的新 UTXO因此不会再命中UTXO does not exist。另一种成因并发提交时的资源冲突同样的UTXO does not exist错误还可能来自另一类场景第一笔交易提交后尚未处理完SDK 就为第二笔交易选了同一批资源UTXO 或 Message。因为资源在第一笔交易完全处理前仍算未花费第二笔就会引用到已被第一笔消耗掉的资源节点拒绝插入并报以下错误之一Transaction is not inserted. Hash is already known Transaction is not inserted. UTXO does not exist: {{utxoID}} Transaction is not inserted. A higher priced tx {{txID}} is already spending this message: {{messageNonce}}针对这种场景Provider 提供resourceCacheTTL选项控制资源缓存时长SDK 默认缓存 20 秒防止在窗口期内复用已提交交易占用的资源传-1可禁用缓存new Provider(NETWORK_URL, { // Cache resources (Coins and Messages) for 5 seconds resourceCacheTTL: 5000, });需要注意的是文档给出的限制如果想不等待每笔交易完成就连续提交多笔账户必须有多余的 UTXO 可用。如果只有一个 UTXO第一笔交易会消耗它剩余金额会转成一个 ID 不同的新 UTXO后续交易无法复用原资源。小结先用sendTransaction/waitForResult定位失败阶段只有交易被接受但处理中回滚时才涉及重提。失败交易的 gas 已扣剩余资金进入新 UTXO原请求引用的 UTXO 不复存在——这就是UTXO does not exist的直接原因。处理方式是丢弃原transactionRequest从零重建请求再提交并发场景下配合resourceCacheTTL避免选到同一批资源。更多细节可查阅仓库中的 重提失败交易文档、Provider 选项文档以及示例代码 正确的重提交 与 会失败的重提交。【免费下载链接】fuels-tsFuel Network Typescript SDK项目地址: https://gitcode.com/GitHub_Trending/fu/fuels-ts创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考