Files
explore/lib/web3/useDetectWalletEip6963.ts
T
0c5a297834 "Add chain" button in the header (#3084)
* redesign "add chain" button

* fix wallet detection

* [skip ci] update default value for ENV

* fix tests

* return button to the footer and add source to mixpanel event

* regcred from helmfile for review

* [skip ci] remove wallets env from values for demo stand

* use react-query to cache detection result

* add cookie to hide button in the topbar

* add prefix to svg ids to fix rabby icon

* update screenshot

* remove unnecessary comment

---------

Co-authored-by: Nick Zenchik <[email protected]>
2025-11-17 18:15:21 +01:00

72 lines
2.1 KiB
TypeScript

// https://eips.ethereum.org/EIPS/eip-6963
import React from 'react';
import type { WalletType } from 'types/client/wallets';
import type { WalletProvider } from 'types/web3';
interface EIP6963ProviderInfo {
uuid: string;
name: string;
icon: string;
rdns: string;
}
interface EIP6963ProviderDetail {
info: EIP6963ProviderInfo;
provider: WalletProvider;
}
const WALLET_RDNS_MAP: Record<WalletType, string> = {
metamask: 'io.metamask',
coinbase: 'com.coinbase.wallet',
token_pocket: 'io.tokenpocket',
rabby: 'io.rabby',
okx: 'com.okex.wallet',
trust: 'com.trustwallet.app',
} as const;
const DETECTED_PROVIDERS: Partial<Record<WalletType, WalletProvider | false>> = {};
export default function useDetectWalletEip6963() {
const detectionTimeoutRef = React.useRef<number | null>(null);
const handleAnnounceProviderEvent = React.useCallback((event: CustomEvent<EIP6963ProviderDetail>) => {
const wallet = Object.entries(WALLET_RDNS_MAP)
.find(([ , rdns ]) => rdns === event.detail.info.rdns)?.[0] as WalletType | undefined;
if (wallet && !DETECTED_PROVIDERS[wallet]) {
DETECTED_PROVIDERS[wallet] = event.detail.provider;
}
}, []);
const detect = React.useCallback((wallet: WalletType) => {
return new Promise<{ wallet: WalletType; provider: WalletProvider } | undefined>((resolve) => {
const provider = DETECTED_PROVIDERS[wallet];
if (provider) {
resolve({ wallet, provider });
return;
}
window.addEventListener('eip6963:announceProvider', handleAnnounceProviderEvent as EventListener);
window.dispatchEvent(new Event('eip6963:requestProvider'));
detectionTimeoutRef.current = window.setTimeout(() => {
const provider = DETECTED_PROVIDERS[wallet];
resolve(provider ? { wallet, provider } : undefined);
}, 200);
});
}, [ handleAnnounceProviderEvent ]);
React.useEffect(() => {
return () => {
window.removeEventListener('eip6963:announceProvider', handleAnnounceProviderEvent as EventListener);
};
}, [ handleAnnounceProviderEvent ]);
return React.useMemo(() => ({
detect,
}), [ detect ]);
}