Home

Core

Batching Transactions

Learn how to send batched transactions onchain.

note

To use embedded signers, first you need to authenticate your users. Follow the steps to set up embedded signers for your users with the embedded signer overview.

Smart accounts support batching transactions, allowing multiple actions to be rolled into one. This feature significantly simplifies Web3 interactions for your users. For example, instead of executing approve() and then transfer(), your user can perform both in a single transaction.

Batching transactions offers several key benefits:

  • Users only wait for one transaction to complete instead of multiple.
  • Users save on gas fees.
  • If any transaction in the batch fails, the entire batch reverts, preventing users from ending up in an inconsistent state. This characteristic is known as "atomicity."

Fore security reasons, there is a limit of 9 interactions per transaction intent.

Quickstart#

1. Create a transactionIntent#

Create a request to your backend to create a transactionIntent. In the body of the request:

  • Include the player that signs the transaction.
  • Include the policy that interacts with the contract for gas. If non-existen the user will need to have gas tokens.
  • Include optimistic if you want the transactions to be confirmed faster.

Depending on the type of transaction you're creating you'll define interactions. The interactions field is an array of objects that contain the information of the contract to interact with, the function to call, and the arguments to pass to the function.

  • the interactions field contains the contract that has previously been added to Openfort.
  • the functionName defines the function to call from within the contract.
  • If there exist more than one function with the same name, the functionArgs will be used to determine which function to call.

To execute a batch transaction, you can send a transaction intent with multiple interactions, and each interaction will be executed in the order they are received.

note

Openfort systems check the contract's ABI to find a function signature based on the functionName that you provide and the number of functionArgs.

In the case that, in your contract, you have multiple functions with the same functionName and number of arguments, you can also include the functionName together with the argument types e.g. mint(address)

command-line

_12
curl https://api.openfort.xyz/v1/transaction_intents \
_12
-H "Authorization: Bearer $YOUR_SECRET_KEY" \
_12
-d player="pla_...", \
_12
-d policy="pol_..." \
_12
-d chainId=80002 \
_12
-d optimistic=true \
_12
-d "interactions[0][contract]=con_..." \
_12
-d "interactions[0][functionName]=mint" \
_12
-d "interactions[0][functionArgs][0]=0x63B7...484f" \
_12
-d "interactions[1][contract]=con_..." \
_12
-d "interactions[1][functionName]=transfer" \
_12
-d "interactions[1][functionArgs][0]=0x32B7...213d"

2. Sign the transactionIntent with the signer.#

Use the nextAction returned by the backend to sign the transaction with the embedded signer.

The transaction will be automatically signed and broadcasted by using the sendSignatureTransactionIntentRequest method.


_29
const handleCollectButtonClick = async () => {
_29
try {
_29
setCollectLoading(true);
_29
const collectResponse = await fetch(`/api/examples/protected-collect`, {
_29
method: "POST",
_29
headers: {
_29
"Content-Type": "application/json",
_29
},
_29
});
_29
const collectResponseJSON = await collectResponse.json();
_29
_29
if (collectResponseJSON.data?.nextAction) {
_29
console.log("config", config);
_29
_29
const response = await openfort.sendSignatureTransactionIntentRequest(
_29
collectResponseJSON.data.id,
_29
collectResponseJSON.data.nextAction.payload.userOperationHash
_29
);
_29
console.log("response", response);
_29
}
_29
_29
console.log("success:", collectResponseJSON.data);
_29
alert("Action performed successfully");
_29
} catch (error) {
_29
console.error("Error:", error);
_29
} finally {
_29
setCollectLoading(false);
_29
}
_29
};

Examples#