Invoke chains of Move calls with Dynamic Script Composer
Overview
Section titled “Overview”In the basic API, you can only specify one entry function call for a single transaction. Advanced builders might want to invoke multiple public Move functions in one transaction. This is now enabled by the new scriptComposer
API provided in the transaction builder.
Basic Usage
Section titled “Basic Usage”Here’s an example of how to invoke the API:
Please note that the current example is only for reference on how to use Script Composer to combine transactions, receive return values from public functions, and pass them to the next function
const tx = await BuildScriptComposerTransaction({ // You need to fill in the sender's address here sender: singleSignerED25519SenderAccount.accountAddress, builder: async (composer) => { // Start by withdrawing some Coin const coin = await composer.addBatchedCalls({ function: "0x1::coin::withdraw", functionArguments: [CallArgument.newSigner(0), 1], typeArguments: ["0x1::aptos_coin::AptosCoin"], });
// Pass the coin value to 0x1::coin::coin_to_fungible_asset to convert the token // into a fungible asset const fungibleAsset = await composer.addBatchedCalls({ function: "0x1::coin::coin_to_fungible_asset", // coin[0] represents the first return value from the first call you added functionArguments: [coin[0]], typeArguments: ["0x1::aptos_coin::AptosCoin"], });
// Deposit the fungibleAsset converted from the second call await composer.addBatchedCalls({ function: "0x1::primary_fungible_store::deposit", // You need to fill in the sender's address here functionArguments: [singleSignerED25519SenderAccount.accountAddress, fungibleAsset[0]], typeArguments: [], }); return composer }, // You need to pass Aptos Config here because the combined transaction needs to read on-chain state aptosConfig: new AptosConfig({ network: Network.TESTNET, }),});
Transaction Processing
Section titled “Transaction Processing”After combining the transaction, we can use interfaces like sign transaction / simulate transaction / submit transaction from @aptos-labs/ts-sdk
:
We’ll use the simulate transaction interface to show how to use it:
...
const aptos = new Aptos(new AptosConfig({ network: Network.TESTNET, }));
const simulate_result = await aptos.transaction.simulate.simple({ transaction: tx, })
console.log('simulate_result: ', simulate_result)...
Examples
Section titled “Examples”If you need some practical examples, we have also prepared usage examples for three common environments:
In the examples, you will see a combined transaction and the return value of the simulated transaction (the simulated transaction uses the 0x1 address as the sender. Although it can be simulated successfully by default, if you want to actually use this feature to initiate a simulated transaction, please replace it with your account address and set up the corresponding network)
- nodejs: https://github.com/aptos-labs/script-composer-sdk/tree/main/examples/nodejs
- nextjs: https://github.com/aptos-labs/script-composer-sdk/tree/main/examples/nextjs-project
- react: https://github.com/aptos-labs/script-composer-sdk/tree/main/examples/react-project
Technical Principles
Section titled “Technical Principles”Under the hood, the SDK will invoke a WASM binary to compile the series of Move calls into a CompiledScript
. This will guarantee that the type and ability safety of Move is still being honored during the construction process. For the SDK users, this means:
- Ability safety: a. If the returned value does not have the Drop ability, the returned value needs to be consumed by subsequent calls. b. If the returned value does not have the Copy ability, the returned value can only be passed to subsequent calls once.
- The caller will need to make sure they pass the right values as arguments to subsequent calls. In the previous example, the
0x1::coin::coin_to_fungible_asset
function will expect an argument ofCoin<AptosCoin>
.
This implements AIP-102