| description | toc_max_heading_level | sidebar_custom_props | ||
|---|---|---|---|---|
Use the Multichain API. |
4 |
|
:::flaskOnly :::
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.
:::note See also
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)
})To interact with multiple networks simultaneously, you'll create and manage CAIP-25 multichain sessions with MetaMask.
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.
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
sessionScopeof each Multichain API response indicate which wallet capabilities your dapp can use during the session.
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.
}
});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.
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],
}
}
}
})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"],
}
}
}
});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",
}]
}
}
}
});