Skip to content

Commit

Permalink
fix: eip 6963 detection on wallet-ui
Browse files Browse the repository at this point in the history
  • Loading branch information
khanti42 committed Jul 10, 2024
1 parent fcb83e1 commit a15f6ab
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 81 deletions.
1 change: 0 additions & 1 deletion packages/wallet-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
"@fortawesome/free-solid-svg-icons": "^6.1.1",
"@fortawesome/react-fontawesome": "^0.1.18",
"@headlessui/react": "^1.6.4",
"@metamask/detect-provider": "^1.2.0",
"@metamask/jazzicon": "github:metamask/jazzicon#d923914fda6a8795f74c2e66134f73cd72070667",
"@mui/icons-material": "^5.6.2",
"@mui/material": "^5.6.2",
Expand Down
122 changes: 81 additions & 41 deletions packages/wallet-ui/src/hooks/useHasMetamask.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,96 @@
import detectEthereumProvider from '@metamask/detect-provider';
import { useEffect, useState } from 'react';
import { useAppDispatch } from 'hooks/redux';
import { setProvider } from 'slices/walletSlice';
import { enableLoadingWithMessage, disableLoading } from 'slices/UISlice';

interface MetaMaskProvider {
isMetaMask: boolean;
request(options: { method: string }): Promise<void>;
}

declare global {
interface Window {
ethereum?: MetaMaskProvider;
}
}

function isMetaMaskProvider(obj: unknown): obj is MetaMaskProvider {
return obj !== null && typeof obj === 'object' && obj.hasOwnProperty('isMetaMask') && obj.hasOwnProperty('request');
}

function detectMetaMaskProvider(
windowObject: Window & typeof globalThis,
{ timeout = 3000 } = {},
): Promise<MetaMaskProvider | null> {
let handled = false;
return new Promise<MetaMaskProvider | null>((resolve) => {
const handleEIP6963Provider = (event: CustomEvent) => {
const { info, provider } = event.detail;
if (['io.metamask', 'io.metamask.flask'].includes(info.rdns) && isMetaMaskProvider(provider)) {
resolve(provider);
handled = true;
}
};

if (typeof windowObject.addEventListener === 'function') {
windowObject.addEventListener('eip6963:announceProvider', (event: Event) => {
handleEIP6963Provider(event as CustomEvent);
});
}

setTimeout(() => {
if (!handled) {
resolve(null);
}
}, timeout);

// Notify event listeners and other parts of the dapp that a provider is requested.
if (typeof windowObject.dispatchEvent === 'function') {
windowObject.dispatchEvent(new Event('eip6963:requestProvider'));
}
});
}

async function waitForMetaMaskProvider(
windowObject: Window & typeof globalThis,
{ timeout = 1000, retries = 0 } = {},
): Promise<MetaMaskProvider | null> {
return detectMetaMaskProvider(windowObject, { timeout })
.catch(function () {
return null;
})
.then(function (provider) {
if (provider || retries === 0) {
return provider;
}
return waitForMetaMaskProvider(windowObject, {
timeout,
retries: retries - 1,
});
});
}

async function detectMetamaskSupport(windowObject: Window & typeof globalThis) {
const provider = await waitForMetaMaskProvider(windowObject, { retries: 3 });
return provider;
}

export const useHasMetamask = () => {
const dispatch = useAppDispatch();
const [hasMetamask, setHasMetamask] = useState<boolean | null>(null);

useEffect(() => {
const init = async () => {
try {
dispatch(enableLoadingWithMessage('Detecting Metamask...'));
//make sure mm has installed
if (await detectMetamask()) {
//metamask SDK is not support when multiple wallet installed, and each wallet may injected window.ethereum, some may override isMetamask
const _provider = await getProvider();
dispatch(setProvider(_provider));
setHasMetamask(_provider != null);
const provider = await detectMetamaskSupport(window);
// Use the new detection method

if (provider && (await isSupportSnap(provider))) {
window.ethereum = provider;
dispatch(setProvider(provider));
setHasMetamask(provider != null);
return window.ethereum;
} else {
dispatch(setProvider(null));
setHasMetamask(false);
Expand All @@ -36,40 +110,6 @@ export const useHasMetamask = () => {
};
};

export const detectMetamask = async () => {
try {
const hasMetamask = await detectEthereumProvider({ mustBeMetaMask: true });
if (hasMetamask) {
return true;
}
return false;
} catch (e) {
console.log('Error', e);
return false;
}
};

export const getProvider = async () => {
let { ethereum } = window as any;
let providers = [ethereum];

//ethereum.detected or ethereum.providers may exist when more than 1 wallet installed
if ('detected' in ethereum) {
providers = ethereum['detected'];
} else if ('providers' in ethereum) {
providers = ethereum['providers'];
}

//delect provider by sending request
for (const provider of providers) {
if (provider && (await isSupportSnap(provider))) {
window.ethereum = provider;
return window.ethereum;
}
}
return null;
};

const isSupportSnap = async (provider: any) => {
try {
await provider.request({
Expand Down
39 changes: 0 additions & 39 deletions packages/wallet-ui/src/hooks/useHasMetamaskFlask.ts

This file was deleted.

0 comments on commit a15f6ab

Please sign in to comment.