There may be scenarios where you need to build out transactions that involve multiple program types and assets; this can be done by instantiating a ScriptTransactionRequest
. This class allows you to a append multiple program types and assets to a single transaction.
Consider the following script that transfers multiple assets to a contract:
script;
use std::token::force_transfer_to_contract;
fn main(
contract_address: b256,
asset_a: AssetId,
amount_asset_a: u64,
asset_b: AssetId,
amount_asset_b: u64,
) -> bool {
let wrapped_contract = ContractId::from(contract_address);
force_transfer_to_contract(wrapped_contract, asset_a, amount_asset_a);
force_transfer_to_contract(wrapped_contract, asset_b, amount_asset_b);
true
}
This script can be executed by creating a ScriptTransactionRequest
, appending the resource and contract inputs/outputs and then sending the transaction, as follows:
import type { BN, CoinQuantityLike, ScriptTransactionRequest } from 'fuels';
// 1. Create a script transaction using the script binary
const request = new ScriptTransactionRequest({
...defaultTxParams,
gasLimit: 3_000_000,
script: scriptBin,
});
// 2. Instantiate the script main arguments
const scriptArguments = [contract.id.toB256(), assetIdA, new BN(1000), assetIdB, new BN(500)];
// 3. Get the resources for inputs and outpoints
const { gasPriceFactor } = contract.provider.getGasConfig();
const fee = request.calculateFee(gasPriceFactor);
const quantities: CoinQuantityLike[] = [[1000, assetIdA], [500, assetIdB], fee];
const resources = await wallet.getResourcesToSpend(quantities);
// 4. Populate the script data and inputs/outputs
request
.setData(abiContents, scriptArguments)
.addContractInputAndOutput(contract.id)
.addResources(resources);
// 5. Send the transaction
const tx = await wallet.sendTransaction(request);
await tx.waitForResult();