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

发布时间:2026/9/9 22:50:48

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/9/9 22:50:48

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

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

2026/9/9 22:45:48

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

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

2026/9/9 23:40:53

乐鑫ESP32模组智能交互实战:选型、语音、GUI与量产避坑指南

1. 乐鑫模组为什么总能出现在智能交互的第一线 做智能硬件这几年,我发现一个很有意思的现象:不管是做智能音箱、中控屏、离线语音开关,还是做雷达人体存在传感器,大家聊着聊着总会提到乐鑫。早些年大家用ESP8266做联网&#xff0c…

2026/9/9 23:40:53

2007年数学建模B题公交车调度优化:从建模到代码实现

简介:2007年全国大学生数学建模B题通常涉及交通网络或公交路径优化,Dijkstra算法是求解最短路径的核心工具。该压缩包提供了当年参赛队伍的完整Java实现,包含7个Java源文件、11个编译后的class文件以及Eclipse工程配置文件,共21个…

2026/9/9 23:40:53

基于YOLOv8的多端车流检测系统:从训练到部署的完整实践

简介:基于YOLOv8的多端车流检测系统,适合计算机视觉方向的毕业设计或开源研究。资源包共396个文件,体积16.94MB,包含Python源码、预训练权重(.pt)、模型配置(.yaml)、GUI界面文件&am…

2026/9/9 23:40:53

用纯前端实现Markdown在线预览编辑器:从解析到安全渲染全解析

做前端项目的时候,总有那么几个工具类页面看着不起眼,真要动手却发现坑不少。Markdown在线预览编辑器就是典型的例子,看起来无非是左边写右边渲染,实际做下来涉及解析库选型、XSS过滤、代码高亮、同步滚动、性能防抖一堆问题。这篇…

2026/9/9 23:35:52

微信小程序源码学习指南:从支付v3到导航栏适配的实战拆解

简介:压缩包内汇集了近一百个微信小程序完整源码项目,覆盖电商、餐饮、生活服务、资讯阅读等常用行业,无论是课程设计还是工作参考,都适合移动端开发者、前端初学者以及想系统掌握小程序开发流程的学习者。资源共含7590个文件&…

2026/9/9 13:11:35

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/8 7:15:15

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/9 16:31:09

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/9 0:00:48

MHS模型硬件标准:让大模型像调用软件一样控制物理设备

让Claude真正看着显微镜说“这个细胞形态不太对”,或者让大模型自己调一版机械臂的运动轨迹,这事儿听上去已经很接近科幻片了。但你真上手试一次就会发现,模型不缺智商,缺的是一个能插进显微镜、机械臂、激光控制器里的“通用插座…

2026/9/9 0:00:48

AI五大核心方向详解:从机器学习到大模型,零基础转行选哪条?

会有人告诉我,他想转行学AI,但打开招聘网站一看直接傻眼:机器学习、深度学习、自然语言处理、计算机视觉、大模型应用……满屏都是这些词,好像每个都会一点,又好像每个都离自己很远。还有人上来就问“学Python还是学Ja…

2026/9/9 0:00:49

从50行最小循环到生产级AI引擎:工程化改造全解析

直接说干货。这一章我写的不是那种"hello world跑通某个模型"的教程,而是把AI引擎当做一个真正要上线、要被人调用、要扛流量的系统来聊。从最初只有50行的最小循环,到能够承载生产流量的AI引擎,中间差的不是代码量,而是…

2026/9/7 16:23:03

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/7 22:46:00

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/9 10:21:54

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

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

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

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