Skip to content

Execute a Simple Supertransaction

In this tutorial, we will use the Biconomy Modular Execution Environment to execute a very simple Supertransaction.

Goals

The goal of this tutorial is to learn the flow of executing a Supertransaction. This tutorial will not cover the functionalities which Supertransactions unlock - such as multichain orchestration, intent execution or cross-chain gas abstraction.

Getting Started

Install AbstractJS and viem

Install
npm install @biconomy/abstractjs viem @rhinestone/module-sdk@0.2.3

Initialize the MEE Infrastructure

Supertransactions are powered by the Biconomy Modular Execution Environment (MEE). To connect to MEE, we need to initialize an meeClient

Initialize Infrastructure
// Create an account owner - signer
const eoaSigner = privateKeyToAccount("Your private key here")
 
// Create a connector to Biconomy Nexus account
// implementations across multiple chains
// with the multichain account utility function
const mcNexus = await toMultichainNexusAccount({
  chains: [optimism, base, polygon, arbitrum],
  transports: [http(), http(), http(), http()],
  signer: eoaSigner
})
 
// Create the connection to the MEE
const meeClient = await createMeeClient({
  account: mcNexus
})

Encode a Dummy Transaction

For the purposes of this tutorial, we'll encode a dummy transaction which simply send 0ETH to 0x000000...

Dummy Transaction
const emptyTx: AbstractCall = {
  to: zeroAddress,
  value: 0n
}

Encode a Supertransaction

Now we will encode an instance of the Supertransaction object. The Supertransaction object contains two fields:

  1. Instructions - which function calls need to be executed and on which chains

  2. Fee Token - which native or ERC20 token and on which chain will be used to pay for the Supertransaction

Encode Supertransaction
const supertransaction: Supertransaction = {
  // Transactions to be executed within a
  // Supertransaction
  instructions: [
    mcNexus.build({ type: "default", data: { chainId: optimism.id, calls: [emptyTx] } }),
  ],
  // Token to pay for the Supertransaction
  feeToken: {
    chainId: optimism.id,
    address: mcUSDC.addressOn(optimism.id)
  }
}

Executing the Supertransaction

The way Supertransaction execution goes is as follows:

  1. The user sends the Supertransaction to the MEE Node
  2. The MEE node gives back a quote - saying for how much it's willing to execute the Supertransaction
  3. The user either confirms or declines the quote

Getting a Quote from the MEE Node

In order to get the Quote from the MEE Node, we call the getQuote function:

Get Quote
const quote = await meeClient.getQuote(supertransaction)

Checking the Execution Cost

Check the cost of the execution from the quote given by the MEE Node:

Check Execution Cost
quote.paymentInfo.tokenValue // execution price in USD (from chainlink feed)
quote.paymentInfo.tokenWeiAmount // execution price in token base units
quote.paymentInfo.tokenAmount // execution price in token decimal units

Execute the Supertransaction

If you're OK with the quoted execution cost, execute the Supertransaction.

Execute Supertransaction
const { hash } = await meeClient.executeQuote({
  quote
})

Get a Tracking Link for the MEE Explorer

You can track the execution of the Supertransaction by visiting the MEE Explorer

Tracking Link
console.log("Link: ", getMeeScanLink(hash))

Wait for the Supertransaction to Execute

// Wait for the MEE Node to commit the transactions
// within the Supertransaction onchain
const receipt = await meeClient.waitForSupertransactionReceipt({
  hash
})

Concise Implementation

The previous implementation went step by step. Now we will show the concise implementation of this exact same execution.

Concise Implementation
const meeClient = await createMeeClient({
  account: await toMultichainNexusAccount({
    chains: [optimism, base, polygon, arbitrum],
    transports: [http(), http(), http(), http()],
    signer: eoaSigner
  })
})
 
const { hash } = await meeClient.executeQuote({
  quote: await meeClient.getQuote({
    instructions: [
      mcNexus.build({ type: "default", data: { chainId: optimism.id, calls: [{ to: zeroAddress, value: 0n }] } }),
    ],
    feeToken: {
      chainId: optimism.id,
      address: mcUSDC.addressOn(optimism.id)
    }
  })
})
 
const receipt = await meeClient.waitForSupertransactionReceipt({
  hash
})