Commit 9d9b3dca authored by Mike Grabowski's avatar Mike Grabowski Committed by GitHub

feat: detect Brave Wallet (#5836)

* feat: support brave better

* fix: apply review comments

* address revieW

* chore: fix lint

* chore: add comment
parent a11c7e95
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { import { getConnection, getConnectionName, getIsCoinbaseWallet, getIsMetaMaskWallet } from 'connection/utils'
getConnection,
getConnectionName,
getHasCoinbaseExtensionInstalled,
getHasMetaMaskExtensionInstalled,
} from 'connection/utils'
import { useCallback } from 'react' import { useCallback } from 'react'
import { ExternalLink as LinkIcon } from 'react-feather' import { ExternalLink as LinkIcon } from 'react-feather'
import { useAppDispatch } from 'state/hooks' import { useAppDispatch } from 'state/hooks'
...@@ -215,8 +210,8 @@ export default function AccountDetails({ ...@@ -215,8 +210,8 @@ export default function AccountDetails({
const theme = useTheme() const theme = useTheme()
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
const hasMetaMaskExtension = getHasMetaMaskExtensionInstalled() const hasMetaMaskExtension = getIsMetaMaskWallet()
const hasCoinbaseExtension = getHasCoinbaseExtensionInstalled() const hasCoinbaseExtension = getIsCoinbaseWallet()
const isInjectedMobileBrowser = (hasMetaMaskExtension || hasCoinbaseExtension) && isMobile const isInjectedMobileBrowser = (hasMetaMaskExtension || hasCoinbaseExtension) && isMobile
function formatConnectorName() { function formatConnectorName() {
......
...@@ -73,8 +73,8 @@ it('loads Wallet Modal on desktop', async () => { ...@@ -73,8 +73,8 @@ it('loads Wallet Modal on desktop', async () => {
it('loads Wallet Modal on desktop with generic Injected', async () => { it('loads Wallet Modal on desktop with generic Injected', async () => {
jest.spyOn(connectionUtils, 'getIsInjected').mockReturnValue(true) jest.spyOn(connectionUtils, 'getIsInjected').mockReturnValue(true)
jest.spyOn(connectionUtils, 'getHasMetaMaskExtensionInstalled').mockReturnValue(false) jest.spyOn(connectionUtils, 'getIsMetaMaskWallet').mockReturnValue(false)
jest.spyOn(connectionUtils, 'getHasCoinbaseExtensionInstalled').mockReturnValue(false) jest.spyOn(connectionUtils, 'getIsCoinbaseWallet').mockReturnValue(false)
render(<WalletModal pendingTransactions={[]} confirmedTransactions={[]} />) render(<WalletModal pendingTransactions={[]} confirmedTransactions={[]} />)
expect(screen.getByText('Browser Wallet')).toBeInTheDocument() expect(screen.getByText('Browser Wallet')).toBeInTheDocument()
...@@ -85,8 +85,8 @@ it('loads Wallet Modal on desktop with generic Injected', async () => { ...@@ -85,8 +85,8 @@ it('loads Wallet Modal on desktop with generic Injected', async () => {
it('loads Wallet Modal on desktop with MetaMask installed', async () => { it('loads Wallet Modal on desktop with MetaMask installed', async () => {
jest.spyOn(connectionUtils, 'getIsInjected').mockReturnValue(true) jest.spyOn(connectionUtils, 'getIsInjected').mockReturnValue(true)
jest.spyOn(connectionUtils, 'getHasMetaMaskExtensionInstalled').mockReturnValue(true) jest.spyOn(connectionUtils, 'getIsMetaMaskWallet').mockReturnValue(true)
jest.spyOn(connectionUtils, 'getHasCoinbaseExtensionInstalled').mockReturnValue(false) jest.spyOn(connectionUtils, 'getIsCoinbaseWallet').mockReturnValue(false)
render(<WalletModal pendingTransactions={[]} confirmedTransactions={[]} />) render(<WalletModal pendingTransactions={[]} confirmedTransactions={[]} />)
expect(screen.getByText('MetaMask')).toBeInTheDocument() expect(screen.getByText('MetaMask')).toBeInTheDocument()
...@@ -99,8 +99,8 @@ it('loads Wallet Modal on mobile', async () => { ...@@ -99,8 +99,8 @@ it('loads Wallet Modal on mobile', async () => {
UserAgentMock.isMobile = true UserAgentMock.isMobile = true
jest.spyOn(connectionUtils, 'getIsInjected').mockReturnValue(false) jest.spyOn(connectionUtils, 'getIsInjected').mockReturnValue(false)
jest.spyOn(connectionUtils, 'getHasMetaMaskExtensionInstalled').mockReturnValue(false) jest.spyOn(connectionUtils, 'getIsMetaMaskWallet').mockReturnValue(false)
jest.spyOn(connectionUtils, 'getHasCoinbaseExtensionInstalled').mockReturnValue(false) jest.spyOn(connectionUtils, 'getIsCoinbaseWallet').mockReturnValue(false)
render(<WalletModal pendingTransactions={[]} confirmedTransactions={[]} />) render(<WalletModal pendingTransactions={[]} confirmedTransactions={[]} />)
expect(screen.getByText('Open in Coinbase Wallet')).toBeInTheDocument() expect(screen.getByText('Open in Coinbase Wallet')).toBeInTheDocument()
...@@ -112,8 +112,8 @@ it('loads Wallet Modal on MetaMask browser', async () => { ...@@ -112,8 +112,8 @@ it('loads Wallet Modal on MetaMask browser', async () => {
UserAgentMock.isMobile = true UserAgentMock.isMobile = true
jest.spyOn(connectionUtils, 'getIsInjected').mockReturnValue(true) jest.spyOn(connectionUtils, 'getIsInjected').mockReturnValue(true)
jest.spyOn(connectionUtils, 'getHasMetaMaskExtensionInstalled').mockReturnValue(true) jest.spyOn(connectionUtils, 'getIsMetaMaskWallet').mockReturnValue(true)
jest.spyOn(connectionUtils, 'getHasCoinbaseExtensionInstalled').mockReturnValue(false) jest.spyOn(connectionUtils, 'getIsCoinbaseWallet').mockReturnValue(false)
render(<WalletModal pendingTransactions={[]} confirmedTransactions={[]} />) render(<WalletModal pendingTransactions={[]} confirmedTransactions={[]} />)
expect(screen.getByText('MetaMask')).toBeInTheDocument() expect(screen.getByText('MetaMask')).toBeInTheDocument()
...@@ -124,8 +124,8 @@ it('loads Wallet Modal on Coinbase Wallet browser', async () => { ...@@ -124,8 +124,8 @@ it('loads Wallet Modal on Coinbase Wallet browser', async () => {
UserAgentMock.isMobile = true UserAgentMock.isMobile = true
jest.spyOn(connectionUtils, 'getIsInjected').mockReturnValue(true) jest.spyOn(connectionUtils, 'getIsInjected').mockReturnValue(true)
jest.spyOn(connectionUtils, 'getHasMetaMaskExtensionInstalled').mockReturnValue(false) jest.spyOn(connectionUtils, 'getIsMetaMaskWallet').mockReturnValue(false)
jest.spyOn(connectionUtils, 'getHasCoinbaseExtensionInstalled').mockReturnValue(true) jest.spyOn(connectionUtils, 'getIsCoinbaseWallet').mockReturnValue(true)
render(<WalletModal pendingTransactions={[]} confirmedTransactions={[]} />) render(<WalletModal pendingTransactions={[]} confirmedTransactions={[]} />)
expect(screen.getByText('Coinbase Wallet')).toBeInTheDocument() expect(screen.getByText('Coinbase Wallet')).toBeInTheDocument()
......
...@@ -10,9 +10,9 @@ import { networkConnection } from 'connection' ...@@ -10,9 +10,9 @@ import { networkConnection } from 'connection'
import { import {
getConnection, getConnection,
getConnectionName, getConnectionName,
getHasCoinbaseExtensionInstalled, getIsCoinbaseWallet,
getHasMetaMaskExtensionInstalled,
getIsInjected, getIsInjected,
getIsMetaMaskWallet,
} from 'connection/utils' } from 'connection/utils'
import usePrevious from 'hooks/usePrevious' import usePrevious from 'hooks/usePrevious'
import { useCallback, useEffect, useState } from 'react' import { useCallback, useEffect, useState } from 'react'
...@@ -253,8 +253,8 @@ export default function WalletModal({ ...@@ -253,8 +253,8 @@ export default function WalletModal({
function getOptions() { function getOptions() {
const isInjected = getIsInjected() const isInjected = getIsInjected()
const hasMetaMaskExtension = getHasMetaMaskExtensionInstalled() const hasMetaMaskExtension = getIsMetaMaskWallet()
const hasCoinbaseExtension = getHasCoinbaseExtensionInstalled() const hasCoinbaseExtension = getIsCoinbaseWallet()
const isCoinbaseWalletBrowser = isMobile && hasCoinbaseExtension const isCoinbaseWalletBrowser = isMobile && hasCoinbaseExtension
const isMetaMaskBrowser = isMobile && hasMetaMaskExtension const isMetaMaskBrowser = isMobile && hasMetaMaskExtension
......
...@@ -12,16 +12,19 @@ export function getIsInjected(): boolean { ...@@ -12,16 +12,19 @@ export function getIsInjected(): boolean {
return Boolean(window.ethereum) return Boolean(window.ethereum)
} }
export function getHasMetaMaskExtensionInstalled(): boolean { export function getIsBraveWallet(): boolean {
return window.ethereum?.isMetaMask ?? false return window.ethereum?.isBraveWallet ?? false
} }
export function getHasCoinbaseExtensionInstalled(): boolean { export function getIsMetaMaskWallet(): boolean {
return window.ethereum?.isCoinbaseWallet ?? false // When using Brave browser, `isMetaMask` is set to true when using the built-in wallet
// This function should return true only when using the MetaMask extension
// https://wallet-docs.brave.com/ethereum/wallet-detection#compatability-with-metamask
return (window.ethereum?.isMetaMask ?? false) && !getIsBraveWallet()
} }
export function getIsMetaMask(connectionType: ConnectionType): boolean { export function getIsCoinbaseWallet(): boolean {
return connectionType === ConnectionType.INJECTED && getHasMetaMaskExtensionInstalled() return window.ethereum?.isCoinbaseWallet ?? false
} }
const CONNECTIONS = [ const CONNECTIONS = [
...@@ -56,7 +59,7 @@ export function getConnection(c: Connector | ConnectionType) { ...@@ -56,7 +59,7 @@ export function getConnection(c: Connector | ConnectionType) {
export function getConnectionName( export function getConnectionName(
connectionType: ConnectionType, connectionType: ConnectionType,
hasMetaMaskExtension: boolean = getHasMetaMaskExtensionInstalled() hasMetaMaskExtension: boolean = getIsMetaMaskWallet()
) { ) {
switch (connectionType) { switch (connectionType) {
case ConnectionType.INJECTED: case ConnectionType.INJECTED:
......
...@@ -8,8 +8,11 @@ interface Window { ...@@ -8,8 +8,11 @@ interface Window {
// walletLinkExtension is injected by the Coinbase Wallet extension // walletLinkExtension is injected by the Coinbase Wallet extension
walletLinkExtension?: any walletLinkExtension?: any
ethereum?: { ethereum?: {
// value that is populated and returns true by the Coinbase Wallet mobile dapp browser // set by the Coinbase Wallet mobile dapp browser
isCoinbaseWallet?: true isCoinbaseWallet?: true
// set by the Brave browser when using built-in wallet
isBraveWallet?: true
// set by the MetaMask browser extension (also set by Brave browser when using built-in wallet)
isMetaMask?: true isMetaMask?: true
autoRefreshOnNetworkChange?: boolean autoRefreshOnNetworkChange?: boolean
} }
......
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