Skip to content
This repository has been archived by the owner on Jun 24, 2022. It is now read-only.

Commit

Permalink
Use previously supported wallets (#2166)
Browse files Browse the repository at this point in the history
* testing

* Enable Coinbase Wallet (wallet-link) (#2353)

* enable walletlink and upgrade package

* Limiting the supported networks for CoinbaseWallet

* Adding setDefaultInjected provider

* Enable Formatic wallet (#2388)

* Activate formatic wallet

* Adding reconnect Uninjected Provider

* Adding connecting web3Status after refresh

* Upgrade fortmatic to v2.2.1

* Mute unnecessary Overlay useEffect

* Adding new API 🔑

* Adding custom src/custom/connectors/Fortmaitc.ts

* merger conflict resolution

* set api key according to environment (#2422)

* Change clickable, fortmatic supportedChains, enum DefaultInjected

* Change CW deeplink

* Testing walletLink on mobile

(cherry picked from commit e88eb5e)
  • Loading branch information
henrypalacios authored and biocom committed Mar 2, 2022
1 parent 670ecf3 commit ffbbda9
Show file tree
Hide file tree
Showing 13 changed files with 190 additions and 61 deletions.
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ REACT_APP_NETWORK_URL_100=https://rpc.xdaichain.com

# Wallets
REACT_APP_PORTIS_ID="c0e2bf01-4b08-4fd5-ac7b-8e26b58cd236"
REACT_APP_FORTMATIC_KEY="pk_live_F937DF033A1666BF"
REACT_APP_FORTMATIC_KEY="pk_live_6AED76CA755EFDC7"
REACT_APP_FORTMATIC_SITE_VERIFICATION="LzjrtdM7hqVJfvvA"

# Domain regex (to detect environment)
Expand Down
4 changes: 3 additions & 1 deletion .env.production
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ REACT_APP_NETWORK_URL_100=https://rpc.xdaichain.com

# Wallets
REACT_APP_PORTIS_ID="c0e2bf01-4b08-4fd5-ac7b-8e26b58cd236"
REACT_APP_FORTMATIC_KEY="pk_live_F937DF033A1666BF"
REACT_APP_FORTMATIC_KEY="pk_live_9E53F9A29112A9FC"
REACT_APP_FORTMATIC_KEY_BARN="pk_live_C0DA025E15EBF895"
REACT_APP_FORTMATIC_KEY_PROD="pk_live_7BD8004CBBF5CDD6"

# Domain regex (to detect environment)
REACT_APP_DOMAIN_REGEX_LOCAL="^(:?localhost:\d{2,5}|(?:127|192)(?:\.[0-9]{1,3}){3})"
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@
"@web3-react/injected-connector": "^6.0.7",
"@web3-react/portis-connector": "^6.1.9",
"@web3-react/walletconnect-connector": "6.2.4",
"@web3-react/walletlink-connector": "^6.2.5",
"@web3-react/walletlink-connector": "^6.2.12",
"ajv": "^6.12.3",
"array.prototype.flat": "^1.2.4",
"array.prototype.flatmap": "^1.2.4",
Expand Down Expand Up @@ -227,6 +227,7 @@
"bnc-sdk": "^3.5.0",
"fast-safe-stringify": "^2.0.8",
"firebase": "^9.1.3",
"fortmatic": "^2.2.1",
"ipfs-http-client": "^52.0.3",
"paraswap": "npm:@nenad91/paraswap#5.1.0",
"react-appzi": "^1.0.4",
Expand Down
8 changes: 0 additions & 8 deletions src/constants/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,7 @@ export const SUPPORTED_WALLETS: { [key: string]: WalletInfo } = {
description: 'Use Coinbase Wallet app on mobile device',
href: null,
color: '#315CF5',
},
COINBASE_LINK: {
name: 'Open in Coinbase Wallet',
iconURL: COINBASE_ICON_URL,
description: 'Open in Coinbase Wallet app.',
href: 'https://go.cb-w.com/mtUDhEZPy1',
color: '#315CF5',
mobile: true,
mobileOnly: true,
},
FORTMATIC: {
connector: fortmatic,
Expand Down
14 changes: 7 additions & 7 deletions src/custom/components/WalletModal/WalletModalMod.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import styled from 'styled-components/macro'

import MetamaskIcon from 'assets/images/metamask.png'
import { ReactComponent as Close } from 'assets/images/x.svg'
import { fortmatic, injected, portis } from 'connectors'
import { OVERLAY_READY } from 'connectors/Fortmatic'
import { injected, portis } from 'connectors'
// import { OVERLAY_READY } from 'connectors/Fortmatic'
import { SUPPORTED_WALLETS } from 'constants/index'
import usePrevious from 'hooks/usePrevious'
import { useModalOpen, useWalletModalToggle } from 'state/application/hooks'
Expand Down Expand Up @@ -229,11 +229,11 @@ export default function WalletModal({
}

// close wallet modal if fortmatic modal is active
useEffect(() => {
fortmatic.on(OVERLAY_READY, () => {
toggleWalletModal()
})
}, [toggleWalletModal])
// useEffect(() => {
// fortmatic.on(OVERLAY_READY, () => {
// toggleWalletModal()
// })
// }, [toggleWalletModal])

// get wallets user can switch too, depending on device/browser
function getOptions() {
Expand Down
40 changes: 32 additions & 8 deletions src/custom/components/Web3Status/Web3StatusMod.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,19 +88,30 @@ const Web3StatusConnect = styled(Web3StatusGeneric)<{ faded?: boolean }>`
`}
`

export const Web3StatusConnected = styled(Web3StatusGeneric)<{ pending?: boolean }>`
export const Web3StatusConnected = styled(Web3StatusGeneric)<{ pending?: boolean; clickDisabled?: boolean }>`
background-color: ${({ pending, theme }) => (pending ? theme.primary1 : theme.bg2)};
border: 1px solid ${({ pending, theme }) => (pending ? theme.primary1 : theme.bg3)};
color: ${({ pending, theme }) => (pending ? theme.white : theme.text1)};
font-weight: 500;
:hover,
:focus {
background-color: ${({ pending, theme }) => (pending ? darken(0.05, theme.primary1) : lighten(0.05, theme.bg2))};
:focus {
border: 1px solid ${({ pending, theme }) => (pending ? darken(0.1, theme.primary1) : darken(0.1, theme.bg3))};
}
}
${({ clickDisabled }) =>
clickDisabled &&
css`
cursor: not-allowed;
`}
${({ clickDisabled, pending }) =>
!clickDisabled &&
css`
:hover,
:focus {
background-color: ${({ theme }) => (pending ? darken(0.05, theme.primary1) : lighten(0.05, theme.bg2))};
:focus {
border: 1px solid ${({ theme }) => (pending ? darken(0.1, theme.primary1) : darken(0.1, theme.bg3))};
}
}
`}
`

export const Text = styled.p`
Expand Down Expand Up @@ -172,10 +183,12 @@ export function Web3StatusInner({
pendingCount,
StatusIconComponent,
openOrdersPanel, // mod
thereWasAProvider, //mod
}: {
pendingCount?: number
StatusIconComponent: (props: { connector: AbstractConnector }) => JSX.Element | null
openOrdersPanel: () => void // mod
thereWasAProvider: boolean //mod
}) {
const { account, connector, error } = useWeb3React()

Expand Down Expand Up @@ -230,6 +243,17 @@ export function Web3StatusInner({
<Text>{error instanceof UnsupportedChainIdError ? <Trans>Wrong Network</Trans> : <Trans>Error</Trans>}</Text>
</Web3StatusError>
)
} else if (thereWasAProvider) {
return (
<Web3StatusConnected pending clickDisabled={true}>
<RowBetween>
<Text>
<Trans>Connecting</Trans>...
</Text>{' '}
<Loader stroke="white" />
</RowBetween>
</Web3StatusConnected>
)
} else {
return (
<Web3StatusConnect id="connect-wallet" onClick={toggleWalletModal} faded={!account}>
Expand Down
6 changes: 4 additions & 2 deletions src/custom/components/Web3Status/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import useRecentActivity, { TransactionAndOrder } from 'hooks/useRecentActivity'
import { useWalletInfo } from 'hooks/useWalletInfo'
import { ButtonSecondary } from 'components/Button'
import { OrderStatus } from '@src/custom/state/orders/actions'
import { STORAGE_KEY_LAST_PROVIDER } from 'constants/index'

export const Wrapper = styled.div`
color: ${({ theme }) => theme.wallet?.color};
Expand Down Expand Up @@ -72,7 +73,7 @@ interface Web3StatusProps {

export default function Web3Status({ openOrdersPanel }: Web3StatusProps) {
const walletInfo = useWalletInfo()

const latestProvider = localStorage.getItem(STORAGE_KEY_LAST_PROVIDER)
// Returns all RECENT (last day) transaction and orders in 2 arrays: pending and confirmed
const allRecentActivity = useRecentActivity()

Expand All @@ -88,7 +89,7 @@ export default function Web3Status({ openOrdersPanel }: Web3StatusProps) {
}, [allRecentActivity])

const { active, activeNetwork, ensName } = walletInfo
if (!activeNetwork && !active) {
if (!activeNetwork && !active && !latestProvider) {
return null
}

Expand All @@ -98,6 +99,7 @@ export default function Web3Status({ openOrdersPanel }: Web3StatusProps) {
pendingCount={pendingActivity.length}
StatusIconComponent={StatusIcon}
openOrdersPanel={openOrdersPanel}
thereWasAProvider={!!latestProvider}
/>
<WalletModal ENSName={ensName} pendingTransactions={pendingActivity} confirmedTransactions={confirmedActivity} />
</Wrapper>
Expand Down
56 changes: 56 additions & 0 deletions src/custom/connectors/Fortmatic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { FortmaticConnector as FortmaticConnectorCore } from '@web3-react/fortmatic-connector'
import { isProd, isBarn } from 'utils/environments'
import { SupportedChainId } from 'constants/chains'

export const OVERLAY_READY = 'OVERLAY_READY'

type FormaticSupportedChains = SupportedChainId.MAINNET | SupportedChainId.RINKEBY

const CHAIN_ID_NETWORK_ARGUMENT: Partial<Record<SupportedChainId, string | undefined>> = {
[SupportedChainId.MAINNET]: undefined,
[SupportedChainId.RINKEBY]: 'rinkeby',
}

export class FortmaticConnector extends FortmaticConnectorCore {
async activate() {
if (!this.fortmatic) {
const { default: Fortmatic } = await import('fortmatic')

const { apiKey, chainId } = this as any
if (chainId in CHAIN_ID_NETWORK_ARGUMENT) {
this.fortmatic = new Fortmatic(apiKey, CHAIN_ID_NETWORK_ARGUMENT[chainId as FormaticSupportedChains])
} else {
throw new Error(`Unsupported network ID: ${chainId}`)
}
}

const provider = this.fortmatic.getProvider()

// It is no longer necessary
// const pollForOverlayReady = new Promise<void>((resolve) => {
// const interval = setInterval(() => {
// if (provider.overlay.overlayReady) {
// clearInterval(interval)
// this.emit(OVERLAY_READY)
// resolve()
// }
// }, 200)
// })

const account = await provider.enable().then((accounts: string[]) => accounts[0])

return { provider: this.fortmatic.getProvider(), chainId: (this as any).chainId, account }
}
}

// Allows to select fortmatic envvar according to prod, barn or test environment
export function getFortmaticApiKey(): string | undefined {
let apiKey = process.env.REACT_APP_FORTMATIC_KEY
if (isProd) {
apiKey = process.env.REACT_APP_FORTMATIC_KEY_PROD
} else if (isBarn) {
apiKey = process.env.REACT_APP_FORTMATIC_KEY_BARN
}

return apiKey
}
5 changes: 3 additions & 2 deletions src/custom/connectors/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { WalletConnectConnector } from '@web3-react/walletconnect-connector'
import { WalletLinkConnector } from '@web3-react/walletlink-connector'
import { PortisConnector } from '@web3-react/portis-connector'

import { FortmaticConnector } from 'connectors/Fortmatic'
import { FortmaticConnector, getFortmaticApiKey } from 'connectors/Fortmatic'
import { NetworkConnector } from 'connectors/NetworkConnector'
import { AbstractConnector } from '@web3-react/abstract-connector'

Expand Down Expand Up @@ -91,7 +91,7 @@ export const walletconnect = new WalletConnectConnector({

// mainnet only
export const fortmatic = new FortmaticConnector({
apiKey: process.env.REACT_APP_FORTMATIC_KEY ?? '',
apiKey: getFortmaticApiKey() ?? '',
chainId: NETWORK_CHAIN_ID,
})

Expand All @@ -108,6 +108,7 @@ export const walletlink = new WalletLinkConnector({
url: rpcNetworks[NETWORK_CHAIN_ID],
appName: 'CowSwap',
appLogoUrl: 'https://raw.githubusercontent.com/gnosis/gp-swap-ui/develop/public/favicon.png',
supportedChainIds: getSupportedChainIds(),
})

export enum WalletProvider {
Expand Down
2 changes: 1 addition & 1 deletion src/custom/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const APP_DATA_HASH = getAppDataHash()
export const PRODUCTION_URL = 'cowswap.exchange'
export const BARN_URL = `barn.${PRODUCTION_URL}`

const DISABLED_WALLETS = /^(?:WALLET_LINK|COINBASE_LINK|FORTMATIC|Portis)$/i
const DISABLED_WALLETS = /^(?:Portis)$/i

// Re-export only the supported wallets
export const SUPPORTED_WALLETS = Object.keys(SUPPORTED_WALLETS_UNISWAP).reduce((acc, key) => {
Expand Down
85 changes: 64 additions & 21 deletions src/custom/hooks/web3.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { useWeb3React as useWeb3ReactCore } from '@web3-react/core'
import { AbstractConnector } from '@web3-react/abstract-connector'
import { useEffect, useState, useCallback } from 'react'
import { isMobile } from 'react-device-detect'
import { injected, walletconnect, getProviderType, WalletProvider } from 'connectors'
import { injected, walletconnect, getProviderType, WalletProvider, fortmatic, walletlink } from 'connectors'
import { STORAGE_KEY_LAST_PROVIDER } from 'constants/index'

// exports from the original file
export { useActiveWeb3React, useInactiveListener } from '@src/hooks/web3'

enum DefaultProvidersInjected {
METAMASK = WalletProvider.INJECTED,
COINBASE_WALLET = WalletProvider.WALLET_LINK,
}

export function useEagerConnect() {
const { activate, active, connector } = useWeb3ReactCore()
const [tried, setTried] = useState(false)
Expand All @@ -22,30 +28,38 @@ export function useEagerConnect() {
}
}, [connector, active])

const connectInjected = useCallback(() => {
// check if the our application is authorized/connected with Metamask
injected.isAuthorized().then((isAuthorized) => {
if (isAuthorized) {
activate(injected, undefined, true).catch(() => {
setTried(true)
})
} else {
if (isMobile && window.ethereum) {
const connectInjected = useCallback(
(providerName = DefaultProvidersInjected.METAMASK) => {
// check if the our application is authorized/connected with Metamask
injected.isAuthorized().then((isAuthorized) => {
if (isAuthorized) {
setDefaultInjected(providerName)
activate(injected, undefined, true).catch(() => {
setTried(true)
})
} else {
setTried(true)
if (isMobile && window.ethereum) {
setDefaultInjected(providerName)
activate(injected, undefined, true).catch(() => {
setTried(true)
})
} else {
setTried(true)
}
}
}
})
}, [activate, setTried])
})
},
[activate, setTried]
)

const connectWalletConnect = useCallback(() => {
activate(walletconnect, undefined, true).catch(() => {
setTried(true)
})
}, [activate, setTried])
const reconnectUninjectedProvider = useCallback(
(provider: AbstractConnector): void => {
activate(provider, undefined, true).catch(() => {
setTried(true)
})
},
[activate, setTried]
)

useEffect(() => {
if (!active) {
Expand All @@ -60,10 +74,14 @@ export function useEagerConnect() {
connectInjected()
} else if (latestProvider === WalletProvider.WALLET_CONNECT) {
// WC is last provider
connectWalletConnect()
reconnectUninjectedProvider(walletconnect)
} else if (latestProvider === WalletProvider.WALLET_LINK) {
reconnectUninjectedProvider(walletlink)
} else if (latestProvider === WalletProvider.FORMATIC) {
reconnectUninjectedProvider(fortmatic)
}
}
}, [connectInjected, connectWalletConnect, active]) // intentionally only running on mount (make sure it's only mounted once :))
}, [connectInjected, active, reconnectUninjectedProvider]) // intentionally only running on mount (make sure it's only mounted once :))

// if the connection worked, wait until we get confirmation of that to flip the flag
useEffect(() => {
Expand All @@ -84,3 +102,28 @@ export function useEagerConnect() {

return tried
}

/**
* Allows to select the default injected ethereum provider.
*
* It is assumed that metamask is the default injected Provider, however coinbaseWallet overrides this.
*/
export function setDefaultInjected(providerName: DefaultProvidersInjected) {
const { ethereum } = window

if (!ethereum?.providers) return

let provider
switch (providerName) {
case DefaultProvidersInjected.COINBASE_WALLET:
provider = ethereum.providers.find(({ isCoinbaseWallet }) => isCoinbaseWallet)
break
case DefaultProvidersInjected.METAMASK:
provider = ethereum.providers.find(({ isMetaMask }) => isMetaMask)
break
}

if (provider) {
ethereum.setSelectedProvider(provider)
}
}
Loading

0 comments on commit ffbbda9

Please sign in to comment.