Commit 4eaf16b6 authored by cartcrom's avatar cartcrom Committed by GitHub

fix: injection detection bug (#6276)

* fix: use functions to check injection status rather than static vars

* fix: unnused field

* fix: don't prompt mm install for generics

* fix: generic injector function

* fix: display name for MM on cb browser

* fix: re-add ios mobile check for uniswap wallet

* fix: reword comment

* fix: refactor delayed-injection test

* feat: added comments

* fix: revert to minimal changes

* fix: update tests
parent 857e2915
......@@ -60,7 +60,7 @@ const Socks = () => {
const MiniWalletIcon = ({ connection, side }: { connection: Connection; side: 'left' | 'right' }) => {
return (
<MiniIconContainer side={side}>
<MiniImg src={connection.icon} alt={`${connection.name} icon`} />
<MiniImg src={connection.getIcon?.()} alt={`${connection.getName()} icon`} />
</MiniIconContainer>
)
}
......@@ -71,7 +71,7 @@ const MainWalletIcon = ({ connection, size }: { connection: Connection; size: nu
if (!account) {
return null
} else if (avatar || (connection.type === ConnectionType.INJECTED && connection.name === 'MetaMask')) {
} else if (avatar || (connection.type === ConnectionType.INJECTED && connection.getName() === 'MetaMask')) {
return <Identicon size={size} />
} else {
return <Unicon address={account} size={size} />
......
......@@ -72,7 +72,7 @@ export default function Option({ connection, pendingConnectionType, activate }:
<TraceEvent
events={[BrowserEvent.onClick]}
name={InterfaceEventName.WALLET_SELECTED}
properties={{ wallet_type: connection.name }}
properties={{ wallet_type: connection.getName() }}
element={InterfaceElementName.WALLET_TYPE_OPTION}
>
<OptionCardClickable
......@@ -83,9 +83,9 @@ export default function Option({ connection, pendingConnectionType, activate }:
>
<OptionCardLeft>
<IconWrapper>
<img src={connection.icon} alt="Icon" />
<img src={connection.getIcon?.()} alt="Icon" />
</IconWrapper>
<HeaderText>{connection.name}</HeaderText>
<HeaderText>{connection.getName()}</HeaderText>
{connection.isNew && <NewBadge />}
</OptionCardLeft>
{isPending && <Loader />}
......
......@@ -7,7 +7,7 @@ import { AutoColumn } from 'components/Column'
import { AutoRow } from 'components/Row'
import { useWalletDrawer } from 'components/WalletDropdown'
import IconButton from 'components/WalletDropdown/IconButton'
import { Connection, ConnectionType, networkConnection, useConnections } from 'connection'
import { Connection, ConnectionType, getConnections, networkConnection } from 'connection'
import { useGetConnection } from 'connection'
import { ErrorCode } from 'connection/utils'
import { isSupportedChain } from 'constants/chains'
......@@ -91,7 +91,7 @@ export default function WalletModal({ openSettings }: { openSettings: () => void
const [pendingConnection, setPendingConnection] = useState<Connection | undefined>()
const [pendingError, setPendingError] = useState<any>()
const connections = useConnections()
const connections = getConnections()
const getConnection = useGetConnection()
useEffect(() => {
......@@ -116,7 +116,7 @@ export default function WalletModal({ openSettings }: { openSettings: () => void
// When new wallet is successfully set by the user, trigger logging of Amplitude analytics event.
useEffect(() => {
if (account && account !== lastActiveWalletAddress) {
const walletName = getConnection(connector).name
const walletName = getConnection(connector).getName()
const peerWalletAgent = provider ? getWalletMeta(provider)?.agent : undefined
const isReconnect =
connectedWallets.filter((wallet) => wallet.account === account && wallet.walletType === walletName).length > 0
......@@ -141,6 +141,9 @@ export default function WalletModal({ openSettings }: { openSettings: () => void
const tryActivation = useCallback(
async (connection: Connection) => {
// Skips wallet connection if the connection should override the default behavior, i.e. install metamask or launch coinbase app
if (connection.overrideActivate?.()) return
// log selected wallet
sendEvent({
category: 'Wallet',
......@@ -165,7 +168,7 @@ export default function WalletModal({ openSettings }: { openSettings: () => void
sendAnalyticsEvent(InterfaceEventName.WALLET_CONNECT_TXN_COMPLETED, {
result: WalletConnectionResult.FAILED,
wallet_type: connection.name,
wallet_type: connection.getName(),
})
}
}
......@@ -190,11 +193,11 @@ export default function WalletModal({ openSettings }: { openSettings: () => void
<OptionGrid data-testid="option-grid">
{connections.map((connection) =>
// Hides Uniswap Wallet if mgtm is disabled
connection.shouldDisplay && !(connection.type === ConnectionType.UNIWALLET && !mgtmEnabled) ? (
connection.shouldDisplay() && !(connection.type === ConnectionType.UNIWALLET && !mgtmEnabled) ? (
<Option
key={connection.name}
key={connection.getName()}
connection={connection}
activate={connection.overrideActivate ?? (() => tryActivation(connection))}
activate={() => tryActivation(connection)}
pendingConnectionType={pendingConnection?.type}
/>
) : null
......
......@@ -12,7 +12,7 @@ export default function Web3Provider({ children }: { children: ReactNode }) {
const connections = useOrderedConnections()
const connectors: [Connector, Web3ReactHooks][] = connections.map(({ hooks, connector }) => [connector, hooks])
const key = useMemo(() => connections.map((connection) => connection.name).join('-'), [connections])
const key = useMemo(() => connections.map((connection) => connection.getName()).join('-'), [connections])
return (
<Web3ReactProvider connectors={connectors} key={key}>
......
// eslint-disable-next-line jest/no-export
export {}
import { ConnectionType, getConnections, useGetConnection } from 'connection'
import { renderHook } from 'test-utils'
beforeEach(() => {
jest.resetModules()
jest.resetAllMocks()
})
it('Non-injected Desktop', async () => {
jest.mock('connection/utils', () => ({ isInjected: false, isMetaMaskWallet: false, isCoinbaseWallet: false }))
jest.mock('utils/userAgent', () => ({ isMobile: false }))
const connection = await import('connection')
expect(connection.darkInjectedConnection.shouldDisplay).toBe(true)
expect(connection.darkInjectedConnection.name).toBe('MetaMask')
expect(connection.darkInjectedConnection.overrideActivate).toBeDefined()
expect(connection.coinbaseWalletConnection.shouldDisplay).toBe(true)
expect(connection.uniwalletConnectConnection.shouldDisplay).toBe(true)
expect(connection.walletConnectConnection.shouldDisplay).toBe(true)
expect(connection.getConnections(true).filter((c) => c.shouldDisplay).length).toEqual(4)
})
const UserAgentMock = jest.requireMock('utils/userAgent')
jest.mock('utils/userAgent', () => ({
isMobile: false,
}))
it('MetaMask Injected Desktop', async () => {
jest.mock('connection/utils', () => ({ isInjected: true, isMetaMaskWallet: true, isCoinbaseWallet: false }))
jest.mock('utils/userAgent', () => ({ isMobile: false }))
const connection = await import('connection')
expect(connection.darkInjectedConnection.shouldDisplay).toBe(true)
expect(connection.darkInjectedConnection.name).toBe('MetaMask')
expect(connection.darkInjectedConnection.overrideActivate).toBeUndefined()
expect(connection.coinbaseWalletConnection.shouldDisplay).toBe(true)
expect(connection.uniwalletConnectConnection.shouldDisplay).toBe(true)
expect(connection.walletConnectConnection.shouldDisplay).toBe(true)
expect(connection.getConnections(true).filter((c) => c.shouldDisplay).length).toEqual(4)
})
describe('connection utility/metadata tests', () => {
const createWalletEnvironment = (ethereum: Window['window']['ethereum'], isMobile = false) => {
UserAgentMock.isMobile = isMobile
global.window.ethereum = ethereum
it('Coinbase Injected Desktop', async () => {
jest.mock('connection/utils', () => ({ isInjected: true, isMetaMaskWallet: false, isCoinbaseWallet: true }))
jest.mock('utils/userAgent', () => ({ isMobile: false }))
const connection = await import('connection')
expect(connection.darkInjectedConnection.shouldDisplay).toBe(true)
expect(connection.darkInjectedConnection.name).toBe('MetaMask')
expect(connection.darkInjectedConnection.overrideActivate).toBeDefined()
expect(connection.coinbaseWalletConnection.shouldDisplay).toBe(true)
expect(connection.uniwalletConnectConnection.shouldDisplay).toBe(true)
expect(connection.walletConnectConnection.shouldDisplay).toBe(true)
expect(connection.getConnections(true).filter((c) => c.shouldDisplay).length).toEqual(4)
})
const displayed = getConnections().filter((c) => c.shouldDisplay())
const getConnection = renderHook(() => useGetConnection()).result.current
const injected = getConnection(ConnectionType.INJECTED)
const coinbase = getConnection(ConnectionType.COINBASE_WALLET)
const uniswap = getConnection(ConnectionType.UNIWALLET)
const walletconnect = getConnection(ConnectionType.WALLET_CONNECT)
it('Coinbase and MetaMask Injected Desktop', async () => {
jest.mock('connection/utils', () => ({ isInjected: true, isMetaMaskWallet: true, isCoinbaseWallet: true }))
jest.mock('utils/userAgent', () => ({ isMobile: false }))
const connection = await import('connection')
expect(connection.darkInjectedConnection.shouldDisplay).toBe(true)
expect(connection.darkInjectedConnection.name).toBe('MetaMask')
expect(connection.darkInjectedConnection.overrideActivate).toBeUndefined()
expect(connection.coinbaseWalletConnection.shouldDisplay).toBe(true)
expect(connection.uniwalletConnectConnection.shouldDisplay).toBe(true)
expect(connection.walletConnectConnection.shouldDisplay).toBe(true)
expect(connection.getConnections(true).filter((c) => c.shouldDisplay).length).toEqual(4)
})
return { displayed, injected, coinbase, uniswap, walletconnect }
}
it('Generic Injected Desktop', async () => {
jest.mock('connection/utils', () => ({ isInjected: true, isMetaMaskWallet: false, isCoinbaseWallet: false }))
jest.mock('utils/userAgent', () => ({ isMobile: false }))
const connection = await import('connection')
expect(connection.darkInjectedConnection.shouldDisplay).toBe(true)
expect(connection.darkInjectedConnection.name).toBe('Browser Wallet')
expect(connection.darkInjectedConnection.overrideActivate).toBeUndefined()
expect(connection.coinbaseWalletConnection.shouldDisplay).toBe(true)
expect(connection.uniwalletConnectConnection.shouldDisplay).toBe(true)
expect(connection.walletConnectConnection.shouldDisplay).toBe(true)
expect(connection.getConnections(true).filter((c) => c.shouldDisplay).length).toEqual(4)
})
it('Non-injected Desktop', async () => {
const { displayed, injected } = createWalletEnvironment(undefined)
it('Generic Injected Mobile Browser', async () => {
jest.mock('connection/utils', () => ({ isInjected: true, isMetaMaskWallet: false, isCoinbaseWallet: false }))
jest.mock('utils/userAgent', () => ({ isMobile: true }))
const connection = await import('connection')
expect(connection.darkInjectedConnection.shouldDisplay).toBe(true)
expect(connection.darkInjectedConnection.name).toBe('Browser Wallet')
})
expect(displayed.includes(injected)).toBe(true)
expect(injected.getName()).toBe('MetaMask')
expect(injected.overrideActivate?.()).toBeTruthy()
it('MetaMask Mobile Browser', async () => {
jest.mock('connection/utils', () => ({ isInjected: true, isMetaMaskWallet: true, isCoinbaseWallet: false }))
jest.mock('utils/userAgent', () => ({ isMobile: true }))
const connection = await import('connection')
expect(connection.darkInjectedConnection.shouldDisplay).toBe(true)
expect(connection.darkInjectedConnection.name).toBe('MetaMask')
expect(connection.getConnections(true).filter((c) => c.shouldDisplay).length).toEqual(1)
})
expect(displayed.length).toEqual(4)
})
it('Coinbase Mobile Browser', async () => {
jest.mock('connection/utils', () => ({ isInjected: true, isMetaMaskWallet: false, isCoinbaseWallet: true }))
jest.mock('utils/userAgent', () => ({ isMobile: true }))
const connection = await import('connection')
it('MetaMask-Injected Desktop', async () => {
const { displayed, injected } = createWalletEnvironment({ isMetaMask: true })
expect(connection.coinbaseWalletConnection.shouldDisplay).toBe(true)
expect(connection.coinbaseWalletConnection.overrideActivate).toBeUndefined()
expect(connection.getConnections(true).filter((c) => c.shouldDisplay).length).toEqual(1)
})
expect(displayed.includes(injected)).toBe(true)
expect(injected.getName()).toBe('MetaMask')
expect(injected.overrideActivate?.()).toBeFalsy()
expect(displayed.length).toEqual(4)
})
it('Coinbase-Injected Desktop', async () => {
const { displayed, injected, coinbase } = createWalletEnvironment({ isCoinbaseWallet: true })
expect(displayed.includes(coinbase)).toBe(true)
expect(displayed.includes(injected)).toBe(true)
expect(injected.getName()).toBe('MetaMask')
expect(injected.overrideActivate?.()).toBeTruthy()
expect(displayed.length).toEqual(4)
})
it('Coinbase and MetaMask Injected Desktop', async () => {
const { displayed, injected, coinbase } = createWalletEnvironment({ isCoinbaseWallet: true, isMetaMask: true })
expect(displayed.includes(coinbase)).toBe(true)
expect(displayed.includes(injected)).toBe(true)
expect(injected.getName()).toBe('MetaMask')
expect(injected.overrideActivate?.()).toBeFalsy()
expect(displayed.length).toEqual(4)
})
it('Generic Injected Desktop', async () => {
const { displayed, injected } = createWalletEnvironment({ isTrustWallet: true })
expect(displayed.includes(injected)).toBe(true)
expect(injected.getName()).toBe('Browser Wallet')
expect(injected.overrideActivate?.()).toBeFalsy()
expect(displayed.length).toEqual(4)
})
it('Generic Browser Wallet that injects as MetaMask', async () => {
const { displayed, injected } = createWalletEnvironment({ isRabby: true, isMetaMask: true })
expect(displayed.includes(injected)).toBe(true)
expect(injected.getName()).toBe('Browser Wallet')
expect(injected.overrideActivate?.()).toBeFalsy()
expect(displayed.length).toEqual(4)
})
it('Generic Wallet Browser with delayed injection', async () => {
const { injected } = createWalletEnvironment(undefined)
expect(injected.getName()).toBe('MetaMask')
expect(injected.overrideActivate?.()).toBeTruthy()
createWalletEnvironment({ isTrustWallet: true })
expect(injected.getName()).toBe('Browser Wallet')
expect(injected.overrideActivate?.()).toBeFalsy()
})
const UNKNOWN_INJECTOR = { isRandomWallet: true } as Window['window']['ethereum']
it('Generic Unknown Injected Wallet Browser', async () => {
const { displayed, injected } = createWalletEnvironment(UNKNOWN_INJECTOR, true)
expect(displayed.includes(injected)).toBe(true)
expect(injected.getName()).toBe('Browser Wallet')
expect(injected.overrideActivate?.()).toBeFalsy()
// Ensures we provide multiple connection options if in an unknown injected browser
expect(displayed.length).toEqual(4)
})
it('MetaMask Mobile Browser', async () => {
const { displayed, injected } = createWalletEnvironment({ isMetaMask: true }, true)
expect(displayed.includes(injected)).toBe(true)
expect(injected.getName()).toBe('MetaMask')
expect(injected.overrideActivate?.()).toBeFalsy()
expect(displayed.length).toEqual(1)
})
it('Coinbase Mobile Browser', async () => {
const { displayed, coinbase } = createWalletEnvironment({ isCoinbaseWallet: true }, true)
expect(displayed.includes(coinbase)).toBe(true)
// Expect coinbase option to not override activation in a the cb mobile browser
expect(coinbase.overrideActivate?.()).toBeFalsy()
expect(displayed.length).toEqual(1)
})
it('Uninjected mWeb Browser', async () => {
const { displayed, injected, coinbase, walletconnect } = createWalletEnvironment(undefined, true)
expect(displayed.includes(coinbase)).toBe(true)
expect(displayed.includes(walletconnect)).toBe(true)
// Don't show injected connection on plain mWeb browser
expect(displayed.includes(injected)).toBe(false)
// Expect coinbase option to launch coinbase app in a regular mobile browser
expect(coinbase.overrideActivate?.()).toBeTruthy()
it('mWeb Browser', async () => {
jest.mock('connection/utils', () => ({ isInjected: false, isMetaMaskWallet: false, isCoinbaseWallet: false }))
jest.mock('utils/userAgent', () => ({ isMobile: true }))
const connection = await import('connection')
expect(connection.darkInjectedConnection.shouldDisplay).toBe(false)
expect(connection.coinbaseWalletConnection.shouldDisplay).toBe(true)
expect(connection.coinbaseWalletConnection.overrideActivate).toBeDefined()
expect(connection.uniwalletConnectConnection.shouldDisplay).toBe(true)
expect(connection.walletConnectConnection.shouldDisplay).toBe(true)
expect(connection.getConnections(true).filter((c) => c.shouldDisplay).length).toEqual(3)
expect(displayed.length).toEqual(3)
})
})
......@@ -9,17 +9,15 @@ import GNOSIS_ICON_URL from 'assets/images/gnosis.png'
import METAMASK_ICON_URL from 'assets/images/metamask.svg'
import UNIWALLET_ICON_URL from 'assets/images/uniwallet.svg'
import WALLET_CONNECT_ICON_URL from 'assets/images/walletConnectIcon.svg'
import INJECTED_DARK_ICON_URL from 'assets/svg/browser-wallet-dark.svg'
import INJECTED_LIGHT_ICON_URL from 'assets/svg/browser-wallet-light.svg'
import UNISWAP_LOGO_URL from 'assets/svg/logo.svg'
import { SupportedChainId } from 'constants/chains'
import { useCallback } from 'react'
import { useIsDarkMode } from 'theme/components/ThemeToggle'
import { isMobile, isNonIOSPhone } from 'utils/userAgent'
import { RPC_URLS } from '../constants/networks'
import { RPC_PROVIDERS } from '../constants/providers'
import { isCoinbaseWallet, isInjected, isMetaMaskWallet } from './utils'
import { getIsCoinbaseWallet, getIsInjected, getIsMetaMaskWallet } from './utils'
import { UniwalletConnect, WalletConnectPopup } from './WalletConnect'
export enum ConnectionType {
......@@ -32,13 +30,14 @@ export enum ConnectionType {
}
export interface Connection {
name: string
getName(): string
connector: Connector
hooks: Web3ReactHooks
type: ConnectionType
icon?: string
shouldDisplay?: boolean
overrideActivate?: () => void
// TODO(WEB-3130): add darkmode check for icons
getIcon?(): string
shouldDisplay(): boolean
overrideActivate?: () => boolean
isNew?: boolean
}
......@@ -50,73 +49,72 @@ const [web3Network, web3NetworkHooks] = initializeConnector<Network>(
(actions) => new Network({ actions, urlMap: RPC_PROVIDERS, defaultChainId: 1 })
)
export const networkConnection: Connection = {
name: 'Network',
getName: () => 'Network',
connector: web3Network,
hooks: web3NetworkHooks,
type: ConnectionType.NETWORK,
shouldDisplay: false,
shouldDisplay: () => false,
}
const isCoinbaseWalletBrowser = isMobile && isCoinbaseWallet
const isMetaMaskBrowser = isMobile && isMetaMaskWallet
const getIsInjectedMobileBrowser = isCoinbaseWalletBrowser || isMetaMaskBrowser
const getIsCoinbaseWalletBrowser = () => isMobile && getIsCoinbaseWallet()
const getIsMetaMaskBrowser = () => isMobile && getIsMetaMaskWallet()
const getIsInjectedMobileBrowser = () => getIsCoinbaseWalletBrowser() || getIsMetaMaskBrowser()
const getShouldAdvertiseMetaMask = !isMetaMaskWallet && !isMobile && (!isInjected || isCoinbaseWallet)
const isGenericInjector = isInjected && !isMetaMaskWallet && !isCoinbaseWallet
const getShouldAdvertiseMetaMask = () =>
!getIsMetaMaskWallet() && !isMobile && (!getIsInjected() || getIsCoinbaseWallet())
const getIsGenericInjector = () => getIsInjected() && !getIsMetaMaskWallet() && !getIsCoinbaseWallet()
const [web3Injected, web3InjectedHooks] = initializeConnector<MetaMask>((actions) => new MetaMask({ actions, onError }))
const baseInjectedConnection: Omit<Connection, 'icon'> = {
name: isGenericInjector ? 'Browser Wallet' : 'MetaMask',
const injectedConnection: Connection = {
// TODO(WEB-3131) re-add "Install MetaMask" string when no injector is present
getName: () => (getIsGenericInjector() ? 'Browser Wallet' : 'MetaMask'),
connector: web3Injected,
hooks: web3InjectedHooks,
type: ConnectionType.INJECTED,
shouldDisplay: isMetaMaskWallet || getShouldAdvertiseMetaMask || isGenericInjector,
getIcon: () => (getIsGenericInjector() ? INJECTED_LIGHT_ICON_URL : METAMASK_ICON_URL),
shouldDisplay: () => getIsMetaMaskWallet() || getShouldAdvertiseMetaMask() || getIsGenericInjector(),
// If on non-injected, non-mobile browser, prompt user to install Metamask
overrideActivate: getShouldAdvertiseMetaMask ? () => window.open('https://metamask.io/', 'inst_metamask') : undefined,
}
export const darkInjectedConnection: Connection = {
...baseInjectedConnection,
icon: isGenericInjector ? INJECTED_DARK_ICON_URL : METAMASK_ICON_URL,
}
export const lightInjectedConnection: Connection = {
...baseInjectedConnection,
icon: isGenericInjector ? INJECTED_LIGHT_ICON_URL : METAMASK_ICON_URL,
overrideActivate: () => {
if (getShouldAdvertiseMetaMask()) {
window.open('https://metamask.io/', 'inst_metamask')
return true
}
return false
},
}
const [web3GnosisSafe, web3GnosisSafeHooks] = initializeConnector<GnosisSafe>((actions) => new GnosisSafe({ actions }))
export const gnosisSafeConnection: Connection = {
name: 'Gnosis Safe',
getName: () => 'Gnosis Safe',
connector: web3GnosisSafe,
hooks: web3GnosisSafeHooks,
type: ConnectionType.GNOSIS_SAFE,
icon: GNOSIS_ICON_URL,
shouldDisplay: false,
getIcon: () => GNOSIS_ICON_URL,
shouldDisplay: () => false,
}
const [web3WalletConnect, web3WalletConnectHooks] = initializeConnector<WalletConnectPopup>(
(actions) => new WalletConnectPopup({ actions, onError })
)
export const walletConnectConnection: Connection = {
name: 'WalletConnect',
getName: () => 'WalletConnect',
connector: web3WalletConnect,
hooks: web3WalletConnectHooks,
type: ConnectionType.WALLET_CONNECT,
icon: WALLET_CONNECT_ICON_URL,
shouldDisplay: !getIsInjectedMobileBrowser,
getIcon: () => WALLET_CONNECT_ICON_URL,
shouldDisplay: () => !getIsInjectedMobileBrowser(),
}
const [web3UniwalletConnect, web3UniwalletConnectHooks] = initializeConnector<UniwalletConnect>(
(actions) => new UniwalletConnect({ actions, onError })
)
export const uniwalletConnectConnection: Connection = {
name: 'Uniswap Wallet',
getName: () => 'Uniswap Wallet',
connector: web3UniwalletConnect,
hooks: web3UniwalletConnectHooks,
type: ConnectionType.UNIWALLET,
icon: UNIWALLET_ICON_URL,
shouldDisplay: Boolean(!getIsInjectedMobileBrowser && !isNonIOSPhone),
getIcon: () => UNIWALLET_ICON_URL,
shouldDisplay: () => Boolean(!getIsInjectedMobileBrowser() && !isNonIOSPhone),
isNew: true,
}
......@@ -134,24 +132,28 @@ const [web3CoinbaseWallet, web3CoinbaseWalletHooks] = initializeConnector<Coinba
})
)
export const coinbaseWalletConnection: Connection = {
name: 'Coinbase Wallet',
const coinbaseWalletConnection: Connection = {
getName: () => 'Coinbase Wallet',
connector: web3CoinbaseWallet,
hooks: web3CoinbaseWalletHooks,
type: ConnectionType.COINBASE_WALLET,
icon: COINBASE_ICON_URL,
shouldDisplay: Boolean((isMobile && !getIsInjectedMobileBrowser) || !isMobile || isCoinbaseWalletBrowser),
getIcon: () => COINBASE_ICON_URL,
shouldDisplay: () =>
Boolean((isMobile && !getIsInjectedMobileBrowser()) || !isMobile || getIsCoinbaseWalletBrowser()),
// If on a mobile browser that isn't the coinbase wallet browser, deeplink to the coinbase wallet app
overrideActivate:
isMobile && !getIsInjectedMobileBrowser
? () => window.open('https://go.cb-w.com/mtUDhEZPy1', 'cbwallet')
: undefined,
overrideActivate: () => {
if (isMobile && !getIsInjectedMobileBrowser()) {
window.open('https://go.cb-w.com/mtUDhEZPy1', 'cbwallet')
return true
}
return false
},
}
export function getConnections(isDarkMode: boolean) {
export function getConnections() {
return [
uniwalletConnectConnection,
isDarkMode ? darkInjectedConnection : lightInjectedConnection,
injectedConnection,
walletConnectConnection,
coinbaseWalletConnection,
gnosisSafeConnection,
......@@ -159,38 +161,29 @@ export function getConnections(isDarkMode: boolean) {
]
}
export function useConnections() {
const isDarkMode = useIsDarkMode()
return getConnections(isDarkMode)
}
export function useGetConnection() {
const isDarkMode = useIsDarkMode()
return useCallback(
(c: Connector | ConnectionType) => {
if (c instanceof Connector) {
const connection = getConnections(isDarkMode).find((connection) => connection.connector === c)
if (!connection) {
throw Error('unsupported connector')
}
return connection
} else {
switch (c) {
case ConnectionType.INJECTED:
return isDarkMode ? darkInjectedConnection : lightInjectedConnection
case ConnectionType.COINBASE_WALLET:
return coinbaseWalletConnection
case ConnectionType.WALLET_CONNECT:
return walletConnectConnection
case ConnectionType.UNIWALLET:
return uniwalletConnectConnection
case ConnectionType.NETWORK:
return networkConnection
case ConnectionType.GNOSIS_SAFE:
return gnosisSafeConnection
}
return useCallback((c: Connector | ConnectionType) => {
if (c instanceof Connector) {
const connection = getConnections().find((connection) => connection.connector === c)
if (!connection) {
throw Error('unsupported connector')
}
return connection
} else {
switch (c) {
case ConnectionType.INJECTED:
return injectedConnection
case ConnectionType.COINBASE_WALLET:
return coinbaseWalletConnection
case ConnectionType.WALLET_CONNECT:
return walletConnectConnection
case ConnectionType.UNIWALLET:
return uniwalletConnectConnection
case ConnectionType.NETWORK:
return networkConnection
case ConnectionType.GNOSIS_SAFE:
return gnosisSafeConnection
}
},
[isDarkMode]
)
}
}, [])
}
export const isInjected = Boolean(window.ethereum)
export const getIsInjected = () => Boolean(window.ethereum)
// When using Brave browser, `isMetaMask` is set to true when using the built-in wallet
// This variable should be true only when using the MetaMask extension
// https://wallet-docs.brave.com/ethereum/wallet-detection#compatability-with-metamask
type NonMetaMaskFlag = 'isRabby' | 'isBraveWallet' | 'isTrustWallet' | 'isLedgerConnect'
const allNonMetamaskFlags: NonMetaMaskFlag[] = ['isRabby', 'isBraveWallet', 'isTrustWallet', 'isLedgerConnect']
export const isMetaMaskWallet = Boolean(
window.ethereum?.isMetaMask && !allNonMetamaskFlags.some((flag) => window.ethereum?.[flag])
)
export const getIsMetaMaskWallet = () =>
Boolean(window.ethereum?.isMetaMask && !allNonMetamaskFlags.some((flag) => window.ethereum?.[flag]))
export const isCoinbaseWallet = Boolean(window.ethereum?.isCoinbaseWallet)
export const getIsCoinbaseWallet = () => Boolean(window.ethereum?.isCoinbaseWallet)
// https://eips.ethereum.org/EIPS/eip-1193#provider-errors
export enum ErrorCode {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment