Provider Migration Guide
::: tip Attention MetaMask Users If you are a MetaMask user attempting to use a legacy Ethereum website that hasn't migrated to the new API, please see the section on the MetaMask Legacy Web3 Extension.
Except for such legacy websites, no action is required for MetaMask users. :::
In January of 2021, we made a number of breaking changes to our provider API, and removed our injected window.web3
. These changes are live on all platforms as of version:
9.0.2
of the MetaMask browser extension1.0.9
of MetaMask Mobile
This guide describes how to migrate to the new provider API, and how to replace our window.web3
. To understand why we made these changes, please see this blog post.
Table of Contents
[[toc]]
Summary of Breaking Changes
window.web3
Removal
As part of the breaking changes, we stopped injecting web3.js
version 0.20.7
as window.web3
into web pages. MetaMask still injects a dummy object at window.web3
, in order to issue warnings when websites attempt to access window.web3
.
window.ethereum
API Changes
We made the following breaking changes to the window.ethereum
API:
- Ensure that chain IDs returned by
eth_chainId
are not 0-padded- For example, instead of
0x01
, we always return0x1
, wherever the chain ID is returned or accessible. - Note that this only affects the default Ethereum chains, except Kovan, whose chain ID is formatted correctly (
0x2a
).
- For example, instead of
- Stop emitting
chainIdChanged
, and instead emitchainChanged
- Remove the following experimental methods:
ethereum._metamask.isEnabled
ethereum._metamask.isApproved
- Remove the
ethereum.publicConfigStore
object- This object was, despite its name, never intended for public consumption. Its removal may affect those who do not use it directly, e.g. if another library you use relies on the object.
- Remove the
ethereum.autoRefreshOnNetworkChange
property- Consumers can still set this property on the provider, it just won't do anything.
- Deprecate the
web3.currentProvider
method- Use @metamask/detect-provider to detect the current provider.
Replacing window.web3
::: warning Pages No Longer Reload on Chain Changes Since we removed our window.web3
, MetaMask no longer automatically reloads the page on chain/network changes.
Please see Handling the Removal of ethereum.autoRefreshOnNetworkChange
for details. :::
For historical reasons, MetaMask injected web3@0.20.7
into all web pages. That version of web3
is deprecated, has known security issues, and is no longer maintained by the web3.js team. Therefore, we decided to remove this library.
If your website relied on our window.web3
object, you have to migrate. Please continue reading to understand your options. Some are as simple as a one-line change.
::: tip Tip Regardless of how you choose to migrate, you may 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 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
.
<<< @/docs/snippets/web3ToProvider.js
Using an Updated Convenience library
If you decide that you need a convenience library, you have to convert your usage of window.web3
to an updated convenience library. We recommend ethers
(documentation).
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 we will not add new features to it. :::
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 website even before remove window.web3
on all platforms.
@metamask/legacy-web3
should work exactly like our injected window.web3
, including by refreshing the page on chain/network changes, 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 the npm listing.
Using the MetaMask Legacy Web3 Extension
We created the MetaMask Legacy Web3 Extension for any users of websites that still expect window.web3
to be injected. If you install this extension alongside the regular MetaMask wallet extension, websites that rely on our old window.web3 API should start working again.
As with the regular extension, it’s critical that you only install from the official browser extension stores. Please follow the relevant link below to install the Legacy Web3 extension in your browser:
Migrating to the New Provider API
Handling eth_chainId
Return Values
The eth_chainId
RPC method now returns correctly formatted values, e.g. 0x1
and 0x2
, instead of incorrectly formatted values, e.g. 0x01
and 0x02
. MetaMask's implementation of eth_chainId
used to return 0-padded values for the default Ethereum chains except Kovan. If you expect 0-padded chain ID values from eth_chainId
, make sure to update your code to expect the correct format instead.
For more details on chain IDs and how to handle them, see 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 the _metamask.isEnabled
and _metamask.isApproved
methods to enable web3 sites to check if they have access to the user's accounts. isEnabled
and isApproved
functioned identically, except that isApproved
was async
. These methods were arguably never that useful, and they became completely redundant with the introduction of MetaMask's permission system.
We recommend that you check for account access in the following ways:
You can call the
wallet_getPermissions
RPC method and check for theeth_accounts
permission.You can call the
eth_accounts
RPC method and theethereum._metamask.isUnlocked()
method.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 usingisUnlocked()
.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 relied on 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 (as of January 2021) of the following common libraries were not affected by this change:
ethers
web3
(web3.js)
Handling the Removal of ethereum.autoRefreshOnNetworkChange
The ethereum.autoRefreshOnNetworkChange
was a mutable boolean property used to control whether MetaMask reloaded the page on chain/network changes. However, it only caused the page to be reloaded if the a script access a property on window.web3
. Therefore, this property was removed along with window.web3
.
Despite this, we still recommend reloading the page on chain changes. Some convenience libraries, such as ethers, will continue to reload the page by default. If you don't use such a convenience library, you'll have to reload the page manually. Please see the chainChanged
event for details.