Transfer all assets

The transfer() method lets you transfer a single asset, but what if you needed to move all of your assets to a different wallet? You could repeatably call transfer(), initiating a transaction each time, or you bundle all the transfers into a single transaction. This chapter guides you through crafting your custom transaction for transferring all assets owned by a wallet.

Lets quickly go over the setup:

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());

We prepare two wallets with randomized addresses. Next, we want one of our wallets to have some random assets, so we set them up with setup_multiple_assets_coins(). Having created the coins, we can start a provider and assign it to the previously created wallets.

Transactions require us to define input and output coins. Let's assume we do not know the assets owned by wallet_1. We retrieve its balances, i.e. tuples consisting of a string representing the asset id and the respective amount. This lets us use the helpers get_asset_inputs_for_amount(), get_asset_outputs_for_amount() to create the appropriate inputs and outputs.

For the sake of simplicity, we avoid transferring the base asset so we don't have to worry about transaction fees:

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).unwrap(); // leave the base asset to cover transaction fees if id == BASE_ASSET_ID { continue; } let input = wallet_1.get_asset_inputs_for_amount(id, amount, 0).await?; inputs.extend(input); let output = wallet_1.get_asset_outputs_for_amount(wallet_2.address(), id, amount); outputs.extend(output); }

All that is left is to build the transaction with the helper build_transfer_transaction(), have wallet_1 sign it, and we can send it. We confirm this by checking the number of balances present in the receiving wallet and their amount:

let mut tx = Wallet::build_transfer_tx(&inputs, &outputs, TxParameters::default()); wallet_1.sign_transaction(&mut tx).await?; let _receipts = provider.send_transaction(&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); }