From f7790b4ca6eb32775aa0446284fa3da07197004f Mon Sep 17 00:00:00 2001 From: Adrian Weniger Date: Fri, 11 Nov 2022 10:36:20 +0100 Subject: [PATCH] feat: allow for alternative wallet injections (#34) * fix: wallet popup on page open * refactor: rename walletconnct connector * feat: allow alternative injections * refactor: rename * fix: merge * fix: import error: remove logs --- .../src/LiFiWalletManagement.ts | 74 +++++-- .../src/connectors/eip1193.ts | 85 +++++--- .../src/connectors/metaMask.ts | 7 + .../src/connectors/tallyho.ts | 203 ++++++++++++++++++ .../src/connectors/walletConnect.ts | 20 +- ...connectorHooks.ts => priorityConnector.ts} | 17 +- .../wallet-management/src/walletAutomation.ts | 59 ++--- .../wallet-management/src/walletProviders.ts | 201 ++++++++--------- 8 files changed, 478 insertions(+), 188 deletions(-) create mode 100644 packages/wallet-management/src/connectors/tallyho.ts rename packages/wallet-management/src/{connectorHooks.ts => priorityConnector.ts} (60%) diff --git a/packages/wallet-management/src/LiFiWalletManagement.ts b/packages/wallet-management/src/LiFiWalletManagement.ts index 1cb69d98c..dc94a0c7a 100644 --- a/packages/wallet-management/src/LiFiWalletManagement.ts +++ b/packages/wallet-management/src/LiFiWalletManagement.ts @@ -1,6 +1,11 @@ +import type { ExternalProvider, Web3Provider } from '@ethersproject/providers'; +import { ethers } from 'ethers'; +import type { Connector } from '@web3-react/types'; import type { Signer } from 'ethers'; import { useCallback, useEffect, useState } from 'react'; -import { usePriorityConnector, usePriorityProvider } from './connectorHooks'; +import { getSelectedConnector } from '@web3-react/core'; +import { usePriorityConnector, usePriorityProvider } from './priorityConnector'; +// import { usePriorityConnector, usePriorityProvider } from './connectorHooks'; import { addToActiveWallets, addToDeactivatedWallets, @@ -14,14 +19,39 @@ export const useLiFiWalletManagement = () => { const priorityConnector = usePriorityConnector(); // "any" because of https://github.com/ethers-io/ethers.js/issues/866 const priorityProvider = usePriorityProvider('any'); + const [currentProvider, setCurrentProvider] = useState(); + const [currentConnector, setCurrentConnector] = useState(); const [signer, setSigner] = useState(); + const flushCurrentWalletData = () => { + console.log('flushing wallet data'); + + setCurrentConnector(() => undefined); + setCurrentProvider(() => undefined); + setSigner(() => undefined); + }; + + // eslint-disable-next-line react-hooks/exhaustive-deps + const calcWalletData = (connector?: Connector) => { + if (connector) { + const provider = new ethers.providers.Web3Provider( + connector.provider as ExternalProvider, + ); + setCurrentProvider(() => provider); + setCurrentConnector(() => connector); + setSigner(() => provider?.getSigner?.()); + } + }; + const connect = useCallback( async (wallet?: Wallet) => { const selectedAddress = (window as any)?.ethereum?.selectedAddress; + try { if (wallet) { - await wallet.connector.activate(); + const { connector } = wallet.web3react; + await connector.activate(); + calcWalletData(connector); } else { await priorityConnector.activate(); } @@ -31,7 +61,7 @@ export const useLiFiWalletManagement = () => { removeFromDeactivatedWallets(selectedAddress); addToActiveWallets(selectedAddress); }, - [priorityConnector], + [calcWalletData, priorityConnector], ); const disconnect = useCallback( @@ -40,52 +70,56 @@ export const useLiFiWalletManagement = () => { removeFromActiveWallets(selectedAddress); addToDeactivatedWallets(selectedAddress); if (wallet) { - await wallet.connector.deactivate?.(); + await currentConnector?.deactivate?.(); + flushCurrentWalletData(); } else if (priorityConnector.deactivate) { await priorityConnector.deactivate?.(); + flushCurrentWalletData(); } else { await priorityConnector.resetState(); - setSigner(undefined); + flushCurrentWalletData(); } }, - [priorityConnector], + [priorityConnector, currentConnector], ); - useEffect(() => { - setSigner(priorityProvider?.getSigner()); - }, [priorityProvider]); - + // eager connect useEffect(() => { const selectedAddress = (window as any).ethereum?.selectedAddress; - if (!isWalletDeactivated(selectedAddress)) { + if (!isWalletDeactivated(selectedAddress) && priorityConnector) { priorityConnector?.connectEagerly!(); } - }, [priorityConnector?.connectEagerly]); + }, [priorityConnector]); + // injected wallet listeners useEffect(() => { const { ethereum } = window as any; - const handleConnect = async () => { - await priorityConnector.activate(); - }; const handleChainChanged = async (chainId: string | number) => { - await priorityConnector.activate(); + await currentConnector?.activate(); + calcWalletData(currentConnector); + }; + const handleAccountsChanged = async (accounts: string[]) => { + if (!accounts.length) { + await currentConnector?.deactivate?.(); + flushCurrentWalletData(); + } }; - ethereum?.on('connect', handleConnect); ethereum?.on('chainChanged', handleChainChanged); + ethereum?.on('accountsChanged', handleAccountsChanged); return () => { if (ethereum?.removeListener) { - ethereum.removeListener('connect', handleConnect); ethereum.removeListener('chainChanged', handleChainChanged); + ethereum.removeListener('accountsChanged', handleAccountsChanged); } }; - }, [priorityConnector]); + }, [currentConnector]); return { connect, disconnect, signer, - provider: priorityProvider, + provider: currentProvider ?? priorityProvider, }; }; diff --git a/packages/wallet-management/src/connectors/eip1193.ts b/packages/wallet-management/src/connectors/eip1193.ts index 44d805b1f..cdacd63f6 100644 --- a/packages/wallet-management/src/connectors/eip1193.ts +++ b/packages/wallet-management/src/connectors/eip1193.ts @@ -1,40 +1,69 @@ +// eslint-disable-next-line max-classes-per-file import { Eip1193Bridge } from '@ethersproject/experimental'; import { initializeConnector } from '@web3-react/core'; -import { EIP1193 } from '@web3-react/eip1193'; +import { EIP1193, EIP1193ConstructorArgs } from '@web3-react/eip1193'; import type { Empty } from '@web3-react/empty'; import { EMPTY } from '@web3-react/empty'; +import { ProviderConnectInfo, ProviderRpcError } from '@web3-react/types'; import { providers } from 'ethers'; class Eip1193BridgeWithoutAccounts extends Eip1193Bridge { // eslint-disable-next-line @typescript-eslint/no-explicit-any request(request: { method: string; params?: any[] }): Promise { - if ( - request.method === 'eth_requestAccounts' || - request.method === 'eth_accounts' - ) { - return Promise.resolve([]); - } return super.request(request); } } -const { ethereum } = window as any; -const currentProvider = ethereum ? new providers.Web3Provider(ethereum) : null; - -const eip1193Provider = currentProvider - ? new Eip1193BridgeWithoutAccounts( - currentProvider?.getSigner(), - currentProvider, - ) - : null; - -export const [eip1193, hooks, store] = initializeConnector( - (actions) => - eip1193Provider - ? new EIP1193({ - actions, - provider: eip1193Provider, - onError: (error) => console.warn(error), - }) - : EMPTY, - // supportedChains.map((chain) => chain.id), -); +class EIP1193Listener extends EIP1193 { + constructor({ actions, provider, onError }: EIP1193ConstructorArgs) { + super({ actions, provider, onError }); + + this.provider = provider; + + this.provider.on('connect', ({ chainId }: ProviderConnectInfo): void => { + console.log('connect:', chainId); + }); + + this.provider.on('disconnect', (error: ProviderRpcError): void => { + this.actions.resetState(); + this.onError?.(error); + }); + + this.provider.on('chainChanged', (chainId: string): void => { + console.log(chainId); + }); + + this.provider.on('accountsChanged', (accounts: string[]): void => { + console.log('eip1193 accounts', accounts); + }); + } +} + +export const createEip1193Connector = () => { + const { ethereum } = window as any; + const currentProvider = ethereum + ? new providers.Web3Provider(ethereum) + : null; + + const eip1193Provider = new Eip1193BridgeWithoutAccounts( + currentProvider!.getSigner(), + currentProvider!, + ); + const [eip1193, hooks] = initializeConnector( + (actions) => + eip1193Provider + ? new EIP1193({ + actions, + provider: eip1193Provider, + onError: (error) => console.warn(error), + }) + : EMPTY, + // supportedChains.map((chain) => chain.id), + ); + + console.log('eip1193:', eip1193); + + return { + connector: eip1193, + hooks, + }; +}; diff --git a/packages/wallet-management/src/connectors/metaMask.ts b/packages/wallet-management/src/connectors/metaMask.ts index bce6e9e35..e6a95972f 100644 --- a/packages/wallet-management/src/connectors/metaMask.ts +++ b/packages/wallet-management/src/connectors/metaMask.ts @@ -5,6 +5,13 @@ export const [metaMask, hooks] = initializeConnector( (actions) => new MetaMask({ actions }), ); +export const createMetamaskConnector = () => { + const [connector, hooks] = initializeConnector( + (actions) => new MetaMask({ actions }), + ); + return { connector, hooks }; +}; + /* Known issues: issue: metamask uninitialized diff --git a/packages/wallet-management/src/connectors/tallyho.ts b/packages/wallet-management/src/connectors/tallyho.ts new file mode 100644 index 000000000..49b8bb518 --- /dev/null +++ b/packages/wallet-management/src/connectors/tallyho.ts @@ -0,0 +1,203 @@ +/* eslint-disable consistent-return */ +/* eslint-disable prefer-promise-reject-errors */ +/* eslint-disable no-void */ +import { initializeConnector } from '@web3-react/core'; +import type { + Actions, + Provider, + ProviderConnectInfo, + ProviderRpcError, +} from '@web3-react/types'; +import { Connector } from '@web3-react/types'; + +declare global { + interface Window { + tally?: TallyHoProvider; + } +} + +export interface TallyHoProvider extends Provider { + isTally: boolean; +} +export interface ConnectEagerlyConfig { + retries: number; + timeoutMs: number; +} + +function isTally(provider: unknown): provider is TallyHoProvider { + return ( + typeof provider === 'object' && + provider !== null && + 'request' in provider && + 'isTally' in provider && + (provider as TallyHoProvider).isTally === true + ); +} + +function isConnectEagerlyConfig(arg: unknown): arg is ConnectEagerlyConfig { + return ( + typeof arg === 'object' && + typeof (arg as ConnectEagerlyConfig).retries === 'number' && + typeof (arg as ConnectEagerlyConfig).timeoutMs === 'number' + ); +} + +function parseChainId(chainId: string) { + return Number.parseInt(chainId, 16); +} + +export class TallyHo extends Connector { + /** {@inheritdoc Connector.provider} */ + provider: Provider | undefined; + + public isCurrentlyUsed: boolean = false; + + /** + * This parameter is used to make sure only one initialization is in progress at a time. + * E.g.: When `connectEagerly` constructor parameter set to true and the `tallyHo.connectEagerly()` + * method is used in an useEffect then it results in 2 requests. + */ + isActivationInProgress = false; + + /** + * @param connectEagerly - A flag indicating whether connection should be initiated when the class is constructed. + */ + constructor( + actions: Actions, + connectEagerly?: boolean | ConnectEagerlyConfig, + ) { + super(actions); + + if (connectEagerly) { + if (connectEagerly === true) { + void this.connectEagerly(); + } else if (isConnectEagerlyConfig(connectEagerly)) { + void this.connectEagerly(connectEagerly); + } else { + throw new Error( + `connectEagerly is expected to be 'true' OR {retries: number, timeoutMs: number}, but ${JSON.stringify( + connectEagerly, + )} was received instead.`, + ); + } + } + } + + /** {@inheritdoc Connector.connectEagerly} */ + public async connectEagerly( + config: ConnectEagerlyConfig = { retries: 5, timeoutMs: 500 }, + ): Promise { + return new Promise((resolve, reject) => { + let counter = 0; + + /** + * When `connectEagerly` is set to true at class initialization time there is no window present. + * But it is usually ready in 1-2 seconds, so we shall wait for it. + */ + function waitForWindow() { + if (typeof window === 'undefined') { + counter++; + + if (counter === config.retries) { + reject( + `window was not present after ${config.retries} retries (with ${config.timeoutMs}ms wait period). Try using the connectEagerly method in a useEffect`, + ); + } + + setTimeout(waitForWindow, config.timeoutMs); + } else { + resolve(); + } + } + + waitForWindow(); + }).then(() => this.activate()); + } + + /** {@inheritdoc Connector.activate} */ + public async activate(): Promise { + if (window === undefined) { + throw new Error( + "window is not defined. This should not have happened. 'Toto, I have a feeling we're not in Kansas anymore! 🌪'", + ); + } + + if (!this.provider) { + this.initializeProvider(); + } + + if (this.isActivationInProgress) return; + + this.isActivationInProgress = true; + + if (isTally(this.provider)) { + const cancelActivation = this.actions.startActivation(); + this.isCurrentlyUsed = true; + + return this.provider + .request({ method: 'eth_requestAccounts' }) + .then((accounts) => + Promise.all([ + this.provider?.request({ + method: 'eth_chainId', + }) as Promise, + accounts as string[], + ]).then(([chainId, accounts]) => { + this.actions.update({ chainId: parseChainId(chainId), accounts }); + }), + ) + .catch((error: Error) => { + this.actions.resetState(); + cancelActivation(); + }) + .finally(() => { + this.isActivationInProgress = false; + }); + } + } + + private initializeProvider() { + if (!isTally(window.tally)) { + throw new Error( + "You don't seem to have TallyHo installed because window.tally is not a TallyHo provider.", + ); + } + this.provider = window.tally; + + this.provider.on('connect', ({ chainId }: ProviderConnectInfo): void => { + this.actions.update({ chainId: parseChainId(chainId) }); + }); + + this.provider.on('disconnect', (error: ProviderRpcError): void => { + this.actions.update({ accounts: [], chainId: undefined }); + this.actions.resetState(); + }); + + this.provider.on('chainChanged', (chainId: string): void => { + this.actions.update({ chainId: parseChainId(chainId) }); + }); + + this.provider.on('accountsChanged', (accounts: string[]): void => { + if (!accounts.length) { + this.actions.update({ accounts: [], chainId: undefined }); + this.actions.resetState(); + } + this.actions.update({ accounts }); + }); + } + + public deactivate(): void | Promise { + if (this.provider) { + this.provider = undefined; + this.isCurrentlyUsed = false; + this.actions.resetState(); + } + } +} + +export const createTallyHoConnector = () => { + const [tallyHo, hooks] = initializeConnector( + (actions) => new TallyHo(actions, false), + ); + return { connector: tallyHo, hooks }; +}; diff --git a/packages/wallet-management/src/connectors/walletConnect.ts b/packages/wallet-management/src/connectors/walletConnect.ts index 3c948e718..4cfac8c93 100644 --- a/packages/wallet-management/src/connectors/walletConnect.ts +++ b/packages/wallet-management/src/connectors/walletConnect.ts @@ -15,7 +15,7 @@ interface MockWalletConnectProvider extends Omit, EventEmitter {} -class WalletConnectV2 extends Connector { +export class WalletConnect extends Connector { private readonly options?: WalletConnectOptions; public provider: MockWalletConnectProvider; @@ -78,9 +78,9 @@ class WalletConnectV2 extends Connector { } } -export const [walletConnect, hooks] = initializeConnector( +export const [walletConnect, hooks] = initializeConnector( (actions) => - new WalletConnectV2(actions, { + new WalletConnect(actions, { rpc: Object.fromEntries( supportedChains.map((chain) => { return [chain.id, chain.metamask.rpcUrls[0] || '']; @@ -88,3 +88,17 @@ export const [walletConnect, hooks] = initializeConnector( ), }), ); + +export const createWalletConnectConnector = () => { + const [connector, hooks] = initializeConnector( + (actions) => + new WalletConnect(actions, { + rpc: Object.fromEntries( + supportedChains.map((chain) => { + return [chain.id, chain.metamask.rpcUrls[0] || '']; + }), + ), + }), + ); + return { connector, hooks }; +}; diff --git a/packages/wallet-management/src/connectorHooks.ts b/packages/wallet-management/src/priorityConnector.ts similarity index 60% rename from packages/wallet-management/src/connectorHooks.ts rename to packages/wallet-management/src/priorityConnector.ts index 049faa41f..e3ba48a25 100644 --- a/packages/wallet-management/src/connectorHooks.ts +++ b/packages/wallet-management/src/priorityConnector.ts @@ -1,11 +1,10 @@ import { getPriorityConnector } from '@web3-react/core'; -import { eip1193, hooks as eip1193Hooks } from './connectors/eip1193'; -import { hooks as metaMaskHooks, metaMask } from './connectors/metaMask'; -import { - hooks as walletConnectHooks, - walletConnect, -} from './connectors/walletConnect'; +import { supportedWallets } from './walletProviders'; +// import { eip1193, hooks as eip1193Hooks } from './connectors/eip1193'; +const metamaskWallet = supportedWallets.find( + (wallet) => wallet.name === 'MetaMask', +); export const { useSelectedStore, useSelectedChainId, @@ -27,9 +26,9 @@ export const { usePriorityENSNames, usePriorityENSName, } = getPriorityConnector( - [metaMask, metaMaskHooks], // needs to be on top! - [eip1193, eip1193Hooks], - [walletConnect, walletConnectHooks], + [metamaskWallet!.web3react.connector, metamaskWallet!.web3react.hooks], // needs to be on top! + // [eip1193, eip1193Hooks], + // [walletConnect, walletConnectHooks], // [walletLink, walletLinkHooks], // [network, networkHooks], ); diff --git a/packages/wallet-management/src/walletAutomation.ts b/packages/wallet-management/src/walletAutomation.ts index f0d7c013b..3eb45c47a 100644 --- a/packages/wallet-management/src/walletAutomation.ts +++ b/packages/wallet-management/src/walletAutomation.ts @@ -1,3 +1,4 @@ +import { supportedWallets } from '@lifi/wallet-management'; /* eslint-disable radix */ import type { Token } from '@lifi/sdk'; import { @@ -5,17 +6,32 @@ import { MetaMaskProviderErrorCode, prefixChainId, } from '@lifi/sdk'; -import { walletConnect } from './connectors/walletConnect'; +import type { WalletConnect } from './connectors/walletConnect'; +import type { TallyHo } from './connectors/tallyho'; + +const getAppropriateProvider = () => { + const walletConnect = supportedWallets.find( + (wallet) => wallet.name === 'Wallet Connect', + ); + const tallyho = supportedWallets.find((wallet) => wallet.name === 'Tally Ho'); + + let provider: any; + if ((walletConnect?.web3react.connector as WalletConnect).isCurrentlyUsed) { + provider = (walletConnect?.web3react.connector as WalletConnect) + .walletConnectProvider; + } else if ((tallyho?.web3react.connector as TallyHo).isCurrentlyUsed) { + const { tally } = window as any; + provider = tally; + } else { + const { ethereum } = window as any; + provider = ethereum; + } + return provider; +}; export const switchChain = async (chainId: number): Promise => { return new Promise((resolve, reject) => { - let provider: any; - if (walletConnect.isCurrentlyUsed) { - provider = walletConnect.walletConnectProvider; - } else { - const { ethereum } = window as any; - provider = ethereum; - } + const provider: any = getAppropriateProvider(); if (!provider) { resolve(false); } @@ -50,13 +66,8 @@ export const switchChain = async (chainId: number): Promise => { }; export const addChain = async (chainId: number) => { - let provider: any; - if (walletConnect.isCurrentlyUsed) { - provider = walletConnect.walletConnectProvider; - } else { - const { ethereum } = window as any; - provider = ethereum; - } + const provider: any = getAppropriateProvider(); + if (!provider) { return false; } @@ -75,13 +86,8 @@ export const addChain = async (chainId: number) => { }; export const addToken = async (token: Token) => { - let provider: any; - if (walletConnect.isCurrentlyUsed) { - provider = walletConnect.walletConnectProvider; - } else { - const { ethereum } = window as any; - provider = ethereum; - } + const provider: any = getAppropriateProvider(); + if (!provider) { return false; } @@ -107,13 +113,8 @@ export const addToken = async (token: Token) => { }; export const switchChainAndAddToken = async (chainId: number, token: Token) => { - let provider: any; - if (walletConnect.isCurrentlyUsed) { - provider = walletConnect.walletConnectProvider; - } else { - const { ethereum } = window as any; - provider = ethereum; - } + const provider: any = getAppropriateProvider(); + if (!provider) { return; } diff --git a/packages/wallet-management/src/walletProviders.ts b/packages/wallet-management/src/walletProviders.ts index 8c61fc0c2..94e402a87 100644 --- a/packages/wallet-management/src/walletProviders.ts +++ b/packages/wallet-management/src/walletProviders.ts @@ -1,20 +1,25 @@ import type { Connector } from '@web3-react/types'; -import { metaMask } from './connectors/metaMask'; -import { wallets } from './wallets'; -import { walletConnect as walletConnectConnector } from './connectors/walletConnect'; +import type { Web3ReactHooks } from '@web3-react/core'; +import { createMetamaskConnector } from './connectors/metaMask'; +import { createWalletConnectConnector } from './connectors/walletConnect'; +import { createTallyHoConnector } from './connectors/tallyho'; +import { walletIcons } from './walletIcons'; export interface Wallet { name: string; icon: string; - connector: Connector; checkProviderIdentity: (helpers: { provider: any; // device: Device; }) => boolean; + web3react: { + connector: Connector; + hooks: Web3ReactHooks; + }; platforms: string[]; } -enum ProviderIdentityFlag { +export enum ProviderIdentityFlag { AlphaWallet = 'isAlphaWallet', AToken = 'isAToken', BlockWallet = 'isBlockWallet', @@ -40,295 +45,292 @@ enum ProviderIdentityFlag { TokenPocket = 'isTokenPocket', TP = 'isTp', WalletIo = 'isWalletIO', - XDEFI = 'isXDEFI', + XDEFI = '__XDEFI', OneInch = 'isOneInchIOSWallet', Tokenary = 'isTokenary', MathWallet = 'isMathWallet', } const metamask: Wallet = { - name: wallets.metamask.name, + name: 'MetaMask', checkProviderIdentity: ({ provider }) => // Removed for now to allow all kinds of injected wallets to connect using the metamask button as fallback // !!provider && !!provider[ProviderIdentityFlag.MetaMask], true, - icon: wallets.metamask.icon, - connector: metaMask, + icon: walletIcons.metamask, platforms: ['all'], + web3react: createMetamaskConnector(), }; const walletConnect: Wallet = { - name: wallets.walletConnect.name, + name: 'Wallet Connect', checkProviderIdentity: ({ provider }) => true, - icon: wallets.walletConnect.icon, - connector: walletConnectConnector, + icon: walletIcons.walletConnect, platforms: ['all'], + web3react: createWalletConnectConnector(), }; const brave: Wallet = { - name: wallets.brave.name, + name: 'Brave', checkProviderIdentity: ({ provider }) => // eslint-disable-next-line no-underscore-dangle (navigator as any).brave && provider?._web3Ref, - icon: wallets.brave.icon, - connector: metaMask, - + icon: walletIcons.brave, platforms: ['all'], + web3react: createMetamaskConnector(), }; const mathWallet: Wallet = { - name: wallets.mathwallet.name, + name: 'MathWallet', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.MathWallet], - icon: wallets.mathwallet.icon, - connector: metaMask, - + icon: walletIcons.mathwallet, platforms: ['all'], + web3react: createMetamaskConnector(), }; const tallyho: Wallet = { - name: wallets.tallyho.name, + name: 'Tally Ho', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.TallyHo], - icon: wallets.tallyho.icon, - connector: metaMask, + icon: walletIcons.tallyho, platforms: ['desktop'], + web3react: createTallyHoConnector(), }; const blockWallet: Wallet = { - name: wallets.blockwallet.name, + name: 'BlockWallet', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.BlockWallet], - icon: wallets.blockwallet.icon, - connector: metaMask, + icon: walletIcons.blockwallet, platforms: ['desktop'], + web3react: createMetamaskConnector(), }; const binance: Wallet = { - name: wallets.binance.name, + name: 'Binance', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.Binance], - icon: wallets.binance.icon, - connector: metaMask, + icon: walletIcons.binance, platforms: ['desktop'], + web3react: createMetamaskConnector(), }; const coinbase: Wallet = { - name: wallets.coinbase.name, + name: 'Coinbase', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.Coinbase] || provider?.providers?.[0]?.[ProviderIdentityFlag.CoinbaseExtension], - icon: wallets.coinbase.icon, - connector: metaMask, + icon: walletIcons.coinbase, platforms: ['all'], + web3react: createMetamaskConnector(), }; const detected: Wallet = { - name: wallets.detected.name, + name: 'Detected', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.Detected], - icon: wallets.detected.icon, - connector: metaMask, + icon: walletIcons.detected, platforms: ['all'], + web3react: createMetamaskConnector(), }; const trust: Wallet = { - name: wallets.trust.name, + name: 'Trust', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.Trust] && !provider[ProviderIdentityFlag.TokenPocket], - icon: wallets.trust.icon, - connector: metaMask, + icon: walletIcons.trust, platforms: ['mobile'], + web3react: createMetamaskConnector(), }; const status: Wallet = { - name: wallets.status.name, + name: 'Status', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.Status], - icon: wallets.status.icon, - connector: metaMask, + icon: walletIcons.status, platforms: ['mobile'], + web3react: createMetamaskConnector(), }; const alphawallet: Wallet = { - name: wallets.alphawallet.name, + name: 'AlphaWallet', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.AlphaWallet], - icon: wallets.alphawallet.icon, - connector: metaMask, + icon: walletIcons.alphawallet, platforms: ['mobile'], + web3react: createMetamaskConnector(), }; const atoken: Wallet = { - name: wallets.atoken.name, + name: 'AToken', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.AToken], - icon: wallets.atoken.icon, - connector: metaMask, + icon: walletIcons.atoken, platforms: ['mobile'], + web3react: createMetamaskConnector(), }; const bitpie: Wallet = { - name: wallets.bitpie.name, + name: 'Bitpie', checkProviderIdentity: () => (window as any).Bitpie, - icon: wallets.bitpie.icon, - connector: metaMask, + icon: walletIcons.bitpie, platforms: ['mobile'], + web3react: createMetamaskConnector(), }; const blankwallet: Wallet = { - name: wallets.blankwallet.name, + name: 'BlankWallet', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.BlankWallet], - icon: wallets.blankwallet.icon, - connector: metaMask, + icon: walletIcons.blankwallet, platforms: ['desktop'], + web3react: createMetamaskConnector(), }; const dcent: Wallet = { - name: wallets.dcent.name, + name: 'Dcent', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.Dcent], - icon: wallets.dcent.icon, - connector: metaMask, + icon: walletIcons.dcent, platforms: ['mobile'], + web3react: createMetamaskConnector(), }; const frame: Wallet = { - name: wallets.frame.name, + name: 'Frame', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.Frame], - icon: wallets.frame.icon, - connector: metaMask, + icon: walletIcons.frame, platforms: ['desktop'], + web3react: createMetamaskConnector(), }; const huobiwallet: Wallet = { - name: wallets.huobiwallet.name, + name: 'HuobiWallet', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.HuobiWallet], - icon: wallets.huobiwallet.icon, - connector: metaMask, + icon: walletIcons.huobiwallet, platforms: ['mobile'], + web3react: createMetamaskConnector(), }; const hyperpay: Wallet = { - name: wallets.hyperpay.name, + name: 'HyperPay', // Note: The property `hiWallet` is as of now the only known way of identifying hyperpay // wallet as it is a direct clone of metamask. `checkProviderIdentity` implementation is subject to // future changes checkProviderIdentity: () => (window as any).hiWallet, - icon: wallets.hyperpay.icon, - connector: metaMask, + icon: walletIcons.hyperpay, platforms: ['mobile'], + web3react: createMetamaskConnector(), }; const imtoken: Wallet = { - name: wallets.imtoken.name, + name: 'ImToken', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.ImToken], - icon: wallets.imtoken.icon, - connector: metaMask, + icon: walletIcons.imtoken, platforms: ['mobile'], + web3react: createMetamaskConnector(), }; const liquality: Wallet = { - name: wallets.liquality.name, + name: 'Liquality', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.Liquality], - icon: wallets.liquality.icon, - connector: metaMask, + icon: walletIcons.liquality, platforms: ['desktop'], + web3react: createMetamaskConnector(), }; const meetone: Wallet = { - name: wallets.meetone.name, + name: 'MeetOne', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.MeetOne] === 'MEETONE', - icon: wallets.meetone.icon, - connector: metaMask, + icon: walletIcons.meetone, platforms: ['mobile'], + web3react: createMetamaskConnector(), }; const mykey: Wallet = { - name: wallets.mykey.name, + name: 'MyKey', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.MyKey], - icon: wallets.mykey.icon, - connector: metaMask, + icon: walletIcons.mykey, platforms: ['mobile'], + web3react: createMetamaskConnector(), }; const ownbit: Wallet = { - name: wallets.ownbit.name, + name: 'OwnBit', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.OwnBit], - icon: wallets.ownbit.icon, - connector: metaMask, + icon: walletIcons.ownbit, platforms: ['mobile'], + web3react: createMetamaskConnector(), }; const tokenpocket: Wallet = { - name: wallets.tokenpocket.name, + name: 'TokenPocket', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.TokenPocket] && !provider[ProviderIdentityFlag.TP], - icon: wallets.tokenpocket.icon, - connector: metaMask, + icon: walletIcons.tokenpocket, platforms: ['all'], + web3react: createMetamaskConnector(), }; const tp: Wallet = { - name: wallets.tp.name, + name: 'TP', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.TP], - icon: wallets.tp.icon, - connector: metaMask, + icon: walletIcons.tp, platforms: ['mobile'], + web3react: createMetamaskConnector(), }; const xdefi: Wallet = { - name: wallets.xdefi.name, - checkProviderIdentity: ({ provider }) => - provider?.ethereum?.[ProviderIdentityFlag.XDEFI], - icon: wallets.xdefi.icon, - connector: metaMask, + name: 'XDEFI', + // eslint-disable-next-line dot-notation + checkProviderIdentity: ({ provider }) => true, + icon: walletIcons.xdefi, platforms: ['all'], + web3react: createMetamaskConnector(), }; const oneInch: Wallet = { - name: wallets.oneInch.name, + name: 'OneInch', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.OneInch], - icon: wallets.oneInch.icon, - connector: metaMask, + icon: walletIcons.oneInch, platforms: ['mobile'], + web3react: createMetamaskConnector(), }; const tokenary: Wallet = { - name: wallets.tokenary.name, + name: 'Tokenary', checkProviderIdentity: ({ provider }) => provider?.[ProviderIdentityFlag.Tokenary], - icon: wallets.tokenary.icon, - connector: metaMask, + icon: walletIcons.tokenary, platforms: ['mobile'], + web3react: createMetamaskConnector(), }; export const supportedWallets = [ metamask, walletConnect, + tallyho, binance, coinbase, detected, trust, status, alphawallet, - oneInch, - tallyho, atoken, blockWallet, bitpie, @@ -346,6 +348,7 @@ export const supportedWallets = [ tokenpocket, tp, xdefi, + oneInch, tokenary, mathWallet, ];