From 7c00ad0dde6a7a085cd8ed93f06243cf974267d8 Mon Sep 17 00:00:00 2001 From: ryanml Date: Thu, 15 Apr 2021 10:41:40 -0700 Subject: [PATCH 1/3] Handling infura blockage (#10883) * Handling infura blockage * Adding blockage home notification * Updating copy, adding temporary notification dismissal * Addressing review feedback * Using eth_blockNumber method to check Infura availability * Handling network changes in availability check --- app/_locales/en/messages.json | 4 ++ app/scripts/controllers/network/network.js | 55 ++++++++++++++++++++++ app/scripts/controllers/preferences.js | 27 +++++++++++ shared/constants/network.js | 2 + ui/app/pages/home/home.component.js | 27 +++++++++++ ui/app/pages/home/home.container.js | 2 + ui/app/selectors/selectors.js | 4 ++ 7 files changed, 121 insertions(+) diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 70e25f644..fe1d4f7e9 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -878,6 +878,10 @@ "infoHelp": { "message": "Info & Help" }, + "infuraBlockedNotification": { + "message": "MetaMask is unable to connect to the blockchain host. Review possible reasons $1.", + "description": "$1 is a clickable link with with text defined by the 'here' key" + }, "initialTransactionConfirmed": { "message": "Your initial transaction was confirmed by the network. Click OK to go back." }, diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js index 1c9c80600..cd0fc0bce 100644 --- a/app/scripts/controllers/network/network.js +++ b/app/scripts/controllers/network/network.js @@ -17,16 +17,19 @@ import { NETWORK_TYPE_TO_ID_MAP, MAINNET_CHAIN_ID, RINKEBY_CHAIN_ID, + INFURA_BLOCKED_KEY, } from '../../../../shared/constants/network'; import { isPrefixedFormattedHexString, isSafeChainId, } from '../../../../shared/modules/network.utils'; +import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout'; import createMetamaskMiddleware from './createMetamaskMiddleware'; import createInfuraClient from './createInfuraClient'; import createJsonRpcClient from './createJsonRpcClient'; const env = process.env.METAMASK_ENV; +const fetchWithTimeout = getFetchWithTimeout(30000); let defaultProviderConfigOpts; if (process.env.IN_TEST === 'true') { @@ -52,6 +55,10 @@ export const NETWORK_EVENTS = { NETWORK_DID_CHANGE: 'networkDidChange', // Fired when the actively selected network *will* change NETWORK_WILL_CHANGE: 'networkWillChange', + // Fired when Infura returns an error indicating no support + INFURA_IS_BLOCKED: 'infuraIsBlocked', + // Fired when not using an Infura network or when Infura returns no error, indicating support + INFURA_IS_UNBLOCKED: 'infuraIsUnblocked', }; export default class NetworkController extends EventEmitter { @@ -152,6 +159,15 @@ export default class NetworkController extends EventEmitter { // Ping the RPC endpoint so we can confirm that it works const ethQuery = new EthQuery(this._provider); const initialNetwork = this.getNetworkState(); + const { type } = this.getProviderConfig(); + const isInfura = INFURA_PROVIDER_TYPES.includes(type); + + if (isInfura) { + this._checkInfuraAvailability(type); + } else { + this.emit(NETWORK_EVENTS.INFURA_IS_UNBLOCKED); + } + ethQuery.sendAsync({ method: 'net_version' }, (err, networkVersion) => { const currentNetwork = this.getNetworkState(); if (initialNetwork === currentNetwork) { @@ -235,6 +251,45 @@ export default class NetworkController extends EventEmitter { // Private // + async _checkInfuraAvailability(network) { + const rpcUrl = `https://${network}.infura.io/v3/${this._infuraProjectId}`; + + let networkChanged = false; + this.once(NETWORK_EVENTS.NETWORK_DID_CHANGE, () => { + networkChanged = true; + }); + + try { + const response = await fetchWithTimeout(rpcUrl, { + method: 'POST', + body: JSON.stringify({ + jsonrpc: '2.0', + method: 'eth_blockNumber', + params: [], + id: 1, + }), + }); + + if (networkChanged) { + return; + } + + if (response.ok) { + this.emit(NETWORK_EVENTS.INFURA_IS_UNBLOCKED); + } else { + const responseMessage = await response.json(); + if (networkChanged) { + return; + } + if (responseMessage.error === INFURA_BLOCKED_KEY) { + this.emit(NETWORK_EVENTS.INFURA_IS_BLOCKED); + } + } + } catch (err) { + log.warn(`MetaMask - Infura availability check failed`, err); + } + } + _switchNetwork(opts) { this.emit(NETWORK_EVENTS.NETWORK_WILL_CHANGE); this.setNetworkState('loading'); diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 240aaaa18..f76646a9f 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -66,6 +66,7 @@ export default class PreferencesController { completedOnboarding: false, // ENS decentralized website resolution ipfsGateway: 'dweb.link', + infuraBlocked: null, ...opts.initState, }; @@ -75,6 +76,7 @@ export default class PreferencesController { this.openPopup = opts.openPopup; this.migrateAddressBookState = opts.migrateAddressBookState; this._subscribeToNetworkDidChange(); + this._subscribeToInfuraAvailability(); global.setPreference = (key, value) => { return this.setFeatureFlag(key, value); @@ -679,6 +681,31 @@ export default class PreferencesController { }); } + _subscribeToInfuraAvailability() { + this.network.on(NETWORK_EVENTS.INFURA_IS_BLOCKED, () => { + this._setInfuraBlocked(true); + }); + this.network.on(NETWORK_EVENTS.INFURA_IS_UNBLOCKED, () => { + this._setInfuraBlocked(false); + }); + } + + /** + * + * A setter for the `infuraBlocked` property + * @param {boolean} isBlocked - Bool indicating whether Infura is blocked + * + */ + _setInfuraBlocked(isBlocked) { + const { infuraBlocked } = this.store.getState(); + + if (infuraBlocked === isBlocked) { + return; + } + + this.store.updateState({ infuraBlocked: isBlocked }); + } + /** * Updates `accountTokens`, `tokens`, `accountHiddenTokens` and `hiddenTokens` of current account and network according to it. * diff --git a/shared/constants/network.js b/shared/constants/network.js index 7b1e1b2ad..8160260e6 100644 --- a/shared/constants/network.js +++ b/shared/constants/network.js @@ -93,3 +93,5 @@ export const NATIVE_CURRENCY_TOKEN_IMAGE_MAP = { [TEST_ETH_SYMBOL]: TEST_ETH_TOKEN_IMAGE_URL, [BNB_SYMBOL]: BNB_TOKEN_IMAGE_URL, }; + +export const INFURA_BLOCKED_KEY = 'countryBlocked'; diff --git a/ui/app/pages/home/home.component.js b/ui/app/pages/home/home.component.js index 84ecd217f..fb66fc964 100644 --- a/ui/app/pages/home/home.component.js +++ b/ui/app/pages/home/home.component.js @@ -34,6 +34,8 @@ const LEARN_MORE_URL = 'https://metamask.zendesk.com/hc/en-us/articles/360045129011-Intro-to-MetaMask-v8-extension'; const LEGACY_WEB3_URL = 'https://metamask.zendesk.com/hc/en-us/articles/360053147012'; +const INFURA_BLOCKAGE_URL = + 'https://metamask.zendesk.com/hc/en-us/articles/360059386712'; export default class Home extends PureComponent { static contextTypes = { @@ -74,10 +76,12 @@ export default class Home extends PureComponent { originOfCurrentTab: PropTypes.string, disableWeb3ShimUsageAlert: PropTypes.func.isRequired, pendingConfirmations: PropTypes.arrayOf(PropTypes.object).isRequired, + infuraBlocked: PropTypes.bool.isRequired, }; state = { mounted: false, + canShowBlockageNotification: true, }; componentDidMount() { @@ -176,6 +180,7 @@ export default class Home extends PureComponent { setWeb3ShimUsageAlertDismissed, originOfCurrentTab, disableWeb3ShimUsageAlert, + infuraBlocked, } = this.props; return ( @@ -241,6 +246,28 @@ export default class Home extends PureComponent { key="home-privacyModeDefault" /> ) : null} + {infuraBlocked && this.state.canShowBlockageNotification ? ( + + global.platform.openTab({ url: INFURA_BLOCKAGE_URL }) + } + > + {t('here')} + , + ])} + ignoreText={t('dismiss')} + onIgnore={() => { + this.setState({ + canShowBlockageNotification: false, + }); + }} + key="home-infuraBlockedNotification" + /> + ) : null} ); } diff --git a/ui/app/pages/home/home.container.js b/ui/app/pages/home/home.container.js index 929833e14..721c7a15e 100644 --- a/ui/app/pages/home/home.container.js +++ b/ui/app/pages/home/home.container.js @@ -11,6 +11,7 @@ import { getUnapprovedTemplatedConfirmations, getWeb3ShimUsageStateForOrigin, unconfirmedTransactionsCountSelector, + getInfuraBlocked, } from '../../selectors'; import { @@ -104,6 +105,7 @@ const mapStateToProps = (state) => { originOfCurrentTab, shouldShowWeb3ShimUsageNotification, pendingConfirmations, + infuraBlocked: getInfuraBlocked(state), }; }; diff --git a/ui/app/selectors/selectors.js b/ui/app/selectors/selectors.js index ab22f2387..0bf2c07af 100644 --- a/ui/app/selectors/selectors.js +++ b/ui/app/selectors/selectors.js @@ -419,6 +419,10 @@ export function getIpfsGateway(state) { return state.metamask.ipfsGateway; } +export function getInfuraBlocked(state) { + return Boolean(state.metamask.infuraBlocked); +} + export function getUSDConversionRate(state) { return state.metamask.usdConversionRate; } From 7786d0512074e7a95a54463eab9a14c8df5a23b3 Mon Sep 17 00:00:00 2001 From: MetaMask Bot Date: Thu, 15 Apr 2021 18:12:50 +0000 Subject: [PATCH 2/3] Version v9.4.0 --- CHANGELOG.md | 2 ++ app/manifest/_base.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e96f45c6..e4a7b916e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Current Develop Branch +## 9.4.0 Thu Apr 15 2021 + ## 9.3.0 Fri Mar 26 2021 - [#10777](https://github.com/MetaMask/metamask-extension/pull/10777): Display BNB token image for default currency on BSC network home screen - [#10721](https://github.com/MetaMask/metamask-extension/pull/10721): Swaps support for the Binance network diff --git a/app/manifest/_base.json b/app/manifest/_base.json index ab4d0d4ec..5cc5a0246 100644 --- a/app/manifest/_base.json +++ b/app/manifest/_base.json @@ -78,6 +78,6 @@ "notifications" ], "short_name": "__MSG_appName__", - "version": "9.3.0", + "version": "9.4.0", "web_accessible_resources": ["inpage.js", "phishing.html"] } From 80ad43ce788afada9e1cf8e09f7b37e1fbdb8bbc Mon Sep 17 00:00:00 2001 From: Dan J Miller Date: Thu, 15 Apr 2021 15:53:41 -0230 Subject: [PATCH 3/3] [skip e2e] Update changelog for v9.4.0 (#10892) --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4a7b916e..effe9fd23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Current Develop Branch ## 9.4.0 Thu Apr 15 2021 +- [#10883](https://github.com/MetaMask/metamask-extension/pull/10883): Notify users when MetaMask is unable to connect to the blockchain host ## 9.3.0 Fri Mar 26 2021 - [#10777](https://github.com/MetaMask/metamask-extension/pull/10777): Display BNB token image for default currency on BSC network home screen