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::asset::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 { BN, CoinQuantityLike, ScriptTransactionRequest }
// 1. Create a script transaction using the script binary
const { minGasPrice } = contract.provider.getGasConfig();
const request = new ScriptTransactionRequest({
...defaultTxParams,
gasLimit: 3_000_000,
script: scriptBin,
gasPrice: minGasPrice,
});
// 2. Instantiate the script main arguments
const scriptArguments = [
contract.id.toB256(),
{ value: assetIdA },
new BN(1000),
{ value: assetIdB },
new BN(500),
];
// 3. Populate the script data and add the contract input and output
request.setData(abiContents, scriptArguments).addContractInputAndOutput(contract.id);
// 4. Calculate the transaction fee
const { maxFee } = await provider.getTransactionCost(request);
// 5. Get the transaction resources
const quantities: CoinQuantityLike[] = [
[1000, assetIdA],
[500, assetIdB],
[maxFee, BaseAssetId],
];
const resources = await wallet.getResourcesToSpend(quantities);
request.addResources(resources);
// 6. Send the transaction
const tx = await wallet.sendTransaction(request);
await tx.waitForResult();