Skip to main content

Interact with multiple networks

Flask Only
This feature is experimental and only available in MetaMask Flask, the canary distribution of MetaMask.

You can use the Multichain API to interact with multiple blockchain networks in MetaMask simultaneously. The API allows you to target specific chains as part of each method call, eliminating the need to detect and switch networks before executing signatures and transactions.

Prerequisites

Install MetaMask Flask.

Steps

1. Set up your project

Establish a connection to MetaMask Flask and set up basic message handling using the wallet_notify event:

// Initialize the connection to Flask.
const EXTENSION_ID = "ljfoeinjpaedjfecbmggjgodbgkmjkjk"; // Flask extension ID
const extensionPort = chrome.runtime.connect(EXTENSION_ID)

// Set up message listener for events.
extensionPort.onMessage.addListener((msg) => {
// Format wallet_notify events to be able to read them later.
if (msg.data.method === "wallet_notify") {
console.log("wallet_notify:", {
scope: msg.data.params.scope,
method: msg.data.params.notification.method,
subscription: msg.data.params.notification.params.subscription,
number: msg.data.params.notification.params.result.number
})
return;
}
console.log(msg.data)
})

2. Manage sessions

To interact with multiple networks simultaneously, you'll create and manage CAIP-25 multichain sessions with MetaMask.

2.1. Check existing sessions

Before creating a new session, check if one already exists using the wallet_getSession method. For example:

extensionPort.postMessage({
type: "caip-x",
data: {
jsonrpc: "2.0",
method: "wallet_getSession",
params: {}
}
});

If the result returns an empty sessionScopes parameter, then a multichain session is not active and you must create a new session.

2.2. Create a new session

Create a new session using the wallet_createSession method. Specify which chains and methods your dapp needs access to, using the optionalScopes parameter. For example:

extensionPort.postMessage({
type: "caip-x",
data: {
jsonrpc: "2.0",
method: "wallet_createSession",
params: {
optionalScopes: {
"wallet:eip155": { // General Ethereum wallet functions
methods: ["wallet_addEthereumChain"],
notifications: [],
accounts: []
},
"eip155:1": { // Ethereum Mainnet
methods: [
"personal_sign",
"eth_blockNumber",
"eth_gasPrice",
"eth_getBalance",
"eth_getTransactionCount",
"eth_sendTransaction",
"eth_subscribe"
],
notifications: ["eth_subscription"],
accounts: []
},
"eip155:59141": { // Linea Sepolia
methods: [
"personal_sign",
"eth_blockNumber",
"eth_gasPrice",
"eth_getBalance",
"eth_getTransactionCount",
"eth_sendTransaction",
"eth_subscribe"
],
notifications: ["eth_subscription"],
accounts: []
}
}
}
}
});

In optionalScopes:

  • Request access to networks that your dapp intends to interact with. If a requested network is not configured by the MetaMask user, you might need to add the network.
  • For each network, request access to Wallet API methods that your dapp expects to call at any time. The methods listed in the sessionScope of each Multichain API response indicate which wallet capabilities your dapp can use during the session.

2.3. Check for session changes

To ensure your dapp responds appropriately to changes in the wallet session, such as network or account updates, check for session changes using the wallet_sessionChanged event. Based on the event data, you can determine whether your dapp needs to request additional permissions using wallet_createSession.

extensionPort.onMessage.addListener((msg) => {
// Check for wallet_sessionChanged events.
if (msg.data.method === "wallet_sessionChanged") {
// Update permissions if required.
}
});

3. Invoke Wallet API methods

You can invoke a subset of the Wallet JSON-RPC API methods on a specified chain using the wallet_invokeMethod Multichain API method. The following are example Wallet API functionalities that are compatible with the Multichain API.

3.1. Sign in with Ethereum

You can implement Sign-In with Ethereum (SIWE) by invoking personal_sign. For example:

// Specify an account that the signature will be requested for.
const address = "0xAddress";
const message = `Sign-in request for ${address} at ${new Date().toLocaleString()}`;

// Invoke the personal_sign Wallet API method.
const sign = await extensionPort.postMessage({
type: "caip-x",
data: {
"jsonrpc": "2.0",
method: "wallet_invokeMethod",
params: {
scope: "eip155:1",
request: {
method: "personal_sign",
params: [message, address],
}
}
}
})

3.2. Check balances

You can read gas token balances by invoking eth_getBalance. For example:

extensionPort.postMessage({
type: "caip-x",
data: {
jsonrpc: "2.0",
method: "wallet_invokeMethod",
params: {
scope: "eip155:1",
request: {
method: "eth_getBalance",
params: ["0xAddress", "latest"],
}
}
}
});

3.3. Send transactions

You can send transactions on a specific network, by invoking eth_sendTransaction. For example:

return extensionPort.postMessage({
type: "caip-x",
data: {
jsonrpc: "2.0",
method: "wallet_invokeMethod",
params: {
// Specify a chain ID where the user has sufficient gas.
scope: "eip155:1",
request: {
method: "eth_sendTransaction",
params: [{
from: "0xFromAccount",
to: "0xToAccount",
value: "0x0",
gasLimit: "0x5028",
maxPriorityFeePerGas: "0x3b9aca00",
maxFeePerGas: "0x2540be400",
}]
}
}
}
});