# Provider Migration Guide

As noted in the Ethereum Provider documentation, we are going to make breaking changes to our provider API and remove our injected window.web3. This guide describes how to migrate to the new provider API, and how to replace our window.web3 object.

All replacement APIs are live, and you can migrate at any time. If you will be affected by the breaking changes, we recommend that you migrate as soon as possible.

You can follow this GitHub issue to be notified of the dates of the breaking changes once we announce them.

# Table of Contents

# Migrating to the New Provider API

# Handling eth_chainId Return Values

Due to a long-standing bug, MetaMask's implementation of the eth_chainId RPC method has returned 0-padded values for the default Ethereum chains except Kovan. For example, instead of 0x1 and 0x2, we currently return 0x01 and 0x02.

For the time being, instead of calling the eth_chainId RPC method, you should use the ethereum.chainId property and the chainChanged event.

# Handling the Removal of chainIdChanged

chainIdChanged is a typo of chainChanged. To migrate, simply listen for chainChanged instead:

// Instead of this:
ethereum.on('chainIdChanged', (chainId) => {
  /* handle the chainId */
});
// Do this:
ethereum.on('chainChanged', (chainId) => {
  /* handle the chainId */
});

# Handling the Removal of isEnabled() and isApproved()

Before the new provider API shipped, we added _metamask.isEnabled and _metamask.isApproved to enable web3 sites to check if they have access to the user's accounts. isEnabled and isApproved are identical, except that isApproved is async. These methods were arguably never that useful, but they are completely redundant since the introduction of MetaMask's permission system.

We recommend that you check for account access in the following ways:

  1. You can call the wallet_getPermissions RPC method and check for the eth_accounts permission.

  2. You can call the eth_accounts RPC method and the ethereum._metamask.isUnlocked() function.

    • MetaMask has to be unlocked before you can access the user's accounts. If the array returned by eth_accounts is empty, check if MetaMask is locked using isUnlocked().

    • If MetaMask is unlocked and you still aren't receiving any accounts, it's time to request accounts using the eth_requestAccounts RPC method.

# Handling the Removal of ethereum.publicConfigStore

How to handle this change depends on if and how you use the publicConfigStore. We have seen examples of listening for provider state changes the publicConfigStore data event, and accessing the publicConfigStore internal state directly.

We recommend that you search your code and its dependencies for references to publicConfigStore. If you find any references, you should understand what it's being used for, and migrate to one of the recommended provider APIs instead. If you don't find any references, you should not be affected by this change.

Although it is possible that your dependencies use the publicConfigStore, we have confirmed that the latest versions of the following common libraries will not be affected by this change:

  • ethers
  • web3 (web3.js)

# Replacing window.web3

For historical reasons, MetaMask injects web3@0.20.7 into all web pages. This version of web3 is deprecated, and is no longer maintained by the web3.js team.

If your website relies on our window.web3 object, your Ethereum-related functionality will break when we stop injecting window.web3. Continue reading to learn more about the migration options.

TIP

Regardless of how you choose to migrate, you will probably want to read the web3@0.20.7 documentation, which you can find here.

# Using window.ethereum Directly

For many web3 sites, the API provided by window.ethereum is more than sufficient. Much of the web3 API simply maps to RPC methods, all of which can be requested using ethereum.request(). For example, here are a couple of actions performed using first window.web3, and then their equivalents using window.ethereum.

/**
 * Getting Accounts
 */
// window.web3
const accounts = web3.eth.accounts;
// window.ethereum
const accounts = await ethereum.request({ method: 'eth_accounts' });
/**
 * Sending a Transaction
 */
// window.web3
web3.eth.sendTransaction(
  {
    to: '0x...',
    'from': '0x...',
    value: '0x...',
    // And so on...
  },
  (error, result) => {
    if (error) {
      return console.error(error);
    }
    // Handle the result
    console.log(result);
  }
);
// window.ethereum
try {
  const transactionHash = await ethereum.request({
    method: 'eth_sendTransaction',
    params: [
      {
        to: '0x...',
        'from': '0x...',
        value: '0x...',
        // And so on...
      },
    ],
  });
  // Handle the result
  console.log(transactionHash);
} catch (error) {
  console.error(error);
}

# Using an Updated Convenience library

If you decide that you need a convenience library, you will have to convert your usage of window.web3 to an updated convenience library. We recommend one of the following options.

# Using @metamask/legacy-web3

WARNING

We strongly recommend that you consider one of the other two migration paths before resorting to this one. It is not future-proof, and it is not guaranteed to work.

Finally, if you just want your web3 site to continue to work, we created @metamask/legacy-web3. This package is a drop-in replacement for our window.web3 that you can add to your web3 site even before MetaMask stops injecting window.web3.

@metamask/legacy-web3 should work exactly like our injected window.web3, but we cannot guarantee that it works perfectly. We will not fix any future incompatibilities between web3@0.20.7 and MetaMask itself, nor will we fix any bugs in web3@0.20.7 itself.

For installation and usage instructions, please see npm.