Fuel TypeScript SDK 交易组装实战:assembleTx 全参数解析与 Fuel UTXO 找零机制

发布时间:2026/11/4 0:48:10

Fuel TypeScript SDK 交易组装实战:assembleTx 全参数解析与 Fuel UTXO 找零机制 Fuel TypeScript SDK 交易组装实战assembleTx 全参数解析与 Fuel UTXO 找零机制【免费下载链接】fuels-tsFuel Network Typescript SDK项目地址: https://gitcode.com/GitHub_Trending/fu/fuels-tsassembleTx是 Fuel TypeScript SDKfuels-ts中负责交易预组装的核心方法它接收一份尚未完整的交易请求自动补齐输入inputs、输出outputs与交易策略policies并完成 gas 价格估算与费用校验。SDK 中几乎所有高层 API账户转账、合约部署、Blob 部署、合约调用最终都经由它落地。读完本文你将掌握assembleTx的完整参数语义、返回结构理解 Fuel 基于 UTXO 的找零change机制对谁收到找零的决定性影响并能在多账户、多资产场景下正确、安全地组装一笔可签名上链的交易。assembleTx 能为你做什么在 Fuel 中交易不能只携带想做什么例如向某个地址转 100 个 base asset还必须明确说明资源从哪来输入 UTXO、找零给谁change 输出、费用由谁承担fee payer以及采用何种 gas 价格。手工拼装这些字段极易出错而assembleTx正是把这一复杂过程收敛为一个方法调用。根据官方指南见 assemble-tx.md它主要处理以下事项不同资产所需的币数量coin quantity汇总指定费用支付账户fee payergas 与费用估算predicate谓词的估算资源排除忽略特定资源 ID避免把某笔 UTXO 或消息重复计入。其方法签名与入口位于 provider.tsasync assembleTxT extends TransactionRequest( params: AssembleTxParamsT ): PromiseAssembleTxResponseT注意方法属于Provider实例因此调用前需要一个已连接网络的Provider本地节点可参考各示例中使用的LOCAL_NETWORK_URL。AssembleTxParams参数全解assembleTx的核心输入类型为AssembleTxParamsT其完整定义位于 provider.tsexport type AssembleTxParamsT extends TransactionRequest TransactionRequest { // The transaction request to assemble request: T; // Coin quantities required for the transaction, optional if transaction only needs funds for the fee accountCoinQuantities?: AccountCoinQuantity[]; // Account that will pay for the transaction fees feePayerAccount: Account; // Block horizon for gas price estimation (default: 10) blockHorizon?: number; // Whether to estimate predicates (default: true) estimatePredicates?: boolean; // Resources to be ignored when funding the transaction (optional) resourcesIdsToIgnore?: ResourcesIdsToIgnore; // Amount of gas to reserve (optional) reserveGas?: BigNumberish; };各参数含义与默认值如下参数是否必填默认值说明request必填无待组装的交易请求如ScriptTransactionRequest、CreateTransactionRequest等。feePayerAccount必填无负责支付交易费用的账户。accountCoinQuantities可选[]交易需要的各资产币数量数组。若交易只需要覆盖手续费例如纯转账且资产由 fee payer 提供可省略。blockHorizon可选10gas 价格估算时向前预看的区块数量。estimatePredicates可选true是否对 predicate 进行 gas 估算。resourcesIdsToIgnore可选无资助交易时需忽略的资源UTXO 或 message。reserveGas可选无额外预留的 gas 数量。这些默认值并非只在文档层面约定而是直接体现在实现里。在 provider.ts 中可以看到解构参数时显式写出的默认值const { request, reserveGas, resourcesIdsToIgnore, feePayerAccount, blockHorizon 10, estimatePredicates true, accountCoinQuantities [], } params;accountCoinQuantities 的内部结构每个AccountCoinQuantity条目包含以下字段字段必填默认行为说明amount必填无需要的币数量费用部分无需手动计入系统会自动叠加 base asset 手续费。assetId必填无资产的 ID可先通过provider.getBaseAssetId()取得 base asset。account可选默认为根级feePayerAccount提供该部分资源的账户。changeOutputAccount可选默认为account若account未提供则回退到feePayerAccount接收该assetId全部已花费资源找零的账户。account / changeOutputAccount 的默认行为account与changeOutputAccount都允许省略它们的缺省回退链在实现中对应如下代码provider.tsconst { amount, assetId, account feePayerAccount, changeOutputAccount } quantity; const changeAccountAddress changeOutputAccount ? changeOutputAccount.address.toB256() : account.address.toB256();即未指定account时直接回退到根级feePayerAccount未指定changeOutputAccount时回退到本条目的account若account也缺省则最终落到feePayerAccount。官方 default-behaviors.ts 示例逐一演示了这三种写法const accountCoinQuantities: AccountCoinQuantity[] [ { amount: 100, assetId: baseAssetId, // account 未指定 默认取 feePayerAccount // changeOutputAccount 未指定 默认取 feePayerAccount }, { amount: 200, assetId: TestAssetId.A.value, account: accountA, // changeOutputAccount 未指定 默认取 accountA }, { amount: 300, assetId: TestAssetId.B.value, account: accountB, changeOutputAccount: accountC, // account 与 changeOutputAccount 均显式指定 }, ];实现中的一个隐含细节fee payer 自动补位从源码看provider.ts 还处理了一种边界情况如果feePayerAccount没有出现在任何accountCoinQuantities条目中assembleTx会自动把它作为金额为 0 的 base asset 需求量追加进 required balances 末尾其 change 输出指向baseAssetChange即已显式声明的 base asset change 地址或 fee payer 自身地址。这意味着费用虽然由 fee payer 承担但找零归属会被统一收敛到你声明的 change 策略上——这是理解后续谁收到找零问题的关键实现基础。返回值 AssembleTxResponse方法返回AssembleTxResponseT定义同样在 provider.tsexport type AssembleTxResponseT extends TransactionRequest TransactionRequest { assembledRequest: T; // 已完整组装、带齐 inputs/outputs/policies 的交易请求 gasPrice: BN; // 估算出的 gas 价格 receipts: TransactionResultReceipt[]; // 解析后的 dry run receipts rawReceipts: TransactionReceiptJson[]; // 未解析的原始 receipts };各字段说明assembledRequest组装完成、可直接签名提交的交易请求gasPrice按blockHorizon估算的 gas 价格receiptsdry run 返回、已解析的 receiptsrawReceiptsdry run 返回的未解析 receipts。需要特别说明的是assembleTx在返回前会对交易做一次 dry run 以验证其可行性。若 dry run 失败实现会读取status.type DryRunFailureStatus的分支并通过extractDryRunError抛出解析后的错误而不会静默返回一笔注定失败的交易provider.ts。基本用法组装一笔可签名的转账basic-usage.ts 给出了完整的入门示例。核心流程如下const provider new Provider(LOCAL_NETWORK_URL); const baseAssetId await provider.getBaseAssetId(); const accountA Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); const accountB Wallet.fromPrivateKey(WALLET_PVT_KEY_2, provider); const transferAmount 100; // 1. 先声明想做什么向 accountB 输出 100 个 base asset const request new ScriptTransactionRequest(); request.addCoinOutput(accountB.address, transferAmount, baseAssetId); const accountCoinQuantities: AccountCoinQuantity[] [ { amount: transferAmount, assetId: baseAssetId, account: accountA, changeOutputAccount: accountA, // 可选 }, ]; // 2. 组装补齐 inputs / outputs / policies const { assembledRequest, gasPrice, receipts } await provider.assembleTx({ request, accountCoinQuantities, feePayerAccount: accountA, blockHorizon: 10, estimatePredicates: true, }); // 3. 组装完成后即可签名并提交 const submit await accountA.sendTransaction(assembledRequest); await submit.waitForResult();使用要点request只描述业务意图这里是为accountB增加一笔 coin 输出不要手工去填输入与 change那是assembleTx的职责assembleTx会在需要时自动补入 base asset 手续费所需资源因此accountCoinQuantities中的amount无需包含费用返回的assembledRequest是待签名状态的请求随后用发送方这里是accountA的sendTransaction提交并waitForResult等待上链。为什么必须关注 changeFuel 的 UTXO 找零模型account与changeOutputAccount看似只是两个可选字段但官方文档用大量篇幅专门提醒开发者注意它们——原因在于 Fuel 的UTXO 记账模型与以太坊的账户模型存在本质差异。整笔消费UTXO 模型下没有部分花费在 Fuel 中一笔交易只要把某个 UTXO 列入输入就会整体消费该 UTXO即使业务上只需要其中一小部分。官方文档给出过一个直观例子假设你有一个价值 10 ETH 的 UTXO。当你创建一笔只想转出 1 Gwei 的交易时整个 10 ETH 的 UTXO 仍会被消耗。交易随后会为接收方创建一个 1 Gwei 的 UTXO为剩余部分10 ETH - 1 Gwei - 费用再创建一个 UTXO并发送到OutputChange中指定的地址。这里的剩余部分就是找零change而OutputChange决定了找零落到谁手里。可以说OutputChange保证了你的钱还能回到你手中。Fuel 约束每个 assetId 每笔交易最多一个 change 输出Fuel 有一条关键规则一笔交易内每个assetId只允许存在一个OutputChange。这意味着如果一笔交易同时花销了多个账户对同一资产比如都是 ETH的 UTXO那么只有一个人能收到这笔资产的全部找零——也就是OutputChange上写明的那位。若处理不当就会出现一个账户出了钱、另一个账户拿了找零的意外结果。多账户场景下的找零归属multiple-output-change 示例把上面两条规则叠加到assembleTxaccountCoinQuantities[].changeOutputAccount就是你在 SDK 层面显式指定这个 assetId 的找零归谁的开关。官方 multiple-output-change.ts 演示了这一典型场景let { assembledRequest } await provider.assembleTx({ request, feePayerAccount: accountA, accountCoinQuantities: [ { amount: transferAmount, assetId: baseAssetId, account: accountB, /** * accountB 将收到找零。虽然这里显式声明 * 但即使不写它也会默认回退到 account 属性此处同样是 accountB。 */ changeOutputAccount: accountB, }, ], });在这个例子中accountB的资源被显式请求进accountCoinQuantities作为本次转账金额的提供方accountA是feePayerAccount因此它也会投入资源来覆盖手续费changeOutputAccount被显式设为accountB。最终效果是无论交易中消费了谁的 UTXO包括accountA为了付手续费投进去的 UTXO这笔资产的全部找零都会发给accountB。官方文档给出了一个极具警示性的推演假设accountA投入了一枚 10 ETH 的 UTXO由于 UTXO 必须整笔消费交易会花掉完整的 10 ETH而剩余找零会流向accountB而非accountA——这正是只配置了 fee payer却没仔细想 change 归属可能踩中的坑。因此代码后续还须由实际出资账户完成见证人签名assembledRequest await accountB.populateTransactionWitnessesSignature(assembledRequest); const submit await accountA.sendTransaction(assembledRequest); await submit.waitForResult();底层原理assembleTx 在 provider 内部做了什么结合仓库源码可以看清assembleTx的完整数据流provider.ts归一化余额请求遍历accountCoinQuantities对每条生成{ account, amount, assetId, changePolicy }当assetId是 base asset 时额外记录该条目的 change 地址作为baseAssetChangefee payer 自动补位若 fee payer 未出现在任何条目中以金额0追加一条 base asset 余额请求保证费用有账户兜底资源排除处理调用adjustResourcesToIgnoreForAddresses基于本次交易涉及的地址集合裁剪resourcesIdsToIgnore——配合 SDK 内部的资源缓存避免把某地址已占用的资源重复列入输入同时这也是传入该参数的意义所在调用 GraphQL 组装端点将request.toTransactionBytes()、blockHorizon、feeAddressIndexfee payer 在余额请求数组中的下标、requiredBalances、estimatePredicates、excludeInput、reserveGas一并提交给 Fuel Core 的operations.assembleTx由其执行估算与 dry run回填并校验把节点返回的 witnesses / inputs / outputs 反序列化后写回request若 dry run 状态为失败则解析 receipts 并抛错。账户解析支持 predicateaccountCoinQuantities与feePayerAccount的账户最终会交给 assemble-tx-helpers.ts 中的resolveAccountForAssembleTxParams序列化普通账户序列化为{ address }predicate 账户实现上通过bytes in account判定则序列化为{ predicate, predicateAddress, predicateData }将谓词字节码、地址与数据一并上报节点用于估算。这解释了为什么assembleTx需要estimatePredicates参数当交易涉及 predicate 资源时gas 估算必须把 predicate 执行的开销计算在内。与已废弃旧 API 的关系assembleTx是getTransactionCostfund、以及estimateAndFund等旧流程的替代方案后者已标记为 deprecated并将在未来版本移除。如果你正在迁移旧代码可参考仓库中的官方迁移指南 assemble-tx-migration-guide.md。相比旧 API新方法的优势可概括为三点对谁付手续费、谁出资源的控制更显式可精确指定每个账户、每种资产各自提供多少数量在声明每个账户的 coin quantity 时就能直接控制该 assetId 的找零归属。测试验证仓库的燃料 gauge 集成测试 assemble-tx.test.ts 覆盖了assembleTx在真实 Fuel 节点上的行为包含多账户、多资产与找零归属等场景可作为理解本文内容后进一步对照源码学习的入口。Best Practices官方建议清单始终提供余额充足的feePayerAccount手续费不足会让 dry run 失败并在组装阶段即抛错多账户共享同一 assetId 时务必谨慎对待 change 输出Fuel 每个 assetId 每笔交易只允许一个 change 输出若同一 assetId 的资源来自多个账户则只有一个账户能收到全部已花费资源的找零请与交易涉及的各方事先协调明确由谁接收该 assetId 的找零再通过changeOutputAccount显式声明。Notes行为特性小结assembleTx会自动处理 base asset 的手续费需求accountCoinQuantities的amount无需叠加费用返回前会对交易执行 dry run 校验失败即抛错避免把无效交易放行到签名环节组装后的交易会依据accountCoinQuantities带齐全部必要的 inputs 与 outputsgas 与费用估算基于指定的blockHorizon完成若要彻底掌控找零去向最稳妥的做法是永远显式写出account与changeOutputAccount不依赖默认回退逻辑。【免费下载链接】fuels-tsFuel Network Typescript SDK项目地址: https://gitcode.com/GitHub_Trending/fu/fuels-ts创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/11/3 6:18:31

DBA 面试不用再到处找题:530 道题库 + AI 模拟面试!

准备 DBA 面试时,最容易陷进去的不是没题,而是题太散:收藏夹里一份 Oracle 文档,网盘里几套 MySQL 题目,临面试了还在判断哪些该背、哪些只要理解。 ORA100 把这件事收拢成了一个面试准备台。先按数据库、难度和能力方…

2026/11/3 9:42:02

Wonderdraft+Dungeondraft:从世界地图到战斗场景的地图制作实战指南

做地图这件事,做了这么多年,我越来越觉得它不是一个“画图”的活儿,而是一个“搭建舞台”的活儿。无论是跑团主持人准备一张大陆全景图,还是独立游戏开发者给关卡配一张战斗地图,工具选对了,效率能差出好几…

2026/11/4 0:03:20

uniapp海外游戏分发工程:PG电子集成与Switch卡带区域适配

简介:这是一套面向海外游戏业务开发者的全栈前端解决方案,基于UniApp框架实现跨平台兼容,专为构建海外游戏交易平台、手游下载站及Switch游戏卡带销售系统设计。资源包含完整可二次开发的前端源码(非编译后产物)&#…

2026/11/4 0:03:20

Qoder NEXT:智能代码补全工具的技术解析与应用

1. 项目概述Qoder NEXT作为新一代智能编程辅助工具,其核心突破在于通过深度优化代码补全算法,将AI生成代码的开发者采纳率提升了65%。这个数字背后代表着编程效率的实质性飞跃——开发者不再需要花费大量时间在重复性代码编写和机械性调试上,…

2026/11/4 0:03:20

32G统一内存跑大模型:内存账、TPS实测与端云分流

想在一台 32G 统一内存的小主机上把大模型跑成"日常可用",这件事我前后折腾了小半年。标题里说的这台 Mac mini M6,是我们这次讨论的目标平台,具体到手规格以实物为准;但下面这套推算方法和实测思路,对任何统…

2026/11/4 0:03:20

从生成Token到直接决策:Jev如何重塑AI Agent工程实践

1. 从"生成文字"到"拍板决策":Jev 到底在解决什么问题大多数人第一次接触大模型,脑子里建立的模型是"输入问题、输出文字"。你问它今天天气怎么样,它给你一段描述;你让它写个周报,它给你…

2026/11/4 0:03:20

AI辅助技术栈评估:提升研发决策效率60%

1. 项目背景与核心价值技术决策一直是研发团队面临的重大挑战。随着技术生态的快速演进,技术栈的选择、维护和迭代变得愈发复杂。我们团队在过去两年里,先后经历了三次重大技术栈迁移,每次都需要投入大量人力进行技术评估和风险分析。直到去年…

2026/11/3 23:58:18

云服务器选购与配置全攻略:从AI开发到Web应用

1. 云服务器选购指南作为一名长期使用云服务器的开发者,我深知选择合适的云服务商对项目开发效率的影响。目前国内主流的云服务器平台中,阿里云和AutoDL是个人开发者和小团队常用的选择。阿里云作为国内市场份额最大的云服务商,其稳定性有保障…

2026/11/3 7:47:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/3 14:24:53

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/11/4 0:03:20

AI辅助技术栈评估:提升研发决策效率60%

1. 项目背景与核心价值技术决策一直是研发团队面临的重大挑战。随着技术生态的快速演进,技术栈的选择、维护和迭代变得愈发复杂。我们团队在过去两年里,先后经历了三次重大技术栈迁移,每次都需要投入大量人力进行技术评估和风险分析。直到去年…

2026/11/4 0:03:20

从生成Token到直接决策:Jev如何重塑AI Agent工程实践

1. 从"生成文字"到"拍板决策":Jev 到底在解决什么问题大多数人第一次接触大模型,脑子里建立的模型是"输入问题、输出文字"。你问它今天天气怎么样,它给你一段描述;你让它写个周报,它给你…

2026/11/4 0:03:20

32G统一内存跑大模型:内存账、TPS实测与端云分流

想在一台 32G 统一内存的小主机上把大模型跑成"日常可用",这件事我前后折腾了小半年。标题里说的这台 Mac mini M6,是我们这次讨论的目标平台,具体到手规格以实物为准;但下面这套推算方法和实测思路,对任何统…

2026/11/3 7:47:06

面向复杂光照与角度的宠物面部识别鲁棒性增强策略

在智慧养宠时代,基于视觉的宠物身份识别技术正逐步从实验室走向家庭应用。然而,与配合度高的人类不同,宠物是典型的“非合作生物识别对象”——它们不会主动配合摄像头调整姿态,更无法控制光照环境。实际应用中,我们常…

2026/11/3 14:24:53

SSM电子书店源码全解析:结构、原理、部署与排错实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑