fuels-ts 合约调用包含转账时如何手动添加 Output Variable
2026/9/10 6:04:00 网站建设 项目流程

fuels-ts 合约调用包含转账时如何手动添加 Output Variable

【免费下载链接】fuels-tsFuel Network Typescript SDK项目地址: https://gitcode.com/GitHub_Trending/fu/fuels-ts

当你在 Sway 合约里调用标准库的资产转账函数(例如std::assettransfer)时,每次转账都会要求交易(transaction)的Outputs列表中多一个 Output Variable。fuels-ts 默认会替你自动估算这些依赖,但估算过程是反复 dry run 的暴力试探,会明显拖慢交易处理。这篇文档介绍如何提前数好转账次数,通过txParams手动指定variableOutputs,跳过自动估算,并给出结果验证方式。

为什么每次转账都需要一个 Output Variable

Sway 提供了把资产转给钱包或合约的函数。文档明确指出:合约函数中每调用一次 Sway 转账函数,交易就需要对应数量的 Output Variable——调用 3 次transfer,outputs 里就需要 3 个 Output Variable。

下面这个仓库文档中的 Sway 合约示例(见 main.sw)封装了两个会触发转账的函数:

use std::asset::{burn, mint, transfer}; abi Token { fn transfer_to_address(target: Address, asset_id: AssetId, coins: u64); fn transfer_to_contract(recipient: ContractId, asset_id: AssetId, coins: u64); fn mint_coins(sub_id: b256, mint_amount: u64); fn burn_coins(sub_id: b256, burn_amount: u64); } impl Token for Contract { fn transfer_to_address(recipient: Address, asset_id: AssetId, amount: u64) { transfer(Identity::Address(recipient), asset_id, amount); } fn transfer_to_contract(target: ContractId, asset_id: AssetId, amount: u64) { transfer(Identity::ContractId(target), asset_id, amount); } // ... }

transfer_to_addresstransfer_to_contract内部各调用一次transfer,所以每次调用它们都需要 1 个 Output Variable。如果合约调用的函数间接触发了其他合约的转账,同样要计入。

SDK 的默认行为:自动估算

按 dependency-estimation 的说明,SDK 默认会通过Provider.estimateTxDependencies自动补齐缺失的依赖,这需要在后台把交易模拟若干次。文档建议:如果依赖数量可以提前算出来,就手动指定,以避免估算带来的性能开销。variableOutputs正是交易参数之一,在 adding-parameters 中被定义为“应添加到交易请求中的 variable outputs 数量”,通过txParams方法设置。

手动添加 variableOutputs

下面是仓库文档 variable-outputs 给出的示例(对应 snippets),核心是.txParams({ variableOutputs: 1 })这一行:

import { Provider, Wallet, getMintedAssetId, getRandomB256 } from 'fuels'; import { LOCAL_NETWORK_URL, WALLET_PVT_KEY } from './env'; import { TokenFactory } from './typegend'; const provider = new Provider(LOCAL_NETWORK_URL); const deployer = Wallet.fromPrivateKey(WALLET_PVT_KEY, provider); const deployContract = await TokenFactory.deploy(deployer); const { contract } = await deployContract.waitForResult(); const subId = getRandomB256(); // 先铸造代币,转账的 assetId 由此得到 const call1 = await contract.functions.mint_coins(subId, 100).call(); await call1.waitForResult(); const address = { bits: Wallet.generate().address.toB256() }; const assetId = { bits: getMintedAssetId(contract.id.toB256(), subId) }; // 关键点:手动声明本次调用需要 1 个 Output Variable const { waitForResult } = await contract.functions .transfer_to_address(address, assetId, 100) .txParams({ variableOutputs: 1, }) .call(); await waitForResult();

说明:

  • LOCAL_NETWORK_URLWALLET_PVT_KEY来自你本地的环境变量文件,TokenFactory来自 fuels 的类型生成产物,按你项目实际的导入路径替换。
  • 示例中的variableOutputs: 1对应transfer_to_address内部的一次transfer调用。如果你调用的函数内部转账 n 次,就填 n。
  • 交易提交前需要先mint_coins铸造出对应资产,否则assetId无法构造,这是示例给出的前置条件。

一次调用触发多次转账时如何计数

仓库的 fee.test.ts 中有一个多调用(multiCall)场景:每次mint_to_addresses向 3 个地址铸造(内部触发 3 次转账),连续发起 15 次调用时,参数这样计算:

const calls = Array.from({ length: 15 }).map(() => contract.functions.mint_to_addresses(addresses, subId, 100) ); const { waitForResult } = await contract .multiCall(calls) .txParams({ variableOutputs: calls.length * 3 }) .call();

variableOutputs等于整笔交易内所有转账调用次数之和(15 次调用 × 每次 3 个地址 = 45)。计数规则以你实际会执行的transfer次数为准。

另外,dry-run-multiple-txs.test.ts 展示了不做手动指定时的对照行为:variableOutputs: 0或不设置时,交易请求在 dry run 阶段由 SDK 补齐依赖,这正是手动指定所要避免的额外模拟开销。

验证结果是否成功

仓库测试中验证转账类调用有两种方式:

  1. 检查交易状态。waitForResult()返回的transactionResult上有isStatusSuccess字段,文档示例直接用它判断:

    const { transactionResult } = await waitForResult(); console.log( 'Transaction should be successful', transactionResult.isStatusSuccess );
  2. 检查接收方余额。token-test-contract.test.ts 在转账后查询接收钱包的getBalances(),确认对应assetId的余额等于转账数量(测试中断言余额为toHex(50),这是测试的示例数值,你的转账金额应以实际传入的coins为准):

    const { balances } = await userWallet.getBalances(); const tokenBalance = balances.find((b) => b.assetId === assetId.bits);

如果转账没有到账或isStatusSuccess为 false,优先核对variableOutputs是否与实际转账次数一致——数量不足时交易在 dry run/模拟阶段就会报错,SDK 才会回退到自动补齐。

限制与边界

  • 手动指定只影响 performance:文档说明自动估算是“brute-force strategy, performing sequential dry runs until no errors are returned”,手动指定是为了跳过这部分开销,两者不会改变交易本身的正确性要求。
  • 数错方向的风险:variableOutputs少于实际转账次数会导致交易缺 Output Variable,最终依赖 SDK 估算或交易失败;具体数值应以合约内实际执行的transfer次数为准,文档没有给出“多算几个也无妨”的结论。
  • 若合约调用链会触发其他合约内的转账,也要把这些间接转账计入总数(见 variable-outputs 的说明)。

进一步阅读:variable-outputs、dependency-estimation、adding-parameters。

【免费下载链接】fuels-tsFuel Network Typescript SDK项目地址: https://gitcode.com/GitHub_Trending/fu/fuels-ts

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询