# JSON-RPC API
Only Available in MetaMask Flask
Snaps is only available in MetaMask Flask (opens new window).
Feature Requests
Do you have feature requests? Other ideas? We'd love to hear about them! Click here (opens new window) to join the discussion.
# Table of Contents
# Unrestricted Methods
# wallet_enable
Only Callable By
- Websites
# Parameters
Array
RequestedPermissions
- The requested permissions.
interface WalletEnableParam {
wallet_snap: {
[snapId: string]: {
version?: string;
};
};
[permissionName: string]: {};
}
# Returns
interface WalletEnableResult {
// The user's Ethereum accounts, if the eth_accounts permission has been
// granted.
accounts: string[];
// The permissions granted to the requester.
permissions: Web3WalletPermission[];
// The user's installed snaps that the requester is permitted to access.
snaps: WalletInstallSnapsResult;
errors?: Error[]; // Any errors encountered during processing.
}
WalletEnableResult
- An object containing the requester's permitted Ethereum accounts, snaps, and granted permissions.
# Description
This is a convenience method for requesting the user's accounts and connecting to / installing snaps.
You can think of it as a combination of eth_requestAccounts
, wallet_installSnaps
, and wallet_requestPermissions
.
See the examples for details.
# Example
let result;
try {
result = await ethereum.request({
method: 'wallet_enable',
// This entire object is ultimately just a list of requested permissions.
// Every snap has an associated permission or permissions, given the prefix `wallet_snap_`
// and its ID. Here, the `wallet_snap` property exists so that callers don't
// have to specify the full permission permission name for each snap.
params: [
{
wallet_snap: {
'npm:@metamask/example-snap': {},
'npm:fooSnap': {
// The optional version argument allows requesting
// SemVer version range, with semantics same as in
// package.json ranges.
version: '^1.0.2',
},
},
eth_accounts: {},
},
],
});
} catch (error) {
// The `wallet_enable` call will throw if the requested permissions are
// rejected.
if (error.code === 4001) {
console.log('The user rejected the request.');
} else {
console.log('Unexpected error:', error);
}
}
// If the installation of all snaps fails, the associated error(s) will be
// returned in the `result.errors` array.
if (result.errors) {
console.log('Snap installation failure :(', result.errors);
} else {
console.log('Success!', result);
// Could print something of the form:
// {
// accounts: ['0xa...', '0xb...'],
// permissions: {
// eth_accounts: {},
// 'wallet_snap_npm:@metamask/example-snap': {},
// },
// snaps: {
// 'npm:@metamask/example-snap': {
// version: '1.0.0',
// permissionName: 'wallet_snap_npm:@metamask/example-snap',
// ...
// },
// 'npm:fooSnap': {
// error: { message: 'The snap does not exist.' },
// },
// }
// }
}
# wallet_getSnaps
Only Callable By
- Websites
# Returns
interface WalletGetSnapsResult {
[snapId: string]: {
/**
* The ID of the Snap.
*/
id: SnapId;
/**
* The initial permissions of the Snap, which will be requested when it is
* installed.
*/
initialPermissions: RequestedSnapPermissions;
/**
* The name of the permission used to invoke the Snap.
*/
permissionName: string;
/**
* The version of the Snap.
*/
version: string;
};
}
WalletGetSnapsResult
- An object containing the requester's permitted snaps.
# Description
This method returns the IDs of the caller's permitted snaps and some relevant metadata.
# Example
const result = await ethereum.request({ method: 'wallet_getSnaps' });
console.log(result);
// If any snaps are permitted, will print e.g.:
// {
// accountRPC methods?s: ['0xa...', '0xb...'],
// permissions: {
// eth_accounts: {},
// 'wallet_snap_npm:@metamask/example-snap': {},
// },
// snaps: {
// 'npm:@metamask/example-snap': {
// version: '1.0.0',
// permissionName: 'wallet_snap_npm:@metamask/example-snap',
// ...
// }
// }
// }
# wallet_installSnaps
Only Callable By
- Websites
Is this the method you're looking for?
This method only installs the requested snaps if the caller is permitted to do so.
You probably want to use wallet_enable
instead, which both requests the permissions for the snaps and installs them.
# Parameters
interface InstallSnapsParam {
[snapId: string]: {
version?: string;
};
}
Array
InstallSnapsParam
- The snaps to install.
# Returns
interface WalletInstallSnapsResult {
[snapId: string]:
| WalletGetSnapsResult[string]
| {
error: Error;
};
}
WalletInstallSnapsResult
- An object mapping the IDs of installed snaps to their metadata or an error if installation failed.
# Description
This method attempts to install the requested snaps, if they are permitted.
If the installation of any snap fails, its object value on the result will contain an error
property with the error that caused the installation to fail.
Optionally, you can specify a SemVer range (opens new window) for any snap to be installed. If you do so, MetaMask will try to install a version of the snap that satisfies the requested range. If a compatible version of a snap is already installed, the request to install that snap will automatically succeed. If an incompatible version is installed, MetaMask will attempt to update the snap to the latest version that satisfies the requested range. The request will succeed if the snap is successfully updated, and fail if the update could not be completed.
# Example
const result = await ethereum.request({
method: 'wallet_installSnaps',
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);
// Could print something of the form:
// {
// 'npm:@metamask/example-snap': {
// version: '1.0.0',
// permissionName: 'wallet_snap_npm:@metamask/example-snap',
// ...
// },
// 'npm:fooSnap': {
// error: { message: 'The snap does not exist.' },
// },
// }
# wallet_invokeSnap
Only Callable By
- Websites
# Parameters
/**
* This is a less stringent version of the JSON-RPC 2.0 request object
* interface. Keep in mind that snaps specify and implement their own JSON-RPC
* APIs, and may require the `id` and `jsonrpc` fields if they wish.
*/
interface SnapRequest {
method: string;
params?: unknown[] | Record<string, unknown>;
id?: string | number;
jsonrpc?: '2.0';
}
Array
string
- The id of the snap to invoke.SnapRequest
- The JSON-RPC request object to send to the invoked snap.
# Returns
unknown
- The result of the snap method call.
# Description
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 will be rejected.
Snaps are fully responsible for implementing their JSON-RPC API; consult the snap's documentation for available methods, their parameters, and return values.
# Example
const result = await ethereum.request({
method: 'wallet_invokeSnap',
params: [
'npm:@metamask/example-snap',
{
method: 'hello',
},
],
});
console.log(result); // We happen to know that this will be `true` or `false`
# Restricted Methods
If a method is restricted, it means that you need the requisite permission before you can call it. Both snaps and dapps / websites can have permissions. Some permissions are only available to snaps, and some are only available to websites. See here for more information about the permission system.
# wallet_snap_*
Only Callable By
- Websites
Is this the method you're looking for?
wallet_invokeSnap
provides a more convenient way of calling this method.
Namespaced Method
This is a namespaced restricted method.
The *
in the name will always be substituted for a string, in this case a snap ID.
# Parameters
Array
SnapRequest
- The JSON-RPC request object to send to the invoked snap.
# Returns
unknown
- The result of the snap method call.
# Description
Invokes the specified JSON-RPC method of the snap corresponding to the specified permission name. The snap must be installed and the caller must have the permission to communicate with the snap, or the request will be rejected.
Snaps are fully responsible for implementing their JSON-RPC API; consult the snap's documentation for available methods, their parameters, and return values.
# Example
const result = await ethereum.request({
method: 'wallet_snap_npm:@metamask/example-snap',
params: [
{
method: 'hello',
},
],
});
console.log(result); // We happen to know that this will be `true` or `false`
# snap_confirm
Only Callable By
- Snaps
# Parameters
interface SnapConfirmParam {
/**
* A prompt, phrased as a question, no greater than 40 characters long.
*/
prompt: string;
/**
* A description, displayed with the prompt, no greater than 140 characters
* long.
*/
description?: string;
/**
* Free-from text content, no greater than 1800 characters long.
* It will be displayed in monospace font in a scrollable text area.
*/
textAreaContent?: string;
}
Array
SnapConfirmParam
- An object containing the contents of the confirmation.
# Returns
boolean
- true
if the user accepted the confirmation, and false
otherwise.
# Description
Calling this method causes a confirmation to be displayed in the MetaMask UI. The contents of the confirmation depend on the parameters, see above for their meaning and format. The user can either approve or reject the confirmation, which will be indicated by the method's return value.
# Example
const result = await wallet.request({
method: 'snap_confirm',
params: [
{
prompt: 'Would you like to take the action?',
description: 'The action is...',
textAreaContent: 'Very detailed information about the action...',
},
],
});
if (result === true) {
// Take the action
} else {
// Do not take the action
}
# snap_getBip44Entropy_*
Powerful Method
If you call this method, you will receive the user's parent key for the protocol that they requested. When that happens, you are now managing a person's keys, and whatever assets they control, on their behalf. Their safety is your responsibility.
Only Callable By
- Snaps
Namespaced Method
This is a namespaced restricted method.
The *
in the name will always be substituted for a string, in this case a BIP-44 coin_type
number.
# Returns
interface BIP44CoinTypeNode {
/**
* The BIP-44 `coin_type` value of this node.
*/
readonly coin_type: number;
/**
* The 0-indexed BIP-44 path depth of this node.
*
* Since this is a `coin_type` node, it will be the number `2`.
*/
readonly depth: 2;
/**
* The Base64-encoded string representation of the key material for this node.
*/
readonly key: string;
/**
* A human-readable representation of the BIP-44 HD tree path of this node.
*
* Since this is a `coin_type` node, it will be of the form:
*
* `m / 44' / coin_type'`
*
* Recall that a complete BIP-44 HD tree path consists of the following nodes:
*
* `m / 44' / coin_type' / account' / change / address_index`
*
* With the following depths:
*
* `0 / 1 / 2 / 3 / 4 / 5`
*/
readonly path: string;
}
BIP44CoinTypeNode
- An object representing the BIP-44 (opens new window) coin_type
HD Tree node and containing its corresponding key material.
# Description
Gets the BIP-44 (opens new window) coin_type
key for the coin_type
number specified by the method name.
This is the "key management" permission of Snaps; use it with the utmost care.
For the authoritative list of available protocols and their coin_type
values, see SLIP-44 (opens new window).
This restricted method is both implemented and designed to be used with @metamask/key-tree
(opens new window).
See the @metamask/key-tree
documentation and below example for more information.
Note that @metamask/key-tree
can help you get the extended private keys (opens new window) for user addresses, but it is your responsibility to know how to use those keys to e.g. derive an address for the relevant protocol or sign a transaction for the user.
# Example
import { getBIP44AddressKeyDeriver } from '@metamask/key-tree';
// By way of example, we will use Dogecoin, which has `coin_type` 3.
const dogecoinNode = await wallet.request({
method: 'snap_getBip44Entropy_3',
});
// Next, we'll create an address key deriver function for the Dogecoin coin_type node.
// In this case, its path will be: m / 44' / 3' / 0' / 0 / address_index
const deriveDogecoinAddress = getBIP44AddressKeyDeriver(dogecoinNode);
// These are Node.js Buffer representations of the extended private keys for
// the respective addresses.
// m / 44' / 3' / 0' / 0 / 0
const addressKey0 = deriveDogecoinAddress(0);
// m / 44' / 3' / 0' / 0 / 1
const addressKey1 = deriveDogecoinAddress(1);
// Now, you can ask the user to e.g. sign transactions!
# snap_manageState
Plaintext Data Storage
The data stored by this method is persisted to disk in unencrypted / plaintext form. Never store any secrets using this method.
Only Callable By
- Snaps
# Parameters
Array
'clear' | 'get' | 'update'
- The state operation to perform.Record<string, unknown> | void
- The value to update state with if the operation isupdate
, and nothing otherwise.
# Returns
null | Record<string, unknown>
- The value stored in state of the operation is get
, and null
otherwise.
# Description
This method allows the snap to persist some data to disk in plaintext form and retrieve it at will. Since the data is in plaintext, the method should never be used to store secrets of any kind.
# Example
// First, let's persist some data
await wallet.request({
method: 'snap_manageState',
params: ['update', { hello: 'world' }],
});
// Then, at some later time, let's get the data we stored
const persistedData = await wallet.request({
method: 'snap_manageState',
params: ['get'],
});
console.log(persistedData);
// { hello: 'world' }
// Finally, if there's no need to store data anymore, we can clear it out
await wallet.request({
method: 'snap_manageState',
params: ['clear'],
});