Experimental APIs

wallet_ RPC methods


Most all Ethereum wallets display some set of tokens, usually from a centrally curated registry of tokens.

At MetaMask, we believe the future of tokens has the potential to be much bigger than any one party can curate, and we want to enable this explosion of creativity.

In support of this goal, we have implemented support for EIP 747, which provides a way for your site to suggest a token that a user might want to track in their wallet.

The code is simple:

	method: 'metamask_watchAsset',
	params: {
		"type":"ERC20", // Initially only supports ERC20, but eventually more!
			"address": tokenAddress, // The address that the token is at.
			"symbol": tokenSymbol, // A ticker symbol or shorthand, up to 5 chars.
			"decimals": tokenDecimals, // The number of decimals in the token
			"image": tokenImage, // A string url of the token logo
	id: Math.round(Math.random() * 100000),
}, (err, addedBoolean) => {


We even created a sample Dapp so developers could suggest their tokens to users with a simple hyperlink, without a line of code. Visit it here.


This method is in support of a new onboarding process that helps users find their way back to the site that requested MetaMask be installed. This RPC method is used by the @metamask/onboarding library to tell MetaMask which site initiated onboarding. It should be send directly from the site doing the onboarding; there are no parameters. We recommend using our @metamask/onboarding library instead of using this method directly.


MetaMask supports the standard Ethereum Provider API as defined in both EIP-1193 and EIP-1102. In addition to ethereum.enable() and its RPC equivalent ethereum.send('eth_requestAccounts'), MetaMask also exposes a collection of nonstandard convenience methods on the provider object at ethereum._metamask. Using these methods is dangerous since other dapp browsers may or may not implement them; for this reason, these methods are intentionally kept at a MetaMask-specific namespace to avoid confusion with standard provider functionality.

Each method and its intended use is described below.

ethereum._metamask.isEnabled: () => boolean (To Be Removed)

Note: This will be removed in early 2020.

This method returns a boolean indicating if the current domain has access to user accounts. This is useful for determining if a user has approved account access for the current session.

ethereum._metamask.isApproved: () => Promise<boolean> (To Be Removed)

Note: This will be removed in early 2020.

This method returns a Promise that resolves to a Boolean indicating if the current domain has a cached approval. This is useful for determining if an approval popup will show when ethereum.enable() is called, since it indicates if a past approval exists.

ethereum._metamask.isUnlocked: () => Promise<boolean>

This method returns a Promise that resolves to a Boolean indicating if MetaMask is unlocked by the user. This is useful for knowing if MetaMask is unlocked in order to provide meaningful instructions to the user during onboarding. Note that this does not indicate if a user has approved account exposure.

eth_ RPC methods


This method is used for getting a public key that based on the nacl library. With such a key, you can encrypt a message.

    jsonrpc: '2.0',
    method: 'eth_getEncryptionPublicKey',
    params: [accounts[0]],
    from: accounts[0],
}, function(error, encryptionpublickey) {
    if (!error) {
	window.encryptionpublickey = encryptionpublickey.result;
    } else {

An example of how to encrypt a message via sigUtil

const encryptedMessage = web3.toHex(JSON.stringify(sigUtil.encrypt(window.encryptionpublickey, {'data': 'Hello world!'}, 'x25519-xsalsa20-poly1305')));


This method is used to decrypt a message that was encrypted using the public key based on the nacl library.

    jsonrpc: '2.0',
    method: 'eth_decrypt',
    params: [encryptedMessage, accounts[0]],
    from: accounts[0],
}, function(error, message) {
    console.log(error, message);
    if (!error) {
	console.log(message.result); // Hello world!
    } else {