Skip to content

Commit

Permalink
Merge pull request #2191 from MyCryptoHQ/enhancement/new-metamask-stuff
Browse files Browse the repository at this point in the history
Enhancement/new metamask stuff
  • Loading branch information
ConnorBryan authored Oct 24, 2018
2 parents 12cfd6f + d8cbd0c commit cbfad18
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 15 deletions.
18 changes: 12 additions & 6 deletions common/components/WalletDecrypt/WalletDecrypt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ const WalletDecrypt = withRouter<Props>(
}

public handleWalletChoice = async (walletType: WalletName) => {
const { showNotification } = this.props;
const wallet = this.WALLETS[walletType];

if (!wallet) {
Expand All @@ -409,12 +410,17 @@ const WalletDecrypt = withRouter<Props>(

let timeout = 0;
if (wallet.attemptUnlock) {
const web3Available = await isWeb3NodeAvailable();
if (web3Available) {
// timeout is only the maximum wait time before secondary view is shown
// send view will be shown immediately on web3 resolve
timeout = 1500;
wallet.unlock();
try {
const web3Available = await isWeb3NodeAvailable();
if (web3Available) {
// timeout is only the maximum wait time before secondary view is shown
// send view will be shown immediately on web3 resolve
timeout = 1500;
wallet.unlock();
}
} catch (e) {
// The permissions request for MetaMask was displayed, but permission was denied.
showNotification('danger', translateRaw('METAMASK_PERMISSION_DENIED'));
}
}

Expand Down
23 changes: 22 additions & 1 deletion common/features/config/sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ import {
getShepherdManualMode
} from 'libs/nodes';
import { Web3Wallet } from 'libs/wallet';
import { setupWeb3Node, Web3Service, isWeb3Node } from 'libs/nodes/web3';
import {
setupWeb3Node,
Web3Service,
isWeb3Node,
ensureWeb3NodeStillAvailable
} from 'libs/nodes/web3';
import { AppState } from 'features/reducers';
import { notificationsActions } from 'features/notifications';
import { walletTypes, walletActions } from 'features/wallet';
Expand Down Expand Up @@ -344,6 +349,18 @@ export function* unlockWeb3(): SagaIterator {
}
const wallet = new Web3Wallet(address, stripWeb3Network(network));
yield put(walletActions.setWallet(wallet));

// Though unlikely, it is possible that a user revokes permission while logged in.
// The following will prompt them with another dialog.
if (!(window as any).ensuringWeb3Availability) {
(window as any).ensuringWeb3Availability = (window as any).setInterval(async () => {
const web3StillAvailable = await ensureWeb3NodeStillAvailable();

if (!web3StillAvailable) {
window.location.reload();
}
}, 500);
}
} catch (err) {
console.error(err);
// unset web3 node so node dropdown isn't disabled
Expand All @@ -366,6 +383,8 @@ export function* unsetWeb3NodeOnWalletEvent(action: walletTypes.SetWalletAction)

// forcefully switch back to a node with the same network as MetaMask/Mist
yield put(configNodesSelectedActions.changeNodeForce(prevNodeId));

clearInterval((window as any).ensuringWeb3Availability);
}

export function* unsetWeb3Node(): SagaIterator {
Expand All @@ -379,6 +398,8 @@ export function* unsetWeb3Node(): SagaIterator {

// forcefully switch back to a node with the same network as MetaMask/Mist
yield put(configNodesSelectedActions.changeNodeForce(prevNodeId));

clearInterval((window as any).ensuringWeb3Availability);
}
//#endregion Web3

Expand Down
68 changes: 61 additions & 7 deletions common/libs/nodes/web3/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { translateRaw } from 'translations';
import { IHexStrWeb3Transaction } from 'libs/transaction';
import { INode } from 'libs/nodes/INode';
import {
Expand All @@ -10,6 +11,8 @@ import RPCNode from '../rpc';
import Web3Client from './client';
import Web3Requests from './requests';

const METAMASK_PERMISSION_DENIED_ERROR = translateRaw('METAMASK_PERMISSION_DENIED');

export default class Web3Node extends RPCNode {
public client: Web3Client;
public requests: Web3Requests;
Expand Down Expand Up @@ -55,13 +58,7 @@ export function isWeb3Node(nodeLib: INode | Web3Node): nodeLib is Web3Node {

export const Web3Service = 'MetaMask / Mist';

export async function setupWeb3Node() {
const { web3 } = window as any;

if (!web3 || !web3.currentProvider || !web3.currentProvider.sendAsync) {
throw new Error('Web3 not found. Please check that MetaMask is installed');
}

export async function getChainIdAndLib() {
const lib = new Web3Node();
const chainId = await lib.getNetVersion();
const accounts = await lib.getAccounts();
Expand All @@ -77,9 +74,66 @@ export async function setupWeb3Node() {
return { chainId, lib };
}

export async function setupWeb3Node() {
// Handle the following MetaMask breaking change:
// https://medium.com/metamask/https-medium-com-metamask-breaking-change-injecting-web3-7722797916a8
const { ethereum } = window as any;

if (ethereum) {
// Overwrite the legacy Web3 with the newer version.
(window as any).web3 = new (window as any).Web3(ethereum);

try {
// Request permission to access MetaMask accounts.
await ethereum.enable();

// Permission was granted; proceed.
return getChainIdAndLib();
} catch (e) {
// Permission was denied; handle appropriately.
throw new Error(METAMASK_PERMISSION_DENIED_ERROR);
}
} else if ((window as any).web3) {
// Legacy handling; will become unavailable 11/2.
const { web3 } = window as any;

if (!web3 || !web3.currentProvider || !web3.currentProvider.sendAsync) {
throw new Error('Web3 not found. Please check that MetaMask is installed');
}

return getChainIdAndLib();
} else {
throw new Error('Web3 not found. Please check that MetaMask is installed');
}
}

export async function isWeb3NodeAvailable(): Promise<boolean> {
try {
await setupWeb3Node();
return true;
} catch (e) {
// If the specific error is that the request for MetaMask permission was denied,
// re-throw the error and allow the caller to handle it.
if (e.message === METAMASK_PERMISSION_DENIED_ERROR) {
throw e;
}

// Otherwise, chances are the MetaMask extension isn't installed.
return false;
}
}

export async function ensureWeb3NodeStillAvailable(): Promise<boolean> {
try {
const { ethereum } = window as any;

// Legacy handling; will become unavailable 11/2.
if (!ethereum) {
return true;
}

await ethereum.enable();

return true;
} catch (e) {
return false;
Expand Down
2 changes: 1 addition & 1 deletion common/translations/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,7 @@
"ONBOARDING_TEXT_27": "Get a Trezor",
"ONBOARDING_TEXT_28": "Get a Ledger",
"ONBOARDING_TEXT_29": "Need more info before you dive in? See [Support Center]($link)",
"METAMASK_PERMISSION_DENIED": "You denied the request for permission to access MetaMask, but permission is required to unlock your wallet. Please click \"Connect to MetaMask\", and then click \"Approve\" when the dialog opens.",
"NEW_FOOTER_TEXT_1": "Donate",
"NEW_FOOTER_TEXT_2": "Address Copied to Clipboard!",
"NEW_FOOTER_TEXT_3": "Subscribe to MyCrypto",
Expand Down Expand Up @@ -724,6 +725,5 @@
"NEW_SIDEBAR_TEXT_6": "Add custom node",
"NEW_SIDEBAR_TEXT_7": "Hide Other Networks",
"NEW_SIDEBAR_TEXT_8": "Show Other Networks"

}
}

0 comments on commit cbfad18

Please sign in to comment.