Skip to content
by Unity Nodes
docs.near.orgweb3 apps › tutorials › frontend multiple contracts

Frontend Interacting with Multiple Contracts

Updated 01-11-2026

Interact with multiple contracts in your frontend.

This example showcases how to interact with multiple contracts from a single frontend.

The frontend uses @hot-labs/near-connect to connect a wallet and sign transactions, and near-api-js to query each contract through a shared RPC provider. Its Wallet wrapper exposes viewMethod for queries and signAndSendTransactions for wallet requests.

Particularly, this example shows how to:

  1. Query data from multiple contracts.
  2. Call methods in multiple contracts simultaneously.

Query Data from Multiple Contracts

To query multiple contracts simply perform multiple view calls:

async function getGreetingAndMessages() {
  // query the greeting in Hello NEAR
  const currentGreeting = await wallet.viewMethod({ method: 'get_greeting', contractId: HELLO_ADDRESS });

  // query the last 4 messages in the Guest Book
  const totalMessages = await wallet.viewMethod({method: 'total_messages', contractId: GUEST_ADDRESS })
  const from_index = (totalMessages > 4? totalMessages - 4: 0).toString();
  const latestMessages = await wallet.viewMethod({ method: 'get_messages', contractId: GUEST_ADDRESS, args: {from_index, limit: "4"} });

  // handle UI stuff
  update_UI(currentGreeting, from_index, latestMessages);
}

See code on GitHub


Dispatching Multiple Transactions

The wallet object enables to dispatch multiple transactions simultaneously. However, please notice that the transactions execute independently.

Dispatching multiple transactions at once is just a nice way to improve UX, because the user interacts with the wallet only once.

const guestTx = {
  receiverId: GUEST_ADDRESS,
  actions: [ // actions execute sequentially
    {
      type: 'FunctionCall',
      params: {
        methodName: 'add_message', args: { text: greeting.value },
        gas: THIRTY_TGAS, deposit: GUEST_DEPOSIT
      }
    },
  ]
}

const helloTx = {
  receiverId: HELLO_ADDRESS,
  actions: [ // if any action fails, they all rollback together
    {
      type: 'FunctionCall',
      params: {
        methodName: 'set_greeting', args: { greeting: greeting.value },
        gas: THIRTY_TGAS, deposit: NO_DEPOSIT
      }
    }
  ]
}

// Sign **independent** transactions: If one fails, the other **DOES NOT** revert
try {
  await wallet.signAndSendTransactions({ transactions: [helloTx, guestTx] });
  await getGreetingAndMessages();
} catch (error) {
  window.alert(`Could not submit both transactions: ${error.message}`);
} finally {
  document.querySelector('#signed-in-flow').classList.remove('please-wait');
}

See code on GitHub

In this example, the user signs two independent transactions:

  1. A transaction to call set_greeting in our Hello NEAR example
  2. A transaction to call add_message in our GuestBook example

[!WARNING]

Even when the user accepts signing the transactions at the same time, the transactions remain independent. This is, if one fails, the other is NOT rolled back.


Batch Actions

You can aggregate multiple actions directed towards a same contract into a single transaction. Batched actions execute sequentially, with the added benefit that, if one fails then they all get reverted.

  // Register a user and transfer them FT on a single take
  const REGISTER_DEPOSIT = "1250000000000000000000";

  const ftTx = {
    receiverId: FT_ADDRESS,
    actions: [
      {
        type: 'FunctionCall',
        params: {
          methodName: 'storage_deposit',
          args: { account_id: "<receiver-account>" },
          gas: THIRTY_TGAS, deposit: REGISTER_DEPOSIT
        }
      },
      {
        type: 'FunctionCall',
        params: {
          methodName: 'ft_transfer',
          args: { receiver_id: "<receiver-account>", amount: amount_in_yocto },
          gas: THIRTY_TGAS, deposit: "1" }
      }
    ]
  }

  // Ask the wallet to sign and send the transaction
  await wallet.signAndSendTransactions({ transactions: [ ftTx ] })