⌘K

Transfer All Assets

Icon Link转移所有资产

transfer() 方法让您可以转移单个资产,但如果您需要将所有资产移动到另一个钱包呢?您可以重复调用 transfer() 方法,每次启动一个交易,或者将所有转移捆绑到一个交易中。本章将指导您如何创建自定义交易,用于转移钱包拥有的所有资产。

首先,让我们快速设置环境:

let mut wallet_1 = WalletUnlocked::new_random(None);
let mut wallet_2 = WalletUnlocked::new_random(None);
 
const NUM_ASSETS: u64 = 5;
const AMOUNT: u64 = 100_000;
const NUM_COINS: u64 = 1;
let (coins, _) =
    setup_multiple_assets_coins(wallet_1.address(), NUM_ASSETS, NUM_COINS, AMOUNT);
 
let provider = setup_test_provider(coins, vec![], None, None).await?;
 
wallet_1.set_provider(provider.clone());
wallet_2.set_provider(provider.clone());

我们创建了两个带有随机地址的钱包。接下来,我们希望其中一个钱包拥有一些随机资产,因此我们使用 setup_multiple_assets_coins() 方法为其设置了资产。创建了这些资产后,我们启动了一个提供程序,并将其分配给之前创建的钱包。

交易需要定义输入和输出币。假设我们不知道 wallet_1 拥有哪些资产。我们检索其余额,即由资产 ID 和相应金额组成的元组。这使我们可以使用助手函数 get_asset_inputs_for_amount()get_asset_outputs_for_amount() 来创建适当的输入和输出。

为了简单起见,我们避免转移基础资产,以免担心交易费用:

let balances = wallet_1.get_balances().await?;
 
let mut inputs = vec![];
let mut outputs = vec![];
for (id_string, amount) in balances {
    let id = AssetId::from_str(&id_string)?;
 
    // leave the base asset to cover transaction fees
    if id == *provider.base_asset_id() {
        continue;
    }
 
    let input = wallet_1.get_asset_inputs_for_amount(id, amount).await?;
    inputs.extend(input);
 
    let output = wallet_1.get_asset_outputs_for_amount(wallet_2.address(), id, amount);
    outputs.extend(output);
}

现在,唯一剩下的就是构建交易了。我们使用 ScriptTransactionBuilder 构建交易,由 wallet_1 签名后发送。我们通过检查接收钱包中的余额数量和金额来确认交易已成功:

let mut tb =
    ScriptTransactionBuilder::prepare_transfer(inputs, outputs, TxPolicies::default());
tb.add_signer(wallet_1.clone())?;
 
let tx = tb.build(&provider).await?;
 
provider.send_transaction_and_await_commit(tx).await?;
 
let balances = wallet_2.get_balances().await?;
 
assert_eq!(balances.len(), (NUM_ASSETS - 1) as usize);
for (_, balance) in balances {
    assert_eq!(balance, AMOUNT);
}