☰
如何用 fuels-rs 在单笔交易中把一个钱包的全部资产转移到另一个钱包
2026/10/15 9:12:42 网站建设 项目流程

如何用 fuels-rs 在单笔交易中把一个钱包的全部资产转移到另一个钱包

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

Wallet的transfer()方法一次只能转移一种资产。如果你需要把某个钱包持有的全部资产(基础资产加上若干其他资产)一次性挪到另一个钱包,逐个调用transfer()意味着每笔转移都是一笔独立交易。fuels-rs 官方文档 Transfer all assets 给出的做法是:用ScriptTransactionBuilder手工构建一笔自定义交易,把所有资产的输入(inputs)和输出(outputs)打包在一起提交。

本文按该文档的完整示例走一遍这条路径:准备两个钱包和一批资产 → 查询源钱包余额 → 生成对应的输入输出 → 构建、签名并提交交易 → 用接收钱包的余额做验证。所有代码取自仓库中的示例 examples/cookbook/src/lib.rs(transfer_multiple测试)。

准备条件

  • 一个引入fuelscrate 的 Rust 项目。示例代码用到了fuels::test_helpers里的setup_test_provider和setup_multiple_assets_coins,这对应fuelscrate 的test-helpersfeature(见 packages/fuels/Cargo.toml),用于在本地启动一个测试节点。
  • 两个已连接 provider 的Wallet:wallet_1是转出方,wallet_2是接收方。
  • 一个 tokio 异步环境,示例代码运行在#[tokio::test]中。

准备钱包与资产

先随机生成一个签名者,用它初始化一批资产,再启动测试 provider 并创建两个钱包:

use std::str::FromStr; use fuels::prelude::*; let wallet_1_signer = PrivateKeySigner::random(&mut thread_rng()); const NUM_ASSETS: u64 = 5; const AMOUNT: u64 = 100_000; const NUM_COINS: u64 = 1; let (coins, _) = setup_multiple_assets_coins(wallet_1_signer.address(), NUM_ASSETS, NUM_COINS, AMOUNT); let provider = setup_test_provider(coins, vec![], None, None).await?; let wallet_1 = Wallet::new(wallet_1_signer, provider.clone()); let wallet_2 = Wallet::random(&mut thread_rng(), provider.clone());

这里wallet_1持有 5 种资产、每种 1 枚 coin、每枚 100_000(文档示例值)。setup_multiple_assets_coins返回的coins直接交给setup_test_provider,让这些资产进入本地测试链。真实场景中这一步换成你自己的资产状态即可,后面的流程不依赖本地节点。

查询源钱包的全部余额

交易需要先定义输入和输出 coin,而文档假设我们不预先知道wallet_1持有哪些资产。因此先查询它的余额:

let balances: HashMap<String, u128> = wallet_1.get_balances().await?;

get_balances()返回一个HashMap,键是资产 ID 的十六进制字符串,值是对应的余额(见 Checking balances and coins)。拿到这份"资产 ID → 数量"的列表后,就可以为每种资产生成对应的输入和输出。

为每种资产生成输入和输出

遍历balances,对每种资产分别调用get_asset_inputs_for_amount()(从源钱包找出足额的输入 coin)和get_asset_outputs_for_amount()(生成指向接收钱包的输出):

let consensus_parameters = provider.consensus_parameters().await?; let mut inputs = vec![]; let mut outputs = vec![]; for (id_string, amount) in balances { let id = AssetId::from_str(&id_string)?; let input = wallet_1 .get_asset_inputs_for_amount(id, amount, None) .await?; inputs.extend(input); // 基础资产只转一半,剩余部分用来支付交易费用 let output = if id == *consensus_parameters.base_asset_id() { wallet_1.get_asset_outputs_for_amount(wallet_2.address(), id, (amount / 2) as u64) } else { wallet_1.get_asset_outputs_for_amount(wallet_2.address(), id, amount as u64) }; outputs.extend(output); }

注意文档强调的一点:基础资产不能全额转出,因为交易费用是用基础资产支付的。示例里只对base_asset_id转amount / 2,其余资产全额转出。判断基础资产 ID 的方式是从provider.consensus_parameters()里取base_asset_id()。

构建交易并发送

用ScriptTransactionBuilder::prepare_transfer把输入输出组装起来,让wallet_1添加 witness(签名),再构建并发送:

let mut tb = ScriptTransactionBuilder::prepare_transfer(inputs, outputs, TxPolicies::default()); wallet_1.add_witnesses(&mut tb)?; let tx = tb.build(&provider).await?; provider.send_transaction_and_await_commit(tx).await?;
  • prepare_transfer(inputs, outputs, TxPolicies::default())是专门针对"纯转账、不部署合约"场景的构建入口;
  • 因为用了需要签名的 coin,必须由持有这些 coin 的wallet_1调用add_witnesses提供签名;
  • send_transaction_and_await_commit会提交交易并等待其确认完成。

关于 builder 的作用机制(witness 索引、签名时机等)可参考 Transaction Builders。

验证转移结果

验证方式是查询接收钱包wallet_2的余额,确认资产种类数和每种资产的数量:

let balances = wallet_2.get_balances().await?; assert_eq!(balances.len(), NUM_ASSETS as usize); for (id, balance) in balances { if id == *consensus_parameters.base_asset_id().to_string() { assert_eq!(balance, (AMOUNT / 2) as u128); } else { assert_eq!(balance, AMOUNT as u128); } }

按文档示例的参数(5 种资产、每种 100_000),预期是:wallet_2的余额包含 5 种资产,其中基础资产为 50_000,其余 4 种各为 100_000。这两个数值是文档示例值,如果你的资产参数不同,按同样的规则换算:基础资产约为转入量的一半(扣费后wallet_1仍留有余额),其他资产等于全额。

限制与说明

  • 单笔交易把所有资产打包的前提是你能拿到源钱包的每种资产 ID 和数量,即get_balances()的结果;文档示例正是"假设不知道资产有哪些"的情形,全部从余额查询推导。
  • 费用约束是这条路径的核心限制:基础资产的输出金额必须留出付手续费的余量,示例采用amount / 2这一保守取法。
  • 如果不需要一笔交易打包(资产种类少、或可以接受多笔交易),文档指出的替代路径就是反复调用transfer(),每次转移一种资产。

完整示例代码见 examples/cookbook/src/lib.rs 的transfer_multiple测试,文档入口为 Transfer all assets。

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

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

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

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

立即咨询