Commit 4e462ddb authored by Vignesh Mohankumar's avatar Vignesh Mohankumar Committed by GitHub

refactor: extract Web3Provider hooks, create internal Connection representation (#4040)

* refactor: separate hooks file for Web3Provider

* move utils

* rename + comments

* rename Wallet enum to ConnectionType

* more wallet -> connectiontype

* more wallet -> connectiontype

* move hooks

* use Connection everywhere

* connector -> connection

* generic getConnection

* rename injected -> injectedConnection

* check connectionType

* rm unused
parent 48a962a7
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { Connector } from '@web3-react/types'
import CopyHelper from 'components/AccountDetails/Copy' import CopyHelper from 'components/AccountDetails/Copy'
import { coinbaseWalletConnection, injectedConnection } from 'connection'
import { getConnection } from 'connection/utils'
import { useCallback, useContext } from 'react' import { useCallback, useContext } 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'
...@@ -10,7 +11,6 @@ import styled, { ThemeContext } from 'styled-components/macro' ...@@ -10,7 +11,6 @@ import styled, { ThemeContext } from 'styled-components/macro'
import { isMobile } from 'utils/userAgent' import { isMobile } from 'utils/userAgent'
import { ReactComponent as Close } from '../../assets/images/x.svg' import { ReactComponent as Close } from '../../assets/images/x.svg'
import { coinbaseWallet, injected } from '../../connectors'
import { SUPPORTED_WALLETS } from '../../constants/wallet' import { SUPPORTED_WALLETS } from '../../constants/wallet'
import { clearAllTransactions } from '../../state/transactions/reducer' import { clearAllTransactions } from '../../state/transactions/reducer'
import { ExternalLink, LinkStyledButton, ThemedText } from '../../theme' import { ExternalLink, LinkStyledButton, ThemedText } from '../../theme'
...@@ -163,29 +163,6 @@ const WalletName = styled.div` ...@@ -163,29 +163,6 @@ const WalletName = styled.div`
color: ${({ theme }) => theme.text3}; color: ${({ theme }) => theme.text3};
` `
const IconWrapper = styled.div<{ size?: number }>`
${({ theme }) => theme.flexColumnNoWrap};
align-items: center;
justify-content: center;
margin-right: 8px;
& > img,
span {
height: ${({ size }) => (size ? size + 'px' : '32px')};
width: ${({ size }) => (size ? size + 'px' : '32px')};
}
${({ theme }) => theme.mediaWidth.upToMedium`
align-items: flex-end;
`};
`
function WrappedStatusIcon({ connector }: { connector: Connector }) {
return (
<IconWrapper size={16}>
<StatusIcon connector={connector} />
</IconWrapper>
)
}
const TransactionListWrapper = styled.div` const TransactionListWrapper = styled.div`
${({ theme }) => theme.flexColumnNoWrap}; ${({ theme }) => theme.flexColumnNoWrap};
` `
...@@ -228,6 +205,8 @@ export default function AccountDetails({ ...@@ -228,6 +205,8 @@ export default function AccountDetails({
openOptions, openOptions,
}: AccountDetailsProps) { }: AccountDetailsProps) {
const { chainId, account, connector } = useWeb3React() const { chainId, account, connector } = useWeb3React()
const connectionType = getConnection(connector).type
const theme = useContext(ThemeContext) const theme = useContext(ThemeContext)
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
...@@ -241,7 +220,8 @@ export default function AccountDetails({ ...@@ -241,7 +220,8 @@ export default function AccountDetails({
const name = Object.keys(SUPPORTED_WALLETS) const name = Object.keys(SUPPORTED_WALLETS)
.filter( .filter(
(k) => (k) =>
SUPPORTED_WALLETS[k].connector === connector && (connector !== injected || isMetaMask === (k === 'METAMASK')) SUPPORTED_WALLETS[k].connector === connector &&
(connector !== injectedConnection.connector || isMetaMask === (k === 'METAMASK'))
) )
.map((k) => SUPPORTED_WALLETS[k].name)[0] .map((k) => SUPPORTED_WALLETS[k].name)[0]
return ( return (
...@@ -281,7 +261,7 @@ export default function AccountDetails({ ...@@ -281,7 +261,7 @@ export default function AccountDetails({
// Coinbase Wallet SDK does not emit a disconnect event to the provider, // Coinbase Wallet SDK does not emit a disconnect event to the provider,
// which is what web3-react uses to reset state. As a workaround we manually // which is what web3-react uses to reset state. As a workaround we manually
// reset state. // reset state.
if (connector === coinbaseWallet) { if (connector === coinbaseWalletConnection.connector) {
connector.resetState() connector.resetState()
} }
} else { } else {
...@@ -308,21 +288,10 @@ export default function AccountDetails({ ...@@ -308,21 +288,10 @@ export default function AccountDetails({
</AccountGroupingRow> </AccountGroupingRow>
<AccountGroupingRow data-testid="web3-account-identifier-row"> <AccountGroupingRow data-testid="web3-account-identifier-row">
<AccountControl> <AccountControl>
{ENSName ? ( <div>
<> <StatusIcon connectionType={connectionType} />
<div> <p>{ENSName ? ENSName : account && shortenAddress(account)}</p>
{connector && <WrappedStatusIcon connector={connector} />} </div>
<p> {ENSName}</p>
</div>
</>
) : (
<>
<div>
{connector && <WrappedStatusIcon connector={connector} />}
<p> {account && shortenAddress(account)}</p>
</div>
</>
)}
</AccountControl> </AccountControl>
</AccountGroupingRow> </AccountGroupingRow>
<AccountGroupingRow> <AccountGroupingRow>
......
...@@ -12,7 +12,7 @@ import { formatCurrencyAmount } from 'utils/formatCurrencyAmount' ...@@ -12,7 +12,7 @@ import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg' import { ReactComponent as DropDown } from '../../assets/images/dropdown.svg'
import useTheme from '../../hooks/useTheme' import useTheme from '../../hooks/useTheme'
import { useCurrencyBalance } from '../../state/wallet/hooks' import { useCurrencyBalance } from '../../state/connection/hooks'
import { ThemedText } from '../../theme' import { ThemedText } from '../../theme'
import { ButtonGray } from '../Button' import { ButtonGray } from '../Button'
import CurrencyLogo from '../CurrencyLogo' import CurrencyLogo from '../CurrencyLogo'
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { getWalletForConnector } from 'connectors' import { getConnection } from 'connection/utils'
import { CHAIN_INFO } from 'constants/chainInfo' import { CHAIN_INFO } from 'constants/chainInfo'
import { CHAIN_IDS_TO_NAMES, SupportedChainId } from 'constants/chains' import { CHAIN_IDS_TO_NAMES, SupportedChainId } from 'constants/chains'
import { useOnClickOutside } from 'hooks/useOnClickOutside' import { useOnClickOutside } from 'hooks/useOnClickOutside'
...@@ -12,8 +12,8 @@ import { ArrowDownCircle, ChevronDown } from 'react-feather' ...@@ -12,8 +12,8 @@ import { ArrowDownCircle, ChevronDown } from 'react-feather'
import { useHistory } from 'react-router-dom' import { useHistory } from 'react-router-dom'
import { useModalOpen, useToggleModal } from 'state/application/hooks' import { useModalOpen, useToggleModal } from 'state/application/hooks'
import { addPopup, ApplicationModal } from 'state/application/reducer' import { addPopup, ApplicationModal } from 'state/application/reducer'
import { updateConnectionError } from 'state/connection/reducer'
import { useAppDispatch } from 'state/hooks' import { useAppDispatch } from 'state/hooks'
import { updateWalletError } from 'state/wallet/reducer'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { ExternalLink, MEDIA_WIDTHS } from 'theme' import { ExternalLink, MEDIA_WIDTHS } from 'theme'
import { replaceURLParam } from 'utils/routes' import { replaceURLParam } from 'utils/routes'
...@@ -285,15 +285,15 @@ export default function NetworkSelector() { ...@@ -285,15 +285,15 @@ export default function NetworkSelector() {
async (targetChain: number, skipToggle?: boolean) => { async (targetChain: number, skipToggle?: boolean) => {
if (!connector) return if (!connector) return
const wallet = getWalletForConnector(connector) const connectionType = getConnection(connector).type
try { try {
dispatch(updateWalletError({ wallet, error: undefined })) dispatch(updateConnectionError({ connectionType, error: undefined }))
await switchChain(connector, targetChain) await switchChain(connector, targetChain)
} catch (error) { } catch (error) {
console.error('Failed to switch networks', error) console.error('Failed to switch networks', error)
dispatch(updateWalletError({ wallet, error: error.message })) dispatch(updateConnectionError({ connectionType, error: error.message }))
dispatch(addPopup({ content: { failedSwitchNetwork: targetChain }, key: `failed-network-switch` })) dispatch(addPopup({ content: { failedSwitchNetwork: targetChain }, key: `failed-network-switch` }))
} }
......
...@@ -9,9 +9,9 @@ import { NavLink } from 'react-router-dom' ...@@ -9,9 +9,9 @@ import { NavLink } from 'react-router-dom'
import { Text } from 'rebass' import { Text } from 'rebass'
import { useShowClaimPopup, useToggleSelfClaimModal } from 'state/application/hooks' import { useShowClaimPopup, useToggleSelfClaimModal } from 'state/application/hooks'
import { useUserHasAvailableClaim } from 'state/claim/hooks' import { useUserHasAvailableClaim } from 'state/claim/hooks'
import { useNativeCurrencyBalances } from 'state/connection/hooks'
import { useUserHasSubmittedClaim } from 'state/transactions/hooks' import { useUserHasSubmittedClaim } from 'state/transactions/hooks'
import { useDarkModeManager } from 'state/user/hooks' import { useDarkModeManager } from 'state/user/hooks'
import { useNativeCurrencyBalances } from 'state/wallet/hooks'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { isChainAllowed } from 'utils/switchChain' import { isChainAllowed } from 'utils/switchChain'
......
import { Connector } from '@web3-react/types' import { ConnectionType } from 'connection'
import styled from 'styled-components/macro'
import CoinbaseWalletIcon from '../../assets/images/coinbaseWalletIcon.svg' import CoinbaseWalletIcon from '../../assets/images/coinbaseWalletIcon.svg'
import FortmaticIcon from '../../assets/images/fortmaticIcon.png' import FortmaticIcon from '../../assets/images/fortmaticIcon.png'
import WalletConnectIcon from '../../assets/images/walletConnectIcon.svg' import WalletConnectIcon from '../../assets/images/walletConnectIcon.svg'
import { coinbaseWallet, fortmatic, injected, walletConnect } from '../../connectors'
import Identicon from '../Identicon' import Identicon from '../Identicon'
export default function StatusIcon({ connector }: { connector: Connector }) { const IconWrapper = styled.div<{ size?: number }>`
switch (connector) { ${({ theme }) => theme.flexColumnNoWrap};
case injected: align-items: center;
return <Identicon /> justify-content: center;
case walletConnect: margin-right: 8px;
return <img src={WalletConnectIcon} alt="WalletConnect" /> & > img,
case coinbaseWallet: span {
return <img src={CoinbaseWalletIcon} alt="Coinbase Wallet" /> height: ${({ size }) => (size ? size + 'px' : '32px')};
case fortmatic: width: ${({ size }) => (size ? size + 'px' : '32px')};
return <img src={FortmaticIcon} alt="Fortmatic" />
default:
return null
} }
${({ theme }) => theme.mediaWidth.upToMedium`
align-items: flex-end;
`};
`
export default function StatusIcon({ connectionType }: { connectionType: ConnectionType }) {
let image
switch (connectionType) {
case ConnectionType.INJECTED:
image = <Identicon />
break
case ConnectionType.WALLET_CONNECT:
image = <img src={WalletConnectIcon} alt="WalletConnect" />
break
case ConnectionType.COINBASE_WALLET:
image = <img src={CoinbaseWalletIcon} alt="Coinbase Wallet" />
break
case ConnectionType.FORTMATIC:
image = <img src={FortmaticIcon} alt="Fortmatic" />
break
}
return <IconWrapper size={16}>{image}</IconWrapper>
} }
...@@ -13,7 +13,7 @@ import styled from 'styled-components/macro' ...@@ -13,7 +13,7 @@ import styled from 'styled-components/macro'
import { BIG_INT_ZERO } from '../../constants/misc' import { BIG_INT_ZERO } from '../../constants/misc'
import { useColor } from '../../hooks/useColor' import { useColor } from '../../hooks/useColor'
import { useTotalSupply } from '../../hooks/useTotalSupply' import { useTotalSupply } from '../../hooks/useTotalSupply'
import { useTokenBalance } from '../../state/wallet/hooks' import { useTokenBalance } from '../../state/connection/hooks'
import { currencyId } from '../../utils/currencyId' import { currencyId } from '../../utils/currencyId'
import { unwrappedToken } from '../../utils/unwrappedToken' import { unwrappedToken } from '../../utils/unwrappedToken'
import { ButtonEmpty, ButtonPrimary, ButtonSecondary } from '../Button' import { ButtonEmpty, ButtonPrimary, ButtonSecondary } from '../Button'
......
...@@ -13,7 +13,7 @@ import styled from 'styled-components/macro' ...@@ -13,7 +13,7 @@ import styled from 'styled-components/macro'
import { BIG_INT_ZERO } from '../../constants/misc' import { BIG_INT_ZERO } from '../../constants/misc'
import { useColor } from '../../hooks/useColor' import { useColor } from '../../hooks/useColor'
import { useTotalSupply } from '../../hooks/useTotalSupply' import { useTotalSupply } from '../../hooks/useTotalSupply'
import { useTokenBalance } from '../../state/wallet/hooks' import { useTokenBalance } from '../../state/connection/hooks'
import { ExternalLink, ThemedText } from '../../theme' import { ExternalLink, ThemedText } from '../../theme'
import { currencyId } from '../../utils/currencyId' import { currencyId } from '../../utils/currencyId'
import { unwrappedToken } from '../../utils/unwrappedToken' import { unwrappedToken } from '../../utils/unwrappedToken'
......
...@@ -33,7 +33,7 @@ jest.mock('@web3-react/core', () => { ...@@ -33,7 +33,7 @@ jest.mock('@web3-react/core', () => {
} }
}) })
jest.mock('../../../state/wallet/hooks', () => { jest.mock('../../../state/connection/hooks', () => {
return { return {
useCurrencyBalance: (currency: Currency) => { useCurrencyBalance: (currency: Currency) => {
return mockCurrencyAmt[(currency as mockToken)?.address] return mockCurrencyAmt[(currency as mockToken)?.address]
......
...@@ -11,9 +11,9 @@ import styled from 'styled-components/macro' ...@@ -11,9 +11,9 @@ import styled from 'styled-components/macro'
import TokenListLogo from '../../../assets/svg/tokenlist.svg' import TokenListLogo from '../../../assets/svg/tokenlist.svg'
import { useIsUserAddedToken } from '../../../hooks/Tokens' import { useIsUserAddedToken } from '../../../hooks/Tokens'
import { useCurrencyBalance } from '../../../state/connection/hooks'
import { useCombinedActiveList } from '../../../state/lists/hooks' import { useCombinedActiveList } from '../../../state/lists/hooks'
import { WrappedTokenInfo } from '../../../state/lists/wrappedTokenInfo' import { WrappedTokenInfo } from '../../../state/lists/wrappedTokenInfo'
import { useCurrencyBalance } from '../../../state/wallet/hooks'
import { ThemedText } from '../../../theme' import { ThemedText } from '../../../theme'
import { isTokenOnList } from '../../../utils' import { isTokenOnList } from '../../../utils'
import Column from '../../Column' import Column from '../../Column'
......
...@@ -15,7 +15,7 @@ import { Edit } from 'react-feather' ...@@ -15,7 +15,7 @@ import { Edit } from 'react-feather'
import AutoSizer from 'react-virtualized-auto-sizer' import AutoSizer from 'react-virtualized-auto-sizer'
import { FixedSizeList } from 'react-window' import { FixedSizeList } from 'react-window'
import { Text } from 'rebass' import { Text } from 'rebass'
import { useAllTokenBalances } from 'state/wallet/hooks' import { useAllTokenBalances } from 'state/connection/hooks'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { useAllTokens, useIsUserAddedToken, useSearchInactiveTokenLists, useToken } from '../../hooks/Tokens' import { useAllTokens, useIsUserAddedToken, useSearchInactiveTokenLists, useToken } from '../../hooks/Tokens'
......
...@@ -4,16 +4,17 @@ import { Connector } from '@web3-react/types' ...@@ -4,16 +4,17 @@ import { Connector } from '@web3-react/types'
import { sendEvent } from 'components/analytics' import { sendEvent } from 'components/analytics'
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
import { AutoRow } from 'components/Row' import { AutoRow } from 'components/Row'
import { ConnectionType, injectedConnection } from 'connection'
import { getConnection } from 'connection/utils'
import { useCallback, useEffect, useState } from 'react' import { useCallback, useEffect, useState } from 'react'
import { ArrowLeft } from 'react-feather' import { ArrowLeft } from 'react-feather'
import { updateConnectionError } from 'state/connection/reducer'
import { useAppDispatch, useAppSelector } from 'state/hooks' import { useAppDispatch, useAppSelector } from 'state/hooks'
import { updateSelectedWallet } from 'state/user/reducer' import { updateSelectedWallet } from 'state/user/reducer'
import { updateWalletError } from 'state/wallet/reducer'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import MetamaskIcon from '../../assets/images/metamask.png' import MetamaskIcon from '../../assets/images/metamask.png'
import { ReactComponent as Close } from '../../assets/images/x.svg' import { ReactComponent as Close } from '../../assets/images/x.svg'
import { fortmatic, getWalletForConnector, injected } from '../../connectors'
import { SUPPORTED_WALLETS } from '../../constants/wallet' import { SUPPORTED_WALLETS } from '../../constants/wallet'
import { useModalOpen, useWalletModalToggle } from '../../state/application/hooks' import { useModalOpen, useWalletModalToggle } from '../../state/application/hooks'
import { ApplicationModal } from '../../state/application/reducer' import { ApplicationModal } from '../../state/application/reducer'
...@@ -125,7 +126,7 @@ export default function WalletModal({ ...@@ -125,7 +126,7 @@ export default function WalletModal({
const [pendingConnector, setPendingConnector] = useState<Connector | undefined>() const [pendingConnector, setPendingConnector] = useState<Connector | undefined>()
const pendingError = useAppSelector((state) => const pendingError = useAppSelector((state) =>
pendingConnector ? state.wallet.errorByWallet[getWalletForConnector(pendingConnector)] : undefined pendingConnector ? state.connection.errorByConnectionType[getConnection(pendingConnector).type] : undefined
) )
const walletModalOpen = useModalOpen(ApplicationModal.WALLET) const walletModalOpen = useModalOpen(ApplicationModal.WALLET)
...@@ -143,39 +144,39 @@ export default function WalletModal({ ...@@ -143,39 +144,39 @@ export default function WalletModal({
useEffect(() => { useEffect(() => {
if (pendingConnector && walletView !== WALLET_VIEWS.PENDING) { if (pendingConnector && walletView !== WALLET_VIEWS.PENDING) {
updateWalletError({ wallet: getWalletForConnector(pendingConnector), error: undefined }) updateConnectionError({ connectionType: getConnection(pendingConnector).type, error: undefined })
setPendingConnector(undefined) setPendingConnector(undefined)
} }
}, [pendingConnector, walletView]) }, [pendingConnector, walletView])
const tryActivation = useCallback( const tryActivation = useCallback(
async (connector: Connector) => { async (connector: Connector) => {
const wallet = getWalletForConnector(connector) const connectionType = getConnection(connector).type
// log selected wallet // log selected wallet
sendEvent({ sendEvent({
category: 'Wallet', category: 'Wallet',
action: 'Change Wallet', action: 'Change Wallet',
label: wallet, label: connectionType,
}) })
try { try {
// Fortmatic opens it's own modal on activation to log in. This modal has a tabIndex // Fortmatic opens it's own modal on activation to log in. This modal has a tabIndex
// collision into the WalletModal, so we special case by closing the modal. // collision into the WalletModal, so we special case by closing the modal.
if (connector === fortmatic) { if (connectionType === ConnectionType.FORTMATIC) {
toggleWalletModal() toggleWalletModal()
} }
setPendingConnector(connector) setPendingConnector(connector)
setWalletView(WALLET_VIEWS.PENDING) setWalletView(WALLET_VIEWS.PENDING)
dispatch(updateWalletError({ wallet, error: undefined })) dispatch(updateConnectionError({ connectionType, error: undefined }))
await connector.activate() await connector.activate()
dispatch(updateSelectedWallet({ wallet })) dispatch(updateSelectedWallet({ wallet: connectionType }))
} catch (error) { } catch (error) {
console.debug(`web3-react connection error: ${error}`) console.debug(`web3-react connection error: ${error}`)
dispatch(updateWalletError({ wallet, error: error.message })) dispatch(updateConnectionError({ connectionType, error: error.message }))
} }
}, },
[dispatch, toggleWalletModal] [dispatch, toggleWalletModal]
...@@ -221,7 +222,7 @@ export default function WalletModal({ ...@@ -221,7 +222,7 @@ export default function WalletModal({
} }
// overwrite injected when needed // overwrite injected when needed
if (option.connector === injected) { if (option.connector === injectedConnection.connector) {
// don't show injected if there's no injected provider // don't show injected if there's no injected provider
if (!(window.web3 || window.ethereum)) { if (!(window.web3 || window.ethereum)) {
if (option.name === 'MetaMask') { if (option.name === 'MetaMask') {
......
import { Web3ReactProvider } from '@web3-react/core' import { Web3ReactProvider } from '@web3-react/core'
import { Connector } from '@web3-react/types' import useConnectors from 'hooks/useConnectors'
import { BACKFILLABLE_WALLETS, getConnectorForWallet, gnosisSafe, injected, network, useConnectors } from 'connectors' import useEagerlyConnect from 'hooks/useEagerlyConnect'
import { ReactNode, useEffect } from 'react' import { ReactNode } from 'react'
import { useAppSelector } from 'state/hooks'
import { isMobile } from '../../utils/userAgent'
const connect = async (connector: Connector) => {
try {
if (connector.connectEagerly) {
await connector.connectEagerly()
} else {
await connector.activate()
}
} catch (error) {
console.debug(`web3-react eager connection error: ${error}`)
}
}
export default function Web3Provider({ children }: { children: ReactNode }) { export default function Web3Provider({ children }: { children: ReactNode }) {
const selectedWalletBackfilled = useAppSelector((state) => state.user.selectedWalletBackfilled) useEagerlyConnect()
const selectedWallet = useAppSelector((state) => state.user.selectedWallet) const connectors = useConnectors()
const connectors = useConnectors(selectedWallet)
const isMetaMask = !!window.ethereum?.isMetaMask
useEffect(() => {
connect(gnosisSafe)
connect(network)
if (isMobile && isMetaMask) {
injected.activate()
} else if (selectedWallet) {
connect(getConnectorForWallet(selectedWallet))
} else if (!selectedWalletBackfilled) {
BACKFILLABLE_WALLETS.map(getConnectorForWallet).forEach(connect)
}
// The dependency list is empty so this is only run once on mount
}, []) // eslint-disable-line react-hooks/exhaustive-deps
return <Web3ReactProvider connectors={connectors}>{children}</Web3ReactProvider> return <Web3ReactProvider connectors={connectors}>{children}</Web3ReactProvider>
} }
// eslint-disable-next-line no-restricted-imports // eslint-disable-next-line no-restricted-imports
import { t, Trans } from '@lingui/macro' import { t, Trans } from '@lingui/macro'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { Connector } from '@web3-react/types' import { getConnection } from 'connection/utils'
import { getWalletForConnector } from 'connectors'
import { darken } from 'polished' import { darken } from 'polished'
import { useMemo } from 'react' import { useMemo } from 'react'
import { Activity } from 'react-feather' import { Activity } from 'react-feather'
...@@ -21,16 +20,6 @@ import Loader from '../Loader' ...@@ -21,16 +20,6 @@ import Loader from '../Loader'
import { RowBetween } from '../Row' import { RowBetween } from '../Row'
import WalletModal from '../WalletModal' import WalletModal from '../WalletModal'
const IconWrapper = styled.div<{ size?: number }>`
${({ theme }) => theme.flexColumnNoWrap};
align-items: center;
justify-content: center;
& > * {
height: ${({ size }) => (size ? size + 'px' : '32px')};
width: ${({ size }) => (size ? size + 'px' : '32px')};
}
`
const Web3StatusGeneric = styled(ButtonSecondary)` const Web3StatusGeneric = styled(ButtonSecondary)`
${({ theme }) => theme.flexRowNoWrap} ${({ theme }) => theme.flexRowNoWrap}
width: 100%; width: 100%;
...@@ -131,18 +120,11 @@ function Sock() { ...@@ -131,18 +120,11 @@ function Sock() {
) )
} }
function WrappedStatusIcon({ connector }: { connector: Connector }) {
return (
<IconWrapper size={16}>
<StatusIcon connector={connector} />
</IconWrapper>
)
}
function Web3StatusInner() { function Web3StatusInner() {
const { account, connector, chainId, ENSName } = useWeb3React() const { account, connector, chainId, ENSName } = useWeb3React()
const connectionType = getConnection(connector).type
const error = useAppSelector((state) => state.wallet.errorByWallet[getWalletForConnector(connector)]) const error = useAppSelector((state) => state.connection.errorByConnectionType[getConnection(connector).type])
const chainAllowed = chainId && isChainAllowed(connector, chainId) const chainAllowed = chainId && isChainAllowed(connector, chainId)
...@@ -199,7 +181,7 @@ function Web3StatusInner() { ...@@ -199,7 +181,7 @@ function Web3StatusInner() {
<Text>{ENSName || shortenAddress(account)}</Text> <Text>{ENSName || shortenAddress(account)}</Text>
</> </>
)} )}
{!hasPendingTransactions && connector && <WrappedStatusIcon connector={connector} />} {!hasPendingTransactions && <StatusIcon connectionType={connectionType} />}
</Web3StatusConnected> </Web3StatusConnected>
) )
} else { } else {
......
...@@ -8,8 +8,8 @@ import { formatCurrencyAmount } from 'utils/formatCurrencyAmount' ...@@ -8,8 +8,8 @@ import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
import { UNI } from '../../constants/tokens' import { UNI } from '../../constants/tokens'
import useENS from '../../hooks/useENS' import useENS from '../../hooks/useENS'
import { useTokenBalance } from '../../state/connection/hooks'
import { useDelegateCallback } from '../../state/governance/hooks' import { useDelegateCallback } from '../../state/governance/hooks'
import { useTokenBalance } from '../../state/wallet/hooks'
import { ThemedText } from '../../theme' import { ThemedText } from '../../theme'
import AddressInputPanel from '../AddressInputPanel' import AddressInputPanel from '../AddressInputPanel'
import { ButtonPrimary } from '../Button' import { ButtonPrimary } from '../Button'
......
...@@ -9,11 +9,10 @@ import { WalletConnect } from '@web3-react/walletconnect' ...@@ -9,11 +9,10 @@ import { WalletConnect } from '@web3-react/walletconnect'
import { SupportedChainId } from 'constants/chains' import { SupportedChainId } from 'constants/chains'
import { INFURA_NETWORK_URLS } from 'constants/infura' import { INFURA_NETWORK_URLS } from 'constants/infura'
import Fortmatic from 'fortmatic' import Fortmatic from 'fortmatic'
import { useMemo } from 'react'
import UNISWAP_LOGO_URL from '../assets/svg/logo.svg' import UNISWAP_LOGO_URL from '../assets/svg/logo.svg'
export enum Wallet { export enum ConnectionType {
INJECTED = 'INJECTED', INJECTED = 'INJECTED',
COINBASE_WALLET = 'COINBASE_WALLET', COINBASE_WALLET = 'COINBASE_WALLET',
WALLET_CONNECT = 'WALLET_CONNECT', WALLET_CONNECT = 'WALLET_CONNECT',
...@@ -22,75 +21,40 @@ export enum Wallet { ...@@ -22,75 +21,40 @@ export enum Wallet {
GNOSIS_SAFE = 'GNOSIS_SAFE', GNOSIS_SAFE = 'GNOSIS_SAFE',
} }
export const BACKFILLABLE_WALLETS = [Wallet.COINBASE_WALLET, Wallet.WALLET_CONNECT, Wallet.INJECTED] export interface Connection {
export const SELECTABLE_WALLETS = [...BACKFILLABLE_WALLETS, Wallet.FORTMATIC] connector: Connector
hooks: Web3ReactHooks
type: ConnectionType
}
function onError(error: Error) { function onError(error: Error) {
console.debug(`web3-react error: ${error}`) console.debug(`web3-react error: ${error}`)
} }
export function getWalletForConnector(connector: Connector) { const [web3Network, web3NetworkHooks] = initializeConnector<Network>(
switch (connector) { (actions) => new Network({ actions, urlMap: INFURA_NETWORK_URLS, defaultChainId: 1 })
case injected: )
return Wallet.INJECTED export const networkConnection: Connection = {
case coinbaseWallet: connector: web3Network,
return Wallet.COINBASE_WALLET hooks: web3NetworkHooks,
case walletConnect: type: ConnectionType.NETWORK,
return Wallet.WALLET_CONNECT
case fortmatic:
return Wallet.FORTMATIC
case network:
return Wallet.NETWORK
case gnosisSafe:
return Wallet.GNOSIS_SAFE
default:
throw Error('unsupported connector')
}
} }
export function getConnectorForWallet(wallet: Wallet) { const [web3Injected, web3InjectedHooks] = initializeConnector<MetaMask>((actions) => new MetaMask({ actions, onError }))
switch (wallet) { export const injectedConnection: Connection = {
case Wallet.INJECTED: connector: web3Injected,
return injected hooks: web3InjectedHooks,
case Wallet.COINBASE_WALLET: type: ConnectionType.INJECTED,
return coinbaseWallet
case Wallet.WALLET_CONNECT:
return walletConnect
case Wallet.FORTMATIC:
return fortmatic
case Wallet.NETWORK:
return network
case Wallet.GNOSIS_SAFE:
return gnosisSafe
}
} }
function getHooksForWallet(wallet: Wallet) { const [web3GnosisSafe, web3GnosisSafeHooks] = initializeConnector<GnosisSafe>((actions) => new GnosisSafe({ actions }))
switch (wallet) { export const gnosisSafeConnection: Connection = {
case Wallet.INJECTED: connector: web3GnosisSafe,
return injectedHooks hooks: web3GnosisSafeHooks,
case Wallet.COINBASE_WALLET: type: ConnectionType.GNOSIS_SAFE,
return coinbaseWalletHooks
case Wallet.WALLET_CONNECT:
return walletConnectHooks
case Wallet.FORTMATIC:
return fortmaticHooks
case Wallet.NETWORK:
return networkHooks
case Wallet.GNOSIS_SAFE:
return gnosisSafeHooks
}
} }
export const [network, networkHooks] = initializeConnector<Network>( const [web3WalletConnect, web3WalletConnectHooks] = initializeConnector<WalletConnect>(
(actions) => new Network({ actions, urlMap: INFURA_NETWORK_URLS, defaultChainId: 1 })
)
export const [injected, injectedHooks] = initializeConnector<MetaMask>((actions) => new MetaMask({ actions, onError }))
export const [gnosisSafe, gnosisSafeHooks] = initializeConnector<GnosisSafe>((actions) => new GnosisSafe({ actions }))
export const [walletConnect, walletConnectHooks] = initializeConnector<WalletConnect>(
(actions) => (actions) =>
new WalletConnect({ new WalletConnect({
actions, actions,
...@@ -101,12 +65,22 @@ export const [walletConnect, walletConnectHooks] = initializeConnector<WalletCon ...@@ -101,12 +65,22 @@ export const [walletConnect, walletConnectHooks] = initializeConnector<WalletCon
onError, onError,
}) })
) )
export const walletConnectConnection: Connection = {
connector: web3WalletConnect,
hooks: web3WalletConnectHooks,
type: ConnectionType.WALLET_CONNECT,
}
export const [fortmatic, fortmaticHooks] = initializeConnector<EIP1193>( const [web3Fortmatic, web3FortmaticHooks] = initializeConnector<EIP1193>(
(actions) => new EIP1193({ actions, provider: new Fortmatic(process.env.REACT_APP_FORTMATIC_KEY).getProvider() }) (actions) => new EIP1193({ actions, provider: new Fortmatic(process.env.REACT_APP_FORTMATIC_KEY).getProvider() })
) )
export const fortmaticConnection: Connection = {
connector: web3Fortmatic,
hooks: web3FortmaticHooks,
type: ConnectionType.FORTMATIC,
}
export const [coinbaseWallet, coinbaseWalletHooks] = initializeConnector<CoinbaseWallet>( const [web3CoinbaseWallet, web3CoinbaseWalletHooks] = initializeConnector<CoinbaseWallet>(
(actions) => (actions) =>
new CoinbaseWallet({ new CoinbaseWallet({
actions, actions,
...@@ -119,33 +93,8 @@ export const [coinbaseWallet, coinbaseWalletHooks] = initializeConnector<Coinbas ...@@ -119,33 +93,8 @@ export const [coinbaseWallet, coinbaseWalletHooks] = initializeConnector<Coinbas
onError, onError,
}) })
) )
export const coinbaseWalletConnection: Connection = {
interface ConnectorListItem { connector: web3CoinbaseWallet,
connector: Connector hooks: web3CoinbaseWalletHooks,
hooks: Web3ReactHooks type: ConnectionType.COINBASE_WALLET,
}
function getConnectorListItemForWallet(wallet: Wallet) {
return {
connector: getConnectorForWallet(wallet),
hooks: getHooksForWallet(wallet),
}
}
export function useConnectors(selectedWallet: Wallet | undefined) {
return useMemo(() => {
const connectors: ConnectorListItem[] = [{ connector: gnosisSafe, hooks: gnosisSafeHooks }]
if (selectedWallet) {
connectors.push(getConnectorListItemForWallet(selectedWallet))
}
connectors.push(
...SELECTABLE_WALLETS.filter((wallet) => wallet !== selectedWallet).map(getConnectorListItemForWallet)
)
connectors.push({ connector: network, hooks: networkHooks })
const web3ReactConnectors: [Connector, Web3ReactHooks][] = connectors.map(({ connector, hooks }) => [
connector,
hooks,
])
return web3ReactConnectors
}, [selectedWallet])
} }
import { Connector } from '@web3-react/types'
import {
coinbaseWalletConnection,
ConnectionType,
fortmaticConnection,
gnosisSafeConnection,
injectedConnection,
networkConnection,
walletConnectConnection,
} from 'connection'
const CONNECTIONS = [
coinbaseWalletConnection,
fortmaticConnection,
injectedConnection,
networkConnection,
walletConnectConnection,
gnosisSafeConnection,
]
export function getConnection(c: Connector | ConnectionType) {
if (c instanceof Connector) {
const connection = CONNECTIONS.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.FORTMATIC:
return fortmaticConnection
case ConnectionType.NETWORK:
return networkConnection
case ConnectionType.GNOSIS_SAFE:
return gnosisSafeConnection
}
}
}
import { Connector } from '@web3-react/types' import { Connector } from '@web3-react/types'
import {
coinbaseWalletConnection,
ConnectionType,
fortmaticConnection,
injectedConnection,
walletConnectConnection,
} from 'connection'
import INJECTED_ICON_URL from '../assets/images/arrow-right.svg' import INJECTED_ICON_URL from '../assets/images/arrow-right.svg'
import COINBASE_ICON_URL from '../assets/images/coinbaseWalletIcon.svg' import COINBASE_ICON_URL from '../assets/images/coinbaseWalletIcon.svg'
import FORTMATIC_ICON_URL from '../assets/images/fortmaticIcon.png' import FORTMATIC_ICON_URL from '../assets/images/fortmaticIcon.png'
import METAMASK_ICON_URL from '../assets/images/metamask.png' import METAMASK_ICON_URL from '../assets/images/metamask.png'
import WALLETCONNECT_ICON_URL from '../assets/images/walletConnectIcon.svg' import WALLETCONNECT_ICON_URL from '../assets/images/walletConnectIcon.svg'
import { coinbaseWallet, fortmatic, injected, Wallet, walletConnect } from '../connectors'
interface WalletInfo { interface WalletInfo {
connector?: Connector connector?: Connector
wallet?: Wallet connectionType?: ConnectionType
name: string name: string
iconURL: string iconURL: string
description: string description: string
...@@ -22,8 +28,8 @@ interface WalletInfo { ...@@ -22,8 +28,8 @@ interface WalletInfo {
export const SUPPORTED_WALLETS: { [key: string]: WalletInfo } = { export const SUPPORTED_WALLETS: { [key: string]: WalletInfo } = {
INJECTED: { INJECTED: {
connector: injected, connector: injectedConnection.connector,
wallet: Wallet.INJECTED, connectionType: ConnectionType.INJECTED,
name: 'Injected', name: 'Injected',
iconURL: INJECTED_ICON_URL, iconURL: INJECTED_ICON_URL,
description: 'Injected web3 provider.', description: 'Injected web3 provider.',
...@@ -32,8 +38,8 @@ export const SUPPORTED_WALLETS: { [key: string]: WalletInfo } = { ...@@ -32,8 +38,8 @@ export const SUPPORTED_WALLETS: { [key: string]: WalletInfo } = {
primary: true, primary: true,
}, },
METAMASK: { METAMASK: {
connector: injected, connector: injectedConnection.connector,
wallet: Wallet.INJECTED, connectionType: ConnectionType.INJECTED,
name: 'MetaMask', name: 'MetaMask',
iconURL: METAMASK_ICON_URL, iconURL: METAMASK_ICON_URL,
description: 'Easy-to-use browser extension.', description: 'Easy-to-use browser extension.',
...@@ -41,8 +47,8 @@ export const SUPPORTED_WALLETS: { [key: string]: WalletInfo } = { ...@@ -41,8 +47,8 @@ export const SUPPORTED_WALLETS: { [key: string]: WalletInfo } = {
color: '#E8831D', color: '#E8831D',
}, },
WALLET_CONNECT: { WALLET_CONNECT: {
connector: walletConnect, connector: walletConnectConnection.connector,
wallet: Wallet.WALLET_CONNECT, connectionType: ConnectionType.WALLET_CONNECT,
name: 'WalletConnect', name: 'WalletConnect',
iconURL: WALLETCONNECT_ICON_URL, iconURL: WALLETCONNECT_ICON_URL,
description: 'Connect to Trust Wallet, Rainbow Wallet and more...', description: 'Connect to Trust Wallet, Rainbow Wallet and more...',
...@@ -51,8 +57,8 @@ export const SUPPORTED_WALLETS: { [key: string]: WalletInfo } = { ...@@ -51,8 +57,8 @@ export const SUPPORTED_WALLETS: { [key: string]: WalletInfo } = {
mobile: true, mobile: true,
}, },
COINBASE_WALLET: { COINBASE_WALLET: {
connector: coinbaseWallet, connector: coinbaseWalletConnection.connector,
wallet: Wallet.COINBASE_WALLET, connectionType: ConnectionType.COINBASE_WALLET,
name: 'Coinbase Wallet', name: 'Coinbase Wallet',
iconURL: COINBASE_ICON_URL, iconURL: COINBASE_ICON_URL,
description: 'Use Coinbase Wallet app on mobile device', description: 'Use Coinbase Wallet app on mobile device',
...@@ -69,8 +75,8 @@ export const SUPPORTED_WALLETS: { [key: string]: WalletInfo } = { ...@@ -69,8 +75,8 @@ export const SUPPORTED_WALLETS: { [key: string]: WalletInfo } = {
mobileOnly: true, mobileOnly: true,
}, },
FORTMATIC: { FORTMATIC: {
connector: fortmatic, connector: fortmaticConnection.connector,
wallet: Wallet.FORTMATIC, connectionType: ConnectionType.FORTMATIC,
name: 'Fortmatic', name: 'Fortmatic',
iconURL: FORTMATIC_ICON_URL, iconURL: FORTMATIC_ICON_URL,
description: 'Login using Fortmatic hosted wallet', description: 'Login using Fortmatic hosted wallet',
......
import { Web3ReactHooks } from '@web3-react/core'
import { Connector } from '@web3-react/types'
import { ConnectionType } from 'connection'
import { getConnection } from 'connection/utils'
import { useMemo } from 'react'
import { BACKFILLABLE_WALLETS } from 'state/connection/constants'
import { useAppSelector } from 'state/hooks'
const SELECTABLE_WALLETS = [...BACKFILLABLE_WALLETS, ConnectionType.FORTMATIC]
export default function useConnectors() {
const selectedWallet = useAppSelector((state) => state.user.selectedWallet)
return useMemo(() => {
const orderedConnectionTypes: ConnectionType[] = []
// Always attempt to use to Gnosis Safe first, as we can't know if we're in a SafeContext.
orderedConnectionTypes.push(ConnectionType.GNOSIS_SAFE)
// Add the `selectedWallet` to the top so it's prioritized, then add the other selectable wallets.
if (selectedWallet) {
orderedConnectionTypes.push(selectedWallet)
}
orderedConnectionTypes.push(...SELECTABLE_WALLETS.filter((wallet) => wallet !== selectedWallet))
// Add network connection last as it should be the fallback.
orderedConnectionTypes.push(ConnectionType.NETWORK)
// Convert to web3-react's representation of connectors.
const web3Connectors: [Connector, Web3ReactHooks][] = orderedConnectionTypes
.map(getConnection)
.map(({ connector, hooks }) => [connector, hooks])
return web3Connectors
}, [selectedWallet])
}
import { Connector } from '@web3-react/types'
import { gnosisSafeConnection, injectedConnection, networkConnection } from 'connection'
import { getConnection } from 'connection/utils'
import { useEffect } from 'react'
import { BACKFILLABLE_WALLETS } from 'state/connection/constants'
import { useAppSelector } from 'state/hooks'
import { isMobile } from 'utils/userAgent'
async function connect(connector: Connector) {
try {
if (connector.connectEagerly) {
await connector.connectEagerly()
} else {
await connector.activate()
}
} catch (error) {
console.debug(`web3-react eager connection error: ${error}`)
}
}
export default function useEagerlyConnect() {
const selectedWalletBackfilled = useAppSelector((state) => state.user.selectedWalletBackfilled)
const selectedWallet = useAppSelector((state) => state.user.selectedWallet)
const isMetaMask = !!window.ethereum?.isMetaMask
useEffect(() => {
connect(gnosisSafeConnection.connector)
connect(networkConnection.connector)
if (isMobile && isMetaMask) {
injectedConnection.connector.activate()
} else if (selectedWallet) {
connect(getConnection(selectedWallet).connector)
} else if (!selectedWalletBackfilled) {
BACKFILLABLE_WALLETS.map(getConnection)
.map((connection) => connection.connector)
.forEach(connect)
}
// The dependency list is empty so this is only run once on mount
}, []) // eslint-disable-line react-hooks/exhaustive-deps
}
...@@ -3,7 +3,7 @@ import { useWeb3React } from '@web3-react/core' ...@@ -3,7 +3,7 @@ import { useWeb3React } from '@web3-react/core'
import { SOCKS_CONTROLLER_ADDRESSES } from 'constants/addresses' import { SOCKS_CONTROLLER_ADDRESSES } from 'constants/addresses'
import { SupportedChainId } from 'constants/chains' import { SupportedChainId } from 'constants/chains'
import { useMemo } from 'react' import { useMemo } from 'react'
import { useTokenBalance } from 'state/wallet/hooks' import { useTokenBalance } from 'state/connection/hooks'
// technically a 721, not an ERC20, but suffices for our purposes // technically a 721, not an ERC20, but suffices for our purposes
const SOCKS = new Token(SupportedChainId.MAINNET, SOCKS_CONTROLLER_ADDRESSES[SupportedChainId.MAINNET], 0) const SOCKS = new Token(SupportedChainId.MAINNET, SOCKS_CONTROLLER_ADDRESSES[SupportedChainId.MAINNET], 0)
......
...@@ -6,9 +6,9 @@ import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount' ...@@ -6,9 +6,9 @@ import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount'
import { useMemo } from 'react' import { useMemo } from 'react'
import { WRAPPED_NATIVE_CURRENCY } from '../constants/tokens' import { WRAPPED_NATIVE_CURRENCY } from '../constants/tokens'
import { useCurrencyBalance } from '../state/connection/hooks'
import { useTransactionAdder } from '../state/transactions/hooks' import { useTransactionAdder } from '../state/transactions/hooks'
import { TransactionType } from '../state/transactions/types' import { TransactionType } from '../state/transactions/types'
import { useCurrencyBalance } from '../state/wallet/hooks'
import { useWETHContract } from './useContract' import { useWETHContract } from './useContract'
export enum WrapType { export enum WrapType {
......
...@@ -24,8 +24,8 @@ import { useTotalSupply } from '../../hooks/useTotalSupply' ...@@ -24,8 +24,8 @@ import { useTotalSupply } from '../../hooks/useTotalSupply'
import useUSDCPrice from '../../hooks/useUSDCPrice' import useUSDCPrice from '../../hooks/useUSDCPrice'
import { useV2Pair } from '../../hooks/useV2Pairs' import { useV2Pair } from '../../hooks/useV2Pairs'
import { useWalletModalToggle } from '../../state/application/hooks' import { useWalletModalToggle } from '../../state/application/hooks'
import { useTokenBalance } from '../../state/connection/hooks'
import { useStakingInfo } from '../../state/stake/hooks' import { useStakingInfo } from '../../state/stake/hooks'
import { useTokenBalance } from '../../state/wallet/hooks'
import { ThemedText } from '../../theme' import { ThemedText } from '../../theme'
import { currencyId } from '../../utils/currencyId' import { currencyId } from '../../utils/currencyId'
......
...@@ -44,8 +44,8 @@ import { useToken } from '../../hooks/Tokens' ...@@ -44,8 +44,8 @@ import { useToken } from '../../hooks/Tokens'
import { usePairContract, useV2MigratorContract } from '../../hooks/useContract' import { usePairContract, useV2MigratorContract } from '../../hooks/useContract'
import useIsArgentWallet from '../../hooks/useIsArgentWallet' import useIsArgentWallet from '../../hooks/useIsArgentWallet'
import { useTotalSupply } from '../../hooks/useTotalSupply' import { useTotalSupply } from '../../hooks/useTotalSupply'
import { useTokenBalance } from '../../state/connection/hooks'
import { TransactionType } from '../../state/transactions/types' import { TransactionType } from '../../state/transactions/types'
import { useTokenBalance } from '../../state/wallet/hooks'
import { BackArrow, ExternalLink, ThemedText } from '../../theme' import { BackArrow, ExternalLink, ThemedText } from '../../theme'
import { isAddress } from '../../utils' import { isAddress } from '../../utils'
import { calculateGasMargin } from '../../utils/calculateGasMargin' import { calculateGasMargin } from '../../utils/calculateGasMargin'
......
...@@ -18,8 +18,8 @@ import QuestionHelper from '../../components/QuestionHelper' ...@@ -18,8 +18,8 @@ import QuestionHelper from '../../components/QuestionHelper'
import { AutoRow } from '../../components/Row' import { AutoRow } from '../../components/Row'
import { Dots } from '../../components/swap/styleds' import { Dots } from '../../components/swap/styleds'
import { V2_FACTORY_ADDRESSES } from '../../constants/addresses' import { V2_FACTORY_ADDRESSES } from '../../constants/addresses'
import { useTokenBalancesWithLoadingIndicator } from '../../state/connection/hooks'
import { toV2LiquidityToken, useTrackedTokenPairs } from '../../state/user/hooks' import { toV2LiquidityToken, useTrackedTokenPairs } from '../../state/user/hooks'
import { useTokenBalancesWithLoadingIndicator } from '../../state/wallet/hooks'
import { BackArrow, StyledInternalLink, ThemedText } from '../../theme' import { BackArrow, StyledInternalLink, ThemedText } from '../../theme'
import { BodyWrapper } from '../AppBody' import { BodyWrapper } from '../AppBody'
......
...@@ -20,9 +20,9 @@ import { Dots } from '../../components/swap/styleds' ...@@ -20,9 +20,9 @@ import { Dots } from '../../components/swap/styleds'
import { SwitchLocaleLink } from '../../components/SwitchLocaleLink' import { SwitchLocaleLink } from '../../components/SwitchLocaleLink'
import { BIG_INT_ZERO } from '../../constants/misc' import { BIG_INT_ZERO } from '../../constants/misc'
import { useV2Pairs } from '../../hooks/useV2Pairs' import { useV2Pairs } from '../../hooks/useV2Pairs'
import { useTokenBalancesWithLoadingIndicator } from '../../state/connection/hooks'
import { useStakingInfo } from '../../state/stake/hooks' import { useStakingInfo } from '../../state/stake/hooks'
import { toV2LiquidityToken, useTrackedTokenPairs } from '../../state/user/hooks' import { toV2LiquidityToken, useTrackedTokenPairs } from '../../state/user/hooks'
import { useTokenBalancesWithLoadingIndicator } from '../../state/wallet/hooks'
import { ExternalLink, HideSmall, ThemedText } from '../../theme' import { ExternalLink, HideSmall, ThemedText } from '../../theme'
const PageWrapper = styled(AutoColumn)` const PageWrapper = styled(AutoColumn)`
......
...@@ -19,8 +19,8 @@ import CurrencySearchModal from '../../components/SearchModal/CurrencySearchModa ...@@ -19,8 +19,8 @@ import CurrencySearchModal from '../../components/SearchModal/CurrencySearchModa
import { SwitchLocaleLink } from '../../components/SwitchLocaleLink' import { SwitchLocaleLink } from '../../components/SwitchLocaleLink'
import { nativeOnChain } from '../../constants/tokens' import { nativeOnChain } from '../../constants/tokens'
import { PairState, useV2Pair } from '../../hooks/useV2Pairs' import { PairState, useV2Pair } from '../../hooks/useV2Pairs'
import { useTokenBalance } from '../../state/connection/hooks'
import { usePairAdder } from '../../state/user/hooks' import { usePairAdder } from '../../state/user/hooks'
import { useTokenBalance } from '../../state/wallet/hooks'
import { StyledInternalLink } from '../../theme' import { StyledInternalLink } from '../../theme'
import { ThemedText } from '../../theme' import { ThemedText } from '../../theme'
import { currencyId } from '../../utils/currencyId' import { currencyId } from '../../utils/currencyId'
......
...@@ -18,9 +18,9 @@ import { Link } from 'react-router-dom' ...@@ -18,9 +18,9 @@ import { Link } from 'react-router-dom'
import { Button } from 'rebass/styled-components' import { Button } from 'rebass/styled-components'
import { useModalOpen, useToggleDelegateModal } from 'state/application/hooks' import { useModalOpen, useToggleDelegateModal } from 'state/application/hooks'
import { ApplicationModal } from 'state/application/reducer' import { ApplicationModal } from 'state/application/reducer'
import { useTokenBalance } from 'state/connection/hooks'
import { ProposalData, ProposalState } from 'state/governance/hooks' import { ProposalData, ProposalState } from 'state/governance/hooks'
import { useAllProposalData, useUserDelegatee, useUserVotes } from 'state/governance/hooks' import { useAllProposalData, useUserDelegatee, useUserVotes } from 'state/governance/hooks'
import { useTokenBalance } from 'state/wallet/hooks'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { ExternalLink, ThemedText } from 'theme' import { ExternalLink, ThemedText } from 'theme'
import { shortenAddress } from 'utils' import { shortenAddress } from 'utils'
......
...@@ -38,6 +38,7 @@ import { ...@@ -38,6 +38,7 @@ import {
useToggleVoteModal, useToggleVoteModal,
} from '../../state/application/hooks' } from '../../state/application/hooks'
import { ApplicationModal } from '../../state/application/reducer' import { ApplicationModal } from '../../state/application/reducer'
import { useTokenBalance } from '../../state/connection/hooks'
import { import {
ProposalData, ProposalData,
ProposalState, ProposalState,
...@@ -47,7 +48,6 @@ import { ...@@ -47,7 +48,6 @@ import {
useUserVotesAsOfBlock, useUserVotesAsOfBlock,
} from '../../state/governance/hooks' } from '../../state/governance/hooks'
import { VoteOption } from '../../state/governance/types' import { VoteOption } from '../../state/governance/types'
import { useTokenBalance } from '../../state/wallet/hooks'
import { ExternalLink, StyledInternalLink, ThemedText } from '../../theme' import { ExternalLink, StyledInternalLink, ThemedText } from '../../theme'
import { isAddress } from '../../utils' import { isAddress } from '../../utils'
import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink' import { ExplorerDataType, getExplorerLink } from '../../utils/getExplorerLink'
......
...@@ -9,8 +9,8 @@ import { useAppDispatch, useAppSelector } from 'state/hooks' ...@@ -9,8 +9,8 @@ import { useAppDispatch, useAppSelector } from 'state/hooks'
import { useTotalSupply } from '../../hooks/useTotalSupply' import { useTotalSupply } from '../../hooks/useTotalSupply'
import { useV2Pair } from '../../hooks/useV2Pairs' import { useV2Pair } from '../../hooks/useV2Pairs'
import { useTokenBalances } from '../connection/hooks'
import { AppState } from '../index' import { AppState } from '../index'
import { useTokenBalances } from '../wallet/hooks'
import { Field, typeInput } from './actions' import { Field, typeInput } from './actions'
export function useBurnState(): AppState['burn'] { export function useBurnState(): AppState['burn'] {
......
import { ConnectionType } from 'connection'
export const BACKFILLABLE_WALLETS = [
ConnectionType.COINBASE_WALLET,
ConnectionType.WALLET_CONNECT,
ConnectionType.INJECTED,
]
import { createSlice } from '@reduxjs/toolkit'
import { ConnectionType } from 'connection'
export interface ConnectionState {
errorByConnectionType: Record<ConnectionType, string | undefined>
}
export const initialState: ConnectionState = {
errorByConnectionType: {
[ConnectionType.INJECTED]: undefined,
[ConnectionType.FORTMATIC]: undefined,
[ConnectionType.WALLET_CONNECT]: undefined,
[ConnectionType.COINBASE_WALLET]: undefined,
[ConnectionType.NETWORK]: undefined,
[ConnectionType.GNOSIS_SAFE]: undefined,
},
}
const connectionSlice = createSlice({
name: 'connection',
initialState,
reducers: {
updateConnectionError(
state,
{ payload: { connectionType, error } }: { payload: { connectionType: ConnectionType; error: string | undefined } }
) {
state.errorByConnectionType[connectionType] = error
},
},
})
export const { updateConnectionError } = connectionSlice.actions
export default connectionSlice.reducer
...@@ -6,6 +6,7 @@ import { load, save } from 'redux-localstorage-simple' ...@@ -6,6 +6,7 @@ import { load, save } from 'redux-localstorage-simple'
import application from './application/reducer' import application from './application/reducer'
import burn from './burn/reducer' import burn from './burn/reducer'
import burnV3 from './burn/v3/reducer' import burnV3 from './burn/v3/reducer'
import connection from './connection/reducer'
import { api as dataApi } from './data/slice' import { api as dataApi } from './data/slice'
import { updateVersion } from './global/actions' import { updateVersion } from './global/actions'
import lists from './lists/reducer' import lists from './lists/reducer'
...@@ -16,7 +17,6 @@ import { routingApi } from './routing/slice' ...@@ -16,7 +17,6 @@ import { routingApi } from './routing/slice'
import swap from './swap/reducer' import swap from './swap/reducer'
import transactions from './transactions/reducer' import transactions from './transactions/reducer'
import user from './user/reducer' import user from './user/reducer'
import wallet from './wallet/reducer'
const PERSISTED_KEYS: string[] = ['user', 'transactions', 'lists'] const PERSISTED_KEYS: string[] = ['user', 'transactions', 'lists']
...@@ -24,7 +24,7 @@ const store = configureStore({ ...@@ -24,7 +24,7 @@ const store = configureStore({
reducer: { reducer: {
application, application,
user, user,
wallet, connection,
transactions, transactions,
swap, swap,
mint, mint,
......
...@@ -9,8 +9,8 @@ import { useAppDispatch, useAppSelector } from 'state/hooks' ...@@ -9,8 +9,8 @@ import { useAppDispatch, useAppSelector } from 'state/hooks'
import { useTotalSupply } from '../../hooks/useTotalSupply' import { useTotalSupply } from '../../hooks/useTotalSupply'
import { PairState, useV2Pair } from '../../hooks/useV2Pairs' import { PairState, useV2Pair } from '../../hooks/useV2Pairs'
import { useCurrencyBalances } from '../connection/hooks'
import { AppState } from '../index' import { AppState } from '../index'
import { useCurrencyBalances } from '../wallet/hooks'
import { Field, typeInput } from './actions' import { Field, typeInput } from './actions'
const ZERO = JSBI.BigInt(0) const ZERO = JSBI.BigInt(0)
......
...@@ -23,8 +23,8 @@ import { replaceURLParam } from 'utils/routes' ...@@ -23,8 +23,8 @@ import { replaceURLParam } from 'utils/routes'
import { BIG_INT_ZERO } from '../../../constants/misc' import { BIG_INT_ZERO } from '../../../constants/misc'
import { PoolState } from '../../../hooks/usePools' import { PoolState } from '../../../hooks/usePools'
import { useCurrencyBalances } from '../../connection/hooks'
import { AppState } from '../../index' import { AppState } from '../../index'
import { useCurrencyBalances } from '../../wallet/hooks'
import { import {
Bound, Bound,
Field, Field,
......
...@@ -15,8 +15,8 @@ import { useCurrency } from '../../hooks/Tokens' ...@@ -15,8 +15,8 @@ import { useCurrency } from '../../hooks/Tokens'
import useENS from '../../hooks/useENS' import useENS from '../../hooks/useENS'
import useParsedQueryString from '../../hooks/useParsedQueryString' import useParsedQueryString from '../../hooks/useParsedQueryString'
import { isAddress } from '../../utils' import { isAddress } from '../../utils'
import { useCurrencyBalances } from '../connection/hooks'
import { AppState } from '../index' import { AppState } from '../index'
import { useCurrencyBalances } from '../wallet/hooks'
import { Field, replaceSwapState, selectCurrency, setRecipient, switchCurrencies, typeInput } from './actions' import { Field, replaceSwapState, selectCurrency, setRecipient, switchCurrencies, typeInput } from './actions'
import { SwapState } from './reducer' import { SwapState } from './reducer'
......
import { createSlice } from '@reduxjs/toolkit' import { createSlice } from '@reduxjs/toolkit'
import { Wallet } from 'connectors' import { ConnectionType } from 'connection'
import { SupportedLocale } from 'constants/locales' import { SupportedLocale } from 'constants/locales'
import { DEFAULT_DEADLINE_FROM_NOW } from '../../constants/misc' import { DEFAULT_DEADLINE_FROM_NOW } from '../../constants/misc'
...@@ -14,7 +14,7 @@ export interface UserState { ...@@ -14,7 +14,7 @@ export interface UserState {
// we want to handle that case by backfilling them manually. Once we backfill, we set the backfilled field to `true`. // we want to handle that case by backfilling them manually. Once we backfill, we set the backfilled field to `true`.
// After some period of time, our active users will have this property set so we can likely remove the backfilling logic. // After some period of time, our active users will have this property set so we can likely remove the backfilling logic.
selectedWalletBackfilled: boolean selectedWalletBackfilled: boolean
selectedWallet?: Wallet selectedWallet?: ConnectionType
// the timestamp of the last updateVersion action // the timestamp of the last updateVersion action
lastUpdateVersionTimestamp?: number lastUpdateVersionTimestamp?: number
......
import { createSlice } from '@reduxjs/toolkit'
import { Wallet } from 'connectors'
export interface WalletState {
errorByWallet: Record<Wallet, string | undefined>
}
export const initialState: WalletState = {
errorByWallet: {
[Wallet.INJECTED]: undefined,
[Wallet.FORTMATIC]: undefined,
[Wallet.WALLET_CONNECT]: undefined,
[Wallet.COINBASE_WALLET]: undefined,
[Wallet.NETWORK]: undefined,
[Wallet.GNOSIS_SAFE]: undefined,
},
}
const walletSlice = createSlice({
name: 'wallet',
initialState,
reducers: {
updateWalletError(
state,
{ payload: { wallet, error } }: { payload: { wallet: Wallet; error: string | undefined } }
) {
state.errorByWallet[wallet] = error
},
},
})
export const { updateWalletError } = walletSlice.actions
export default walletSlice.reducer
import { Connector } from '@web3-react/types' import { Connector } from '@web3-react/types'
import { coinbaseWallet, fortmatic, gnosisSafe, injected, network, walletConnect } from 'connectors' import {
coinbaseWalletConnection,
fortmaticConnection,
gnosisSafeConnection,
injectedConnection,
networkConnection,
walletConnectConnection,
} from 'connection'
import { CHAIN_INFO } from 'constants/chainInfo' import { CHAIN_INFO } from 'constants/chainInfo'
import { ALL_SUPPORTED_CHAIN_IDS, SupportedChainId } from 'constants/chains' import { ALL_SUPPORTED_CHAIN_IDS, SupportedChainId } from 'constants/chains'
import { INFURA_NETWORK_URLS } from 'constants/infura' import { INFURA_NETWORK_URLS } from 'constants/infura'
...@@ -32,13 +39,13 @@ function getRpcUrls(chainId: SupportedChainId): [string] { ...@@ -32,13 +39,13 @@ function getRpcUrls(chainId: SupportedChainId): [string] {
export function isChainAllowed(connector: Connector, chainId: number) { export function isChainAllowed(connector: Connector, chainId: number) {
switch (connector) { switch (connector) {
case fortmatic: case fortmaticConnection.connector:
return chainId === SupportedChainId.MAINNET return chainId === SupportedChainId.MAINNET
case injected: case injectedConnection.connector:
case coinbaseWallet: case coinbaseWalletConnection.connector:
case walletConnect: case walletConnectConnection.connector:
case network: case networkConnection.connector:
case gnosisSafe: case gnosisSafeConnection.connector:
return ALL_SUPPORTED_CHAIN_IDS.includes(chainId) return ALL_SUPPORTED_CHAIN_IDS.includes(chainId)
default: default:
return false return false
...@@ -48,7 +55,7 @@ export function isChainAllowed(connector: Connector, chainId: number) { ...@@ -48,7 +55,7 @@ export function isChainAllowed(connector: Connector, chainId: number) {
export const switchChain = async (connector: Connector, chainId: number) => { export const switchChain = async (connector: Connector, chainId: number) => {
if (!isChainAllowed(connector, chainId)) { if (!isChainAllowed(connector, chainId)) {
throw new Error(`Chain ${chainId} not supported for connector (${typeof connector})`) throw new Error(`Chain ${chainId} not supported for connector (${typeof connector})`)
} else if (connector === walletConnect || connector === network) { } else if (connector === walletConnectConnection.connector || connector === networkConnection.connector) {
await connector.activate(chainId) await connector.activate(chainId)
} else { } else {
const info = CHAIN_INFO[chainId] const info = CHAIN_INFO[chainId]
......
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