Snaps JSON-RPC API
Snaps communicate with MetaMask using the Snaps JSON-RPC API. These API methods allow snaps to modify the functionality of MetaMask, and websites (dapps) to install and communicate with individual snaps. Some methods are only callable by snaps, and some are only callable by websites.
Unrestricted methods
You can call unrestricted methods without requesting permission to do so.
wallet_getSnaps
Returns the IDs of the caller's permitted snaps and some relevant metadata.
This method is only callable by websites.
Returns
An object containing the requester's permitted snaps. Each snap is an object containing:
id
- The ID of the snap.initialPermissions
- The initial permissions of the snap, which will be requested when the snap is installed.version
- The version of the snap.enabled
-true
if the snap is enabled,false
otherwise.blocked
-true
if the snap is blocked,false
otherwise.
Example
- JavaScript
- Result
const result = await window.ethereum.request({ method: 'wallet_getSnaps' });
console.log(result);
// Example result if any snaps are permitted
{
'npm:@metamask/example-snap': {
version: '1.0.0',
id: 'npm:@metamask/example-snap',
enabled: true,
blocked: false,
},
}
wallet_requestSnaps
Requests permission for a website to communicate with the specified snaps and attempts to install them if they're not already installed. If the installation of any snap fails, returns the error that caused the failure.
You can optionally specify a SemVer range for a snap. MetaMask attempts to install a version of the snap that satisfies the requested range. If a compatible version of a snap is already installed, the request succeeds. If an incompatible version is installed, MetaMask attempts to update the snap to the latest version that satisfies the requested range. The request succeeds if the snap is successfully updated.
This method is only callable by websites.
Parameters
An object containing the snaps to request permission to communicate with.
Returns
An object mapping the IDs of installed snaps to either their metadata or an error if installation fails.
Example
- JavaScript
- Result
try {
const result = await window.ethereum.request({
method: 'wallet_requestSnaps',
params: {
'npm:@metamask/example-snap': {},
'npm:fooSnap': {
// The optional version argument allows requesting a SemVer version
// range, with the same semantics as npm package.json ranges.
version: '^1.0.2',
},
},
});
console.log(result);
} catch (error) {
console.log(error);
}
{
'npm:@metamask/example-snap': {
version: '1.0.0',
id: 'npm:@metamask/example-snap',
enabled: true,
blocked: false,
},
'npm:fooSnap': {
version: '1.0.5',
id: 'npm:fooSnap',
enabled: true,
blocked: false,
},
}
Restricted methods
For restricted methods callable by snaps, a snap must request permission to call the method in the
snap manifest file.
For restricted methods callable by websites, a website must request permission to call the method using
wallet_requestPermissions
.
snap_dialog
Displays a dialog in the MetaMask UI. There are three types of dialogs with different parameters and return types:
This method is only callable by snaps.
Alert dialog
Displays an alert that can only be acknowledged.
Parameters
An object containing the contents of the alert dialog:
type
- The type of dialog ('Alert'
).content
- The content of the alert, as a custom UI component.
Example
import { panel, text, heading } from '@metamask/snaps-ui';
await snap.request({
method: 'snap_dialog',
params: {
type: 'Alert',
content: panel([
heading('Something happened in the system'),
text('The thing that happened is...'),
]),
},
});
// Code that should execute after the alert has been acknowledged
Confirmation dialog
Displays a confirmation that can be accepted or rejected.
Parameters
An object containing the contents of the confirmation dialog:
type
- The type of dialog ('Confirmation'
).content
- The content of the confirmation, as a custom UI component.
Returns
true
if the confirmation was accepted, false
otherwise.
Example
import { panel, text, heading } from '@metamask/snaps-ui';
const result = await snap.request({
method: 'snap_dialog',
params: {
type: 'Confirmation',
content: panel([
heading('Would you like to take the action?'),
text('The action is...'),
]),
},
});
if (result === true) {
// Do the action
}
Prompt dialog
Displays a prompt where the user can enter a text response.
Parameters
An object containing the contents of the prompt dialog:
type
- The type of dialog ('Prompt'
).content
- The content of the prompt, as a custom UI component.placeholder
- Text that will be in the input field when nothing is typed.
Returns
The text entered by the user.
Example
import { panel, text, heading } from '@metamask/snaps-ui';
const walletAddress = await snap.request({
method: 'snap_dialog',
params: {
type: 'Prompt',
content: panel([
heading('What is the wallet address?'),
text('Please enter the wallet address to be monitored'),
]),
placeholder: '0x123...',
},
});
// `walletAddress` will be a string containing the address entered by the user
snap_getBip32Entropy
If you call this method, you receive the user's parent key for the derivation path they request. You're managing the user's keys and assets on their behalf. Their safety is your responsibility.
Gets the SLIP-10 key for the path
and curve
specified by the method name.
This method is designed to be used with the
@metamask/key-tree
module.
@metamask/key-tree
can help you get the
extended private keys
for user addresses, but it's your responsibility to know how to use those keys to, for example,
derive an address for the relevant protocol or sign a transaction for the user.
This method is only callable by snaps.
Parameters
An object containing:
path
- An array, starting withm
, containing the BIP-32 derivation path to the key to retrieve. For example,["m", "44'", "60'"]
.curve
- The curve to use for the key derivation. Must be'ed25519'
or'secp256k1'
.
Returns
An object representing the SLIP-10 HD tree node and containing its corresponding key material:
depth
- The 0-indexed path depth of the node.parentFingerprint
- The fingerprint of the parent key, or 0 if this is a master node.index
- The index of the node, or 0 if this is a master node.privateKey
- The private key of the node.publicKey
- The public key of the node.chainCode
- The chain code of the node.curve
- The name of the curve used by the node:'ed25519'
or'secp256k1'
.
Example
- Manifest file
- JavaScript
{
"initialPermissions": {
"snap_getBip32Entropy": [
{
"path": ["m", "44'", "3'"],
"curve": "secp256k1" // Or "ed25519"
}
]
}
}
import { SLIP10Node } from '@metamask/key-tree';
// This example uses Dogecoin, which has a derivation path starting with `m/44'/3'`.
const dogecoinNode = await snap.request({
method: 'snap_getBip32Entropy',
params: {
// Must be specified exactly in the manifest
path: ['m', "44'", "3'"],
curve: 'secp256k1',
},
});
// Next, create an instance of a SLIP-10 node for the Dogecoin node.
const dogecoinSlip10Node = await SLIP10Node.fromJSON(dogecoinNode);
// m / 44' / 3' / 0'
const accountKey0 = await dogecoinSlip10Node.derive(["bip32:0'"]);
// m / 44' / 3' / 1'
const accountKey1 = await dogecoinSlip10Node.derive(["bip32:1'"]);
// Now, you can ask the user to sign transactions, etc.
snap_getBip32PublicKey
Gets the BIP-32 public key for the
derivation path specified by the path
parameter.
Note that this returns the public key, not the extended public key (xpub
), or Ethereum address.
This method is only callable by snaps.
Parameters
An object containing:
path
- An array, starting withm
, containing the BIP-32 derivation path to the public key to retrieve. For example,["m", "44'", "60'"]
.curve
- The curve to use for the key derivation. Must be'ed25519'
or'secp256k1'
.compressed
- Indicates whether the public key should be compressed. The default isfalse
.
Returns
The public key as hexadecimal string.
Example
- Manifest file
- JavaScript
{
"initialPermissions": {
"snap_getBip32PublicKey": [
{
"path": ["m", "44'", "3'", "0'", "0", "0"],
"curve": "secp256k1" // Or "ed25519"
}
]
}
}
// This example uses Dogecoin, which has a derivation path starting with `m/44'/3'`.
const dogecoinPublicKey = await snap.request({
method: 'snap_getBip32PublicKey',
params: {
// The path and curve must be specified in the initial permissions.
path: ['m', "44'", "3'", "0'", '0', '0'],
curve: 'secp256k1',
compressed: false,
},
});
// `0x...`
console.log(dogecoinPublicKey);
snap_getBip44Entropy
If you call this method, you receive the user's parent key for the protocol they request. You're managing the user's keys and assets on their behalf. Their safety is your responsibility.
Gets the BIP-44 coin_type
key
for the coin_type
number specified by the method name.
See SLIP-44 for the list of
available protocols and their coin_type
values.
This method is designed to be used with the
@metamask/key-tree
module.
@metamask/key-tree
can help you get the
extended private keys
for user addresses, but it's your responsibility to know how to use those keys to, for example,
derive an address for the relevant protocol or sign a transaction for the user.
This method is only callable by snaps.
Parameters
An object containing coinType
, the BIP-44 coin type to get the entropy for.
Returns
An object representing the
BIP-44 coin_type
HD tree node
and containing its corresponding key material:
coin_type
- The BIP-44 coin type value of the node.depth
- The 0-indexed BIP-44 path depth of the node. Since this is acoin_type
node, the depth is2
.privateKey
- The hexadecimal-encoded string representation of the private key for the node.publicKey
- The hexadecimal-encoded string representation of the public key for the node.chainCode
- The hexadecimal-encoded string representation of the chain code for the node.path
- A human-readable representation of the BIP-44 HD tree path of the node. Since this is acoin_type
node, the path is of the formm / 44' / coin_type'
.
Example
- Manifest file
- JavaScript
{
"initialPermissions": {
"snap_getBip44Entropy": [
{
"coinType": 3
}
]
}
}
import { getBIP44AddressKeyDeriver } from '@metamask/key-tree';
// This example uses Dogecoin, which has `coin_type` 3.
const dogecoinNode = await snap.request({
method: 'snap_getBip44Entropy',
params: {
coinType: 3,
},
});
// Next, create an address key deriver function for the Dogecoin coin_type node.
// In this case, its path is: m / 44' / 3' / 0' / 0 / address_index
const deriveDogecoinAddress = await getBIP44AddressKeyDeriver(dogecoinNode);
// These are BIP-44 nodes containing the extended private keys for
// the respective derivation paths.
// m / 44' / 3' / 0' / 0 / 0
const addressKey0 = await deriveDogecoinAddress(0);
// m / 44' / 3' / 0' / 0 / 1
const addressKey1 = await deriveDogecoinAddress(1);
// Now, you can ask the user to sign transactions, etc.
snap_getEntropy
Gets a deterministic 256-bit entropy value, specific to the snap and the user's account. You can use this entropy to generate a private key, or any other value that requires a high level of randomness. Other snaps can't access this entropy, and it changes if the user's secret recovery phrase changes.
You can optionally specify a salt to generate different entropy for different purposes. Using a salt results in entropy unrelated to the entropy generated without a salt.
This value is deterministic: it's always the same for the same snap, user account, and salt.
This method is only callable by snaps.
Parameters
An object containing:
version
- The number1
. This is reserved for future use.salt
(optional) - An arbitrary string to be used as a salt for the entropy. This can be used to generate different entropy for different purposes.
Returns
The entropy as a hexadecimal string.
Example
- Manifest file
- JavaScript
{
"initialPermissions": {
"snap_getEntropy": {}
}
}
const entropy = await snap.request({
method: 'snap_getEntropy',
params: {
version: 1,
salt: 'foo', // Optional
},
});
// `0x...`
console.log(entropy);
snap_manageState
Allows the snap to persist up to 100 MB of data to disk and retrieve it at will. The data is automatically encrypted using a snap-specific key and automatically decrypted when retrieved.
This method is only callable by snaps.
Parameters
An object containing:
operation
- The state operation to perform ('clear'
,'get'
, or'update'
).newState
- The value to update state with if the operation isupdate
, and nothing otherwise.
Returns
The value stored in state if the operation is get
, and null
otherwise.
Example
// Persist some data.
await snap.request({
method: 'snap_manageState',
params: { operation: 'update', newState: { hello: 'world' } },
});
// At a later time, get the data stored.
const persistedData = await snap.request({
method: 'snap_manageState',
params: { operation: 'get' },
});
console.log(persistedData);
// { hello: 'world' }
// If there's no need to store data anymore, clear it out.
await snap.request({
method: 'snap_manageState',
params: { operation: 'clear' },
});
snap_notify
Displays a notification in MetaMask or natively in the browser. Snaps can trigger a short notification text for actionable or time sensitive information.
This method is only callable by snaps.
Parameters
An object containing the contents of the notification:
type
- The notification type. SpecifyinApp
to display the notification in the MetaMask UI, andnative
to display the notification in the browser. We recommend usinginApp
because there's no guarantee that native notifications are displayed to the user.message
- A message to show in the notification.
Example
await snap.request({
method: 'snap_notify',
params: {
type: 'inApp',
message: 'Hello, world!',
},
});
wallet_snap
A website must request the wallet_snap
permission using
wallet_requestPermissions
to
interact with the specified snaps.
A website can also call this method to invoke the specified JSON-RPC method of the specified snap.
This method is synonymous to wallet_invokeSnap
, and is only callable by websites.
Most websites only make one call to wallet_requestPermissions
.
Consecutive calls to wallet_requestPermissions
for the wallet_snap
permission overwrites a
website's existing permissions to interact with snaps.
To deal with this, you must write custom logic to merge existing snap IDs with new ones you're requesting.
Use wallet_getSnaps
to get a list of a website's permitted snaps.
Parameters
When requesting this permission, specify a caveat of type snapIds
.
Specify each snap to request permission to interact with as an entry in the value
field of the caveat.
Each snap entry can include a version
to install.
The default is the latest version.
When calling this method, specify an object containing:
snapId
- The ID of the snap to invoke.request
- The JSON-RPC request object to send to the invoked snap.
Returns
Result of the snap method call.
Example
- wallet_requestPermissions
- wallet_snap
The following is an example of calling wallet_requestPermissions
to request the wallet_snap
permission:
const result = await ethereum.request({
method: 'wallet_requestPermissions',
params: [{
wallet_snap: {
caveats: [
{
type: 'snapIds',
value: {
'npm:@metamask/example-snap': { version: '1.0.0' },
'npm:@metamask/foo-bar-snap': { version: '1.2.1' },
}
}
]
}
}],
});
The following is an example of calling wallet_snap
:
const result = await ethereum.request({
method: 'wallet_snap',
params: {
snapId: 'npm:@metamask/example-snap',
request: {
method: 'hello',
},
},
});
console.log(result); // In this example, the result is a boolean.
wallet_invokeSnap
Invokes the specified JSON-RPC method of the specified snap. The snap must be installed and the caller must have the permission to communicate with the snap, or the request is rejected.
Snaps are fully responsible for implementing their JSON-RPC API. Consult the snap's documentation for available methods, their parameters, and return values.
This method is only callable by websites.
Parameters
An object containing:
snapId
- The ID of the snap to invoke.request
- The JSON-RPC request object to send to the invoked snap.
Returns
Result of the snap method call.
Example
const result = await ethereum.request({
method: 'wallet_invokeSnap',
params: {
snapId: 'npm:@metamask/example-snap',
request: {
method: 'hello',
},
},
});
console.log(result); // In this example, the result is a boolean.