Skip to main content

About the Snaps APIs

Snaps, dapps, and MetaMask can communicate with each other using the Snaps API, MetaMask JSON-RPC API, and custom JSON-RPC APIs.

Snaps API

Snaps can access the global object snap, which has one method: request. You can use this object to make Snaps API requests. These API methods allow Snaps to extend or modify the functionality of MetaMask.

To call each method (except the interactive UI methods), you must first request permission in the Snap manifest file. For example, to call snap_notify, first request the snap_notify permission:

snap.manifest.json
"initialPermissions": {
"snap_notify": {}
}

Your Snap can then call snap_notify in its source code:

index.ts
await snap.request({
method: "snap_notify",
params: {
type: "inApp",
message: "Hello, world!",
},
});

MetaMask JSON-RPC API

Dapp requests

Dapps can install and communicate with Snaps using the following MetaMask JSON-RPC API methods:

A dapp must first request permission to communicate with a Snap using wallet_requestSnaps. The dapp can then call wallet_snap or wallet_invokeSnap on the permitted Snap. For example, to call wallet_snap:

index.js
// Request permission to connect to the Snap.
await window.ethereum.request({
method: "wallet_requestSnaps",
params: {
"npm:hello-snap": {},
},
});

// Call the "hello" method of the Snap using wallet_snap.
const response = await window.ethereum.request({
method: "wallet_snap",
params: {
snapId: "npm:hello-snap",
request: {
method: "hello",
},
},
});

console.log(response); // "world!"

Snap requests

Snaps can also call some MetaMask JSON-RPC API methods using the ethereum global, which is an EIP-1193 provider.

To expose ethereum to the Snap execution environment, a Snap must first request the endowment:ethereum-provider permission. For example, to call eth_requestAccounts, first request the required permission:

snap.manifest.json
"initialPermissions": {
"endowment:ethereum-provider": {}
}

Your Snap can then call eth_requestAccounts in its source code:

index.ts
await ethereum.request({ "method": "eth_requestAccounts" });

The ethereum global available to Snaps has fewer capabilities than window.ethereum for dapps. Snaps can only use it to make read requests, not to write to the blockchain or initiate transactions. Snaps can call all MetaMask API methods except the following:

Custom JSON-RPC APIs

Snaps can implement their own custom JSON-RPC APIs to communicate with dapps and other Snaps. To do so, a Snap must expose the onRpcRequest entry point and request the endowment:rpc permission.

The Snap's custom API is entirely up to you, as long as it's a valid JSON-RPC API.

Does my Snap need a custom API?

If your Snap can do something useful without receiving and responding to JSON-RPC requests, such as providing transaction insights, you do not need to implement a custom API. However, if you want to do something such as manage the user's keys for a particular protocol and create a dapp that sends transactions for that protocol via your Snap, you must implement a custom API.

For example, to create a simple Snap with a custom API, first request the endowment:rpc permission. Set dapps to true to enable dapps to make JSON-RPC requests.

snap.manifest.json
"initialPermissions": {
"endowment:rpc": {
"dapps": true
}
}

Your Snap can then implement and expose a custom API using the onRpcRequest function:

index.ts
module.exports.onRpcRequest = async ({ origin, request }) => {
switch (request.method) {
// Expose a "hello" JSON-RPC method to dapps.
case "hello":
return "world!";

default:
throw new Error("Method not found.");
}
};

A dapp can then install the Snap and call the exposed method:

index.js
// Request permission to connect to the Snap.
// If the Snap is not already installed, the user will be prompted to install it.
await window.ethereum.request({
method: "wallet_requestSnaps",
params: {
// Assuming the Snap is published to npm using the package name "hello-snap".
"npm:hello-snap": {},
},
});

// Invoke the "hello" JSON-RPC method exposed by the Snap.
const response = await window.ethereum.request({
method: "wallet_invokeSnap",
params: {
snapId: "npm:hello-snap",
request: {
method: "hello",
},
},
});

console.log(response); // "world!"