Skip to content

Invoke chains of Move calls with Dynamic Script Composer

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.

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,
}),
});

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)
...

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)

  1. nodejs: https://github.com/aptos-labs/script-composer-sdk/tree/main/examples/nodejs
  2. nextjs: https://github.com/aptos-labs/script-composer-sdk/tree/main/examples/nextjs-project
  3. react: https://github.com/aptos-labs/script-composer-sdk/tree/main/examples/react-project

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:

  1. 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.
  2. 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 of Coin<AptosCoin>.

This implements AIP-102