diff --git a/docs/guide/README.md b/docs/guide/README.md index f4213c63c31..5c21ecda384 100644 --- a/docs/guide/README.md +++ b/docs/guide/README.md @@ -7,22 +7,18 @@ Welcome to MetaMask’s Developer Documentation. This documentation is for learn - For up to the minute news, follow our [Peepeth](https://peepeth.com/MetaMask/), [Twitter](https://twitter.com/metamask_io) or [Medium](https://medium.com/metamask) pages. - To learn how to contribute to the MetaMask project itself, visit our [Internal Docs](https://github.com/MetaMask/metamask-extension/tree/develop/docs). -::: warning Breaking Provider Changes -We are in the process of shipping changes that will break some Ethereum web applications. -These changes have already shipped for the MetaMask browser extension, and may ship for MetaMask Mobile at any time. -Please read our [Migration Guide](./provider-migration.html) for more details. - -Action is required for Ethereum application developers only. -MetaMask users do not need to do anything. +::: tip Recent Breaking Provider Changes +If you are an Ethereum application developer and are looking for information about our January 2021 provider API changes, +please see our [Migration Guide](./guide/provider-migration.html) for more details. ::: ## Why MetaMask MetaMask was created to meet the needs of secure and usable Ethereum-based web sites. In particular, it handles account management and connecting the user to the blockchain. -- [Get started here](/guide/getting-started.html) -- [Learn more about our JavaScript Provider API](/guide/ethereum-provider.html) -- [Learn more about our RPC API](/guide/rpc-api.html) +- [Get started here](./guide/getting-started.html) +- [Learn more about our JavaScript Provider API](./guide/ethereum-provider.html) +- [Learn more about our RPC API](./guide/rpc-api.html) ## Account Management diff --git a/docs/guide/create-dapp.md b/docs/guide/create-dapp.md index 171c75359df..15ebe1b7378 100644 --- a/docs/guide/create-dapp.md +++ b/docs/guide/create-dapp.md @@ -6,7 +6,7 @@ We will be building this [app](https://metamask.github.io/test-dapp/) ## Project Setup -Before you setup make sure you've visited and gone through our [Getting Started Guide](/guide/getting-started.html#getting-started) +Before you setup make sure you've visited and gone through our [Getting Started Guide](./guide/getting-started.html#getting-started) Make sure you have: @@ -69,7 +69,7 @@ As you can see here, as soon as the content in the DOM is loaded we are calling What we'll cover in part one: -- [Connecting to the MetaMask Wallet](/guide/create-dapp.html#connecting-to-the-metamask-wallet) +- [Connecting to the MetaMask Wallet](./guide/create-dapp.html#connecting-to-the-metamask-wallet) - See our eth_accounts result - Display our network number - Display our ChainId diff --git a/docs/guide/ethereum-provider.md b/docs/guide/ethereum-provider.md index c7ca2e65147..a56abedb598 100644 --- a/docs/guide/ethereum-provider.md +++ b/docs/guide/ethereum-provider.md @@ -4,15 +4,9 @@ We recommend that all web3 site developers read the [Basic Usage](#basic-usage) section. ::: -::: warning Breaking Provider Changes -We are in the process of shipping changes that will break some Ethereum web applications. -These changes have already shipped for the MetaMask browser extension, and may ship for MetaMask Mobile at any time. -Please see the [Breaking Provider Changes](#upcoming-breaking-changes) section for details. - -If your website is broken and you're wondering how to fix it, please see the [Migration Guide](./provider-migration.html). - -Action is required for Ethereum application developers only. -MetaMask users do not need to do anything. +::: tip Recent Breaking Provider Changes +If you are an Ethereum application developer and are looking for information about our January 2021 provider API changes, +please see our [Migration Guide](./guide/provider-migration.html) for more details. ::: MetaMask injects a global API into websites visited by its users at `window.ethereum`. @@ -41,47 +35,6 @@ if (provider) { [[toc]] -## Breaking Changes - -::: tip Tip -If you are new to using the provider, you do not have to worry about these changes, and can skip ahead [to the next section](#api). -::: - -::: warning Breaking Changes are Live -On January 12, 2020, these changes went live for the Firefox extension. -Chrome, Brave, and Edge will go live in the coming days. -MetaMask Mobile will receive these changes as soon as possible. - -If your website is broken and you're wondering how to fix it, please see the [Migration Guide](./provider-migration.html). -If you want to learn more about the changes, please read on. -::: - -### `window.ethereum` API Changes - -The following changes to the `window.ethereum` API are breaking: - -- Ensure that chain IDs returned by `eth_chainId` are **not** 0-padded - - For example, instead of `0x01`, we will always return `0x1`, wherever the chain ID is returned or accessible. - - Note that this _only_ affects the [default Ethereum chains](#chain-ids), _except_ Kovan, whose chain ID is formatted correctly (`0x2a`). -- Stop emitting `chainIdChanged`, and instead emit `chainChanged` -- 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 will still be able to set this property on the provider, it just won't do anything. - -### `window.web3` Removal - -::: tip Tip -If you do not use the `window.web3` object injected by MetaMask, you can ignore this section. -::: - -As part of the breaking changes, we will stop injecting `web3.js` as `window.web3` into web pages. -MetaMask will continue to inject a shim object as `window.web3`, to issue warnings when websites attempt to access `window.web3`. - ## Basic Usage For any non-trivial Ethereum web application — a.k.a. dapp, web3 site etc. — to work, you will have to: @@ -95,7 +48,7 @@ You can learn how to accomplish the other two by reviewing the snippet in the [U The provider API is all you need to create a full-featured web3 application. -That said, many developers use a convenience library, such as [ethers](https://www.npmjs.com/package/ethers) and [web3.js](https://www.npmjs.com/package/web3), instead of using the provider directly. +That said, many developers use a convenience library, such as [ethers](https://www.npmjs.com/package/ethers), instead of using the provider directly. If you are in need of higher-level abstractions than those provided by this API, we recommend that you use a convenience library. ## Chain IDs @@ -162,7 +115,7 @@ If the request fails for any reason, the Promise will reject with an [Ethereum R MetaMask supports most standardized Ethereum RPC methods, in addition to a number of methods that may not be supported by other wallets. -See the MetaMask [RPC API documentation](./rpc-api.html) for details. +See the MetaMask [RPC API documentation](./guide/rpc-api.html) for details. #### Example diff --git a/docs/guide/getting-started.md b/docs/guide/getting-started.md index e376b302e47..b513b3b5ca0 100644 --- a/docs/guide/getting-started.md +++ b/docs/guide/getting-started.md @@ -9,7 +9,7 @@ This guide assumes intermediate knowledge of HTML, CSS, and JavaScript. Once MetaMask is installed and running, you should find that new browser tabs have a `window.ethereum` object available in the developer console. This is how your website will interact with MetaMask. -You can review the full API for that object [here](./ethereum-provider.html). +You can review the full API for that object [here](./guide/ethereum-provider.html). Note that in **over the course of 2020**, we are introducing significant changes to this API, and we recommend that you refer to its documentation. ## Basic Considerations @@ -24,7 +24,7 @@ if (typeof window.ethereum !== 'undefined') { } ``` -You can review the full API for the `window.ethereum` object [here](./ethereum-provider.html). +You can review the full API for the `window.ethereum` object [here](./guide/ethereum-provider.html). ### Running a Test Network @@ -36,7 +36,7 @@ Since your seed phrase is the power to control all your accounts, it is probably #### Resetting Your Local Nonce Calculation -If you're running a test blockchain and restart it, you can accidentally confuse MetaMask because it calculates the next [nonce](./sending-transactions.html#nonce-ignored) +If you're running a test blockchain and restart it, you can accidentally confuse MetaMask because it calculates the next [nonce](./guide/sending-transactions.html#nonce-ignored) based on both the network state _and_ the known sent transactions. To clear MetaMask's transaction queue, and effectively reset its nonce calculation, you can use the `Reset Account` button in `Settings` (available in the top-right sandwich menu). @@ -53,7 +53,7 @@ Currently there are a few stateful things to consider when interacting with this - What is the current account? Both of these are available synchronously as `ethereum.networkVersion` and `ethereum.selectedAddress`. -You can listen for changes using events too, see ([the API reference](./ethereum-provider.html)). +You can listen for changes using events too, see ([the API reference](./guide/ethereum-provider.html)). ### Connecting to MetaMask diff --git a/docs/guide/mobile-best-practices.md b/docs/guide/mobile-best-practices.md index b61aa47bc32..2b7521980d2 100644 --- a/docs/guide/mobile-best-practices.md +++ b/docs/guide/mobile-best-practices.md @@ -4,16 +4,12 @@ If this page doesn't answer your question, please feel free to open an issue [in ## The Provider (window.ethereum) -::: danger Breaking Provider Changes -We are in the process of shipping changes that will break some Ethereum web applications. -These changes have already shipped for the MetaMask browser extension, and may ship for MetaMask Mobile at any time. -Please read our [Migration Guide](./provider-migration.html) for more details. - -Action is required for Ethereum application developers only. -MetaMask users do not need to do anything. +::: tip Recent Breaking Provider Changes +If you are an Ethereum application developer and are looking for information about our January 2021 provider API changes, +please see our [Migration Guide](./guide/provider-migration.html) for more details. ::: -The [provider API](./ethereum-provider.html) is the same for both MetaMask Mobile and the desktop extension. +The [provider API](./guide/ethereum-provider.html) is the same for both MetaMask Mobile and the desktop extension. However, the providers become available (i.e., are injected into the page) at different points in the page lifecycle. ### Provider Availability diff --git a/docs/guide/provider-migration.md b/docs/guide/provider-migration.md index 4d73fbafddb..0565c36b605 100644 --- a/docs/guide/provider-migration.md +++ b/docs/guide/provider-migration.md @@ -1,34 +1,62 @@ # Provider Migration Guide ::: tip Attention MetaMask Users -This documentation is for Ethereum application developers. -As a MetaMask user, you don't need to do anything. +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](#using-the-metamask-legacy-web3-extension). + +Except for such legacy websites, no action is required for MetaMask users. ::: -As noted in the [Ethereum Provider documentation](./ethereum-provider.html#upcoming-breaking-changes), breaking changes went live for the Firefox extension on January 12, 2020. -Chrome, Brave, and Edge will go live in the coming days. -MetaMask Mobile will receive these changes as soon as possible. +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 extension +* `1.0.9` of MetaMask Mobile -The breaking changes include modifications to the `window.ethereum` API and the removal of `window.web3`. 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](https://medium.com/metamask/breaking-changes-to-the-metamask-provider-are-here-7b11c9388be9). ## 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 return `0x1`, wherever the chain ID is returned or accessible. + * Note that this _only_ affects the [default Ethereum chains](./guide/ethereum-provider.html#chain-ids), _except_ Kovan, whose chain ID is formatted correctly (`0x2a`). +* Stop emitting `chainIdChanged`, and instead emit `chainChanged` +* 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. + ## Replacing `window.web3` -::: warning Pages Will No Longer Reload on Chain Changes -With the removal of `window.web3`, MetaMask will no longer automatically reload the page on chain/network changes. +::: 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`](#handling-the-removal-of-ethereum-autorefreshonnetworkchange) for details. ::: -For historical reasons, MetaMask has injected [`web3@0.20.7`](https://github.com/ethereum/web3.js/tree/0.20.7) into all web pages. -This version of `web3` is deprecated, [has known security issues](https://github.com/ethereum/web3.js/issues/3065), and is no longer maintained by the [web3.js](https://github.com/ethereum/web3.js/) team. +For historical reasons, MetaMask injected [`web3@0.20.7`](https://github.com/ethereum/web3.js/tree/0.20.7) into all web pages. +That version of `web3` is deprecated, [has known security issues](https://github.com/ethereum/web3.js/issues/3065), and is no longer maintained by the [web3.js](https://github.com/ethereum/web3.js/) team. Therefore, we decided to remove this library. -If your website relied on our `window.web3` object, you will have to migrate. +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. @@ -38,22 +66,22 @@ Regardless of how you choose to migrate, you may want to read the `web3@0.20.7` ### 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()`](./ethereum-provider.html#ethereum-request-args). +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()`](./guide/ethereum-provider.html#ethereum-request-args). 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 will have to convert your usage of `window.web3` to 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`](https://npmjs.com/package/ethers) ([documentation](https://docs.ethers.io/)). ### 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, we will not add new features to it. +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`](https://npmjs.com/package/@metamask/legacy-web3). @@ -62,27 +90,27 @@ This package is a drop-in replacement for our `window.web3` that you can add to `@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 [npm](https://npmjs.com/package/@metamask/legacy-web3). +For installation and usage instructions, please see the [npm listing](https://npmjs.com/package/@metamask/legacy-web3). ### Using the MetaMask Legacy Web3 Extension -We have created the [**MetaMask Legacy Web3 Extension**](https://github.com/MetaMask/legacy-web3-extension) for any users of web sites 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. +We created the [**MetaMask Legacy Web3 Extension**](https://github.com/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: * [Chrome, Brave](https://chrome.google.com/webstore/detail/metamask-legacy-web3/dgoegggfhkapjphahmgihfgemkgecdgl) * [Edge](https://microsoftedge.microsoft.com/addons/detail/metamask-legacy-web3/obkfjbjkiofoponpkmphnpaaadebfloh?hl=en-US) -* [Firefox](https://addons.mozilla.org/en-US/firefox/addon/metamask-legacy-web3/) (Will be published soon) +* [Firefox](https://addons.mozilla.org/en-US/firefox/addon/metamask-legacy-web3/) ## 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](./ethereum-provider.html#chain-ids) _except_ Kovan. +MetaMask's implementation of `eth_chainId` used to return 0-padded values for the [default Ethereum chains](./guide/ethereum-provider.html#chain-ids) _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](./ethereum-provider.html#chainchanged). +For more details on chain IDs and how to handle them, see the [`chainChanged` event](./guide/ethereum-provider.html#chainchanged). ### Handling the Removal of `chainIdChanged` @@ -104,42 +132,42 @@ ethereum.on('chainChanged', (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](./rpc-api.html#eth-requestaccounts). +to enable web3 sites to check if they have [access to the user's accounts](./guide/rpc-api.html#eth-requestaccounts). `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](./rpc-api.html#permissions). +These methods were arguably never that useful, and they became completely redundant with the introduction of MetaMask's [permission system](./guide/rpc-api.html#permissions). We recommend that you check for account access in the following ways: -1. You can call the [`wallet_getPermissions` RPC method](./rpc-api.html#wallet-getpermissions) and check for the `eth_accounts` permission. +1. You can call the [`wallet_getPermissions` RPC method](./guide/rpc-api.html#wallet-getpermissions) and check for the `eth_accounts` permission. -2. You can call the `eth_accounts` RPC method and the [`ethereum._metamask.isUnlocked()` method](./ethereum-provider.html#ethereum-metamask-isunlocked). +2. You can call the `eth_accounts` RPC method and the [`ethereum._metamask.isUnlocked()` method](./guide/ethereum-provider.html#ethereum-metamask-isunlocked). - - MetaMask has to be unlocked before you can access the user's accounts. + * 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](./rpc-api.html#eth-requestaccounts). + * If MetaMask is unlocked and you still aren't receiving any accounts, it's time to request accounts using the [`eth_requestAccounts` RPC method](./guide/rpc-api.html#eth-requestaccounts). ### Handling the Removal of `ethereum.publicConfigStore` -How to handle this change depends on if and how you use the `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](./ethereum-provider.html#using-the-provider) instead. +If you find any references, you should understand what it's being used for, and migrate to [one of the recommended provider APIs](./guide/ethereum-provider.html#using-the-provider) 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: +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) +* `ethers` +* `web3` (web3.js) ### Handling the Removal of `ethereum.autoRefreshOnNetworkChange` -The `ethereum.autoRefreshOnNetworkChange` is a mutable boolean property used to control whether MetaMask reloaded the page on chain/network changes. -However, it only causes the page to be reloaded if the a script access a property on `window.web3`. -Therefore, this property will be removed along with `window.web3`. +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](https://www.npmjs.com/package/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](./ethereum-provider.html#chainchanged) for details. +Please see the [`chainChanged` event](./guide/ethereum-provider.html#chainchanged) for details. diff --git a/docs/guide/rpc-api.md b/docs/guide/rpc-api.md index e1c8b6495e0..4e46065127b 100644 --- a/docs/guide/rpc-api.md +++ b/docs/guide/rpc-api.md @@ -1,6 +1,6 @@ # RPC API -MetaMask uses the [`ethereum.request(args)` method](./ethereum-provider.html#ethereum-request-args) to wrap an RPC API. +MetaMask uses the [`ethereum.request(args)` method](./guide/ethereum-provider.html#ethereum-request-args) to wrap an RPC API. The API is based on an interface exposed by all Ethereum clients, along with a growing number of methods that may or may not be supported by other wallets. @@ -55,7 +55,7 @@ If you're interested in learning more about the theory behind this _capability_- ::: tip Tip EIP-1102 This method is specified by [EIP-1102](https://eips.ethereum.org/EIPS/eip-1102). -It is equivalent to the deprecated [`ethereum.enable()`](./ethereum-provider.html#ethereum-enable) provider API method. +It is equivalent to the deprecated [`ethereum.enable()`](./guide/ethereum-provider.html#ethereum-enable) provider API method. Under the hood, it calls [`wallet_requestPermissions`](#wallet-requestpermissions) for the `eth_accounts` permission. Since `eth_accounts` is currently the only permission, this method is all you need for now. @@ -180,7 +180,7 @@ If the caller has no permissions, the array will be empty. ::: tip Tip As an API consumer, you are unlikely to have to call this method yourself. -Please see the [Onboarding Library documentation](/onboarding-library.html) for more information. +Please see the [Onboarding Library documentation](./guide/onboarding-library.html) for more information. ::: #### Returns diff --git a/docs/guide/site-compatibility-checklist.md b/docs/guide/site-compatibility-checklist.md index e68946b4530..83b054165b1 100644 --- a/docs/guide/site-compatibility-checklist.md +++ b/docs/guide/site-compatibility-checklist.md @@ -1,10 +1,10 @@ # Site Compatibility Checklist -- Ensure that your site is compatible with the [MetaMask Ethereum provider API](./ethereum-provider.html) and review the [MetaMask Mobile best practices](./mobile-best-practices.html) +- Ensure that your site is compatible with the [MetaMask Ethereum provider API](./guide/ethereum-provider.html) and review the [MetaMask Mobile best practices](./guide/mobile-best-practices.html) - Include MetaMask Mobile as a listed wallet in your application, and link to open the MetaMask Mobile app (if installed) or to go to the app store (if not yet installed) - We recommend adding a `Connect With MetaMask` button and using [deeplinks](https://metamask.github.io/metamask-deeplinks/) - - For more information about deeplinks, please see the [deeplinking documentation](./mobile-best-practices.html#deeplinking) + - For more information about deeplinks, please see the [deeplinking documentation](./guide/mobile-best-practices.html#deeplinking) Please direct your users to either the relevant app store listing or to [the MetaMask homepage](https://metamask.io/download.html) to download MetaMask Mobile