mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
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
This commit is contained in:
parent
0974709e7c
commit
2f8908804a
@ -878,6 +878,10 @@
|
|||||||
"infoHelp": {
|
"infoHelp": {
|
||||||
"message": "Info & Help"
|
"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": {
|
"initialTransactionConfirmed": {
|
||||||
"message": "Your initial transaction was confirmed by the network. Click OK to go back."
|
"message": "Your initial transaction was confirmed by the network. Click OK to go back."
|
||||||
},
|
},
|
||||||
|
@ -17,16 +17,19 @@ import {
|
|||||||
NETWORK_TYPE_TO_ID_MAP,
|
NETWORK_TYPE_TO_ID_MAP,
|
||||||
MAINNET_CHAIN_ID,
|
MAINNET_CHAIN_ID,
|
||||||
RINKEBY_CHAIN_ID,
|
RINKEBY_CHAIN_ID,
|
||||||
|
INFURA_BLOCKED_KEY,
|
||||||
} from '../../../../shared/constants/network';
|
} from '../../../../shared/constants/network';
|
||||||
import {
|
import {
|
||||||
isPrefixedFormattedHexString,
|
isPrefixedFormattedHexString,
|
||||||
isSafeChainId,
|
isSafeChainId,
|
||||||
} from '../../../../shared/modules/network.utils';
|
} from '../../../../shared/modules/network.utils';
|
||||||
|
import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout';
|
||||||
import createMetamaskMiddleware from './createMetamaskMiddleware';
|
import createMetamaskMiddleware from './createMetamaskMiddleware';
|
||||||
import createInfuraClient from './createInfuraClient';
|
import createInfuraClient from './createInfuraClient';
|
||||||
import createJsonRpcClient from './createJsonRpcClient';
|
import createJsonRpcClient from './createJsonRpcClient';
|
||||||
|
|
||||||
const env = process.env.METAMASK_ENV;
|
const env = process.env.METAMASK_ENV;
|
||||||
|
const fetchWithTimeout = getFetchWithTimeout(30000);
|
||||||
|
|
||||||
let defaultProviderConfigOpts;
|
let defaultProviderConfigOpts;
|
||||||
if (process.env.IN_TEST === 'true') {
|
if (process.env.IN_TEST === 'true') {
|
||||||
@ -52,6 +55,10 @@ export const NETWORK_EVENTS = {
|
|||||||
NETWORK_DID_CHANGE: 'networkDidChange',
|
NETWORK_DID_CHANGE: 'networkDidChange',
|
||||||
// Fired when the actively selected network *will* change
|
// Fired when the actively selected network *will* change
|
||||||
NETWORK_WILL_CHANGE: 'networkWillChange',
|
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 {
|
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
|
// Ping the RPC endpoint so we can confirm that it works
|
||||||
const ethQuery = new EthQuery(this._provider);
|
const ethQuery = new EthQuery(this._provider);
|
||||||
const initialNetwork = this.getNetworkState();
|
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) => {
|
ethQuery.sendAsync({ method: 'net_version' }, (err, networkVersion) => {
|
||||||
const currentNetwork = this.getNetworkState();
|
const currentNetwork = this.getNetworkState();
|
||||||
if (initialNetwork === currentNetwork) {
|
if (initialNetwork === currentNetwork) {
|
||||||
@ -235,6 +251,45 @@ export default class NetworkController extends EventEmitter {
|
|||||||
// Private
|
// 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) {
|
_switchNetwork(opts) {
|
||||||
this.emit(NETWORK_EVENTS.NETWORK_WILL_CHANGE);
|
this.emit(NETWORK_EVENTS.NETWORK_WILL_CHANGE);
|
||||||
this.setNetworkState('loading');
|
this.setNetworkState('loading');
|
||||||
|
@ -66,6 +66,7 @@ export default class PreferencesController {
|
|||||||
completedOnboarding: false,
|
completedOnboarding: false,
|
||||||
// ENS decentralized website resolution
|
// ENS decentralized website resolution
|
||||||
ipfsGateway: 'dweb.link',
|
ipfsGateway: 'dweb.link',
|
||||||
|
infuraBlocked: null,
|
||||||
...opts.initState,
|
...opts.initState,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -75,6 +76,7 @@ export default class PreferencesController {
|
|||||||
this.openPopup = opts.openPopup;
|
this.openPopup = opts.openPopup;
|
||||||
this.migrateAddressBookState = opts.migrateAddressBookState;
|
this.migrateAddressBookState = opts.migrateAddressBookState;
|
||||||
this._subscribeToNetworkDidChange();
|
this._subscribeToNetworkDidChange();
|
||||||
|
this._subscribeToInfuraAvailability();
|
||||||
|
|
||||||
global.setPreference = (key, value) => {
|
global.setPreference = (key, value) => {
|
||||||
return this.setFeatureFlag(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.
|
* Updates `accountTokens`, `tokens`, `accountHiddenTokens` and `hiddenTokens` of current account and network according to it.
|
||||||
*
|
*
|
||||||
|
@ -96,3 +96,5 @@ export const NATIVE_CURRENCY_TOKEN_IMAGE_MAP = {
|
|||||||
[TEST_ETH_SYMBOL]: TEST_ETH_TOKEN_IMAGE_URL,
|
[TEST_ETH_SYMBOL]: TEST_ETH_TOKEN_IMAGE_URL,
|
||||||
[BNB_SYMBOL]: BNB_TOKEN_IMAGE_URL,
|
[BNB_SYMBOL]: BNB_TOKEN_IMAGE_URL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const INFURA_BLOCKED_KEY = 'countryBlocked';
|
||||||
|
@ -34,6 +34,8 @@ const LEARN_MORE_URL =
|
|||||||
'https://metamask.zendesk.com/hc/en-us/articles/360045129011-Intro-to-MetaMask-v8-extension';
|
'https://metamask.zendesk.com/hc/en-us/articles/360045129011-Intro-to-MetaMask-v8-extension';
|
||||||
const LEGACY_WEB3_URL =
|
const LEGACY_WEB3_URL =
|
||||||
'https://metamask.zendesk.com/hc/en-us/articles/360053147012';
|
'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 {
|
export default class Home extends PureComponent {
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
@ -74,10 +76,12 @@ export default class Home extends PureComponent {
|
|||||||
originOfCurrentTab: PropTypes.string,
|
originOfCurrentTab: PropTypes.string,
|
||||||
disableWeb3ShimUsageAlert: PropTypes.func.isRequired,
|
disableWeb3ShimUsageAlert: PropTypes.func.isRequired,
|
||||||
pendingConfirmations: PropTypes.arrayOf(PropTypes.object).isRequired,
|
pendingConfirmations: PropTypes.arrayOf(PropTypes.object).isRequired,
|
||||||
|
infuraBlocked: PropTypes.bool.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
state = {
|
state = {
|
||||||
mounted: false,
|
mounted: false,
|
||||||
|
canShowBlockageNotification: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@ -176,6 +180,7 @@ export default class Home extends PureComponent {
|
|||||||
setWeb3ShimUsageAlertDismissed,
|
setWeb3ShimUsageAlertDismissed,
|
||||||
originOfCurrentTab,
|
originOfCurrentTab,
|
||||||
disableWeb3ShimUsageAlert,
|
disableWeb3ShimUsageAlert,
|
||||||
|
infuraBlocked,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -241,6 +246,28 @@ export default class Home extends PureComponent {
|
|||||||
key="home-privacyModeDefault"
|
key="home-privacyModeDefault"
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
{infuraBlocked && this.state.canShowBlockageNotification ? (
|
||||||
|
<HomeNotification
|
||||||
|
descriptionText={t('infuraBlockedNotification', [
|
||||||
|
<span
|
||||||
|
key="infuraBlockedNotificationLink"
|
||||||
|
className="home-notification__text-link"
|
||||||
|
onClick={() =>
|
||||||
|
global.platform.openTab({ url: INFURA_BLOCKAGE_URL })
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t('here')}
|
||||||
|
</span>,
|
||||||
|
])}
|
||||||
|
ignoreText={t('dismiss')}
|
||||||
|
onIgnore={() => {
|
||||||
|
this.setState({
|
||||||
|
canShowBlockageNotification: false,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
key="home-infuraBlockedNotification"
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
</MultipleNotifications>
|
</MultipleNotifications>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
getUnapprovedTemplatedConfirmations,
|
getUnapprovedTemplatedConfirmations,
|
||||||
getWeb3ShimUsageStateForOrigin,
|
getWeb3ShimUsageStateForOrigin,
|
||||||
unconfirmedTransactionsCountSelector,
|
unconfirmedTransactionsCountSelector,
|
||||||
|
getInfuraBlocked,
|
||||||
} from '../../selectors';
|
} from '../../selectors';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -104,6 +105,7 @@ const mapStateToProps = (state) => {
|
|||||||
originOfCurrentTab,
|
originOfCurrentTab,
|
||||||
shouldShowWeb3ShimUsageNotification,
|
shouldShowWeb3ShimUsageNotification,
|
||||||
pendingConfirmations,
|
pendingConfirmations,
|
||||||
|
infuraBlocked: getInfuraBlocked(state),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -417,6 +417,10 @@ export function getIpfsGateway(state) {
|
|||||||
return state.metamask.ipfsGateway;
|
return state.metamask.ipfsGateway;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getInfuraBlocked(state) {
|
||||||
|
return Boolean(state.metamask.infuraBlocked);
|
||||||
|
}
|
||||||
|
|
||||||
export function getUSDConversionRate(state) {
|
export function getUSDConversionRate(state) {
|
||||||
return state.metamask.usdConversionRate;
|
return state.metamask.usdConversionRate;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user