feat(wallet-connect): add support for v2 (#6582)
* feat(wallet-connect): add support for v2 * use theme button to fix opacity issue * fix lint * add new web3-react v2 package * add mainnet to chains list * fix test * yarn dedupe * add new @walletconnect/ethereum-provider * fix safari padding * fix second-click flash on popover toggle * add walletconnect theme * add goerli to non-prod chain selector * remove: debug * remove vertical line * WEB-2107 Fix modal close behavior * remove logging * clean up accountDrawerOpenAtom usage * remove irrelevant comments * remove unintentional whitespace diff * yarn yarn-deduplicate --strategy=highest * add conditional chain selector * update wc package version * goerli -> sepolia * goerli -> sepolia * yarn yarn-deduplicate --strategy=highest * UNIWALLET -> UNISWAP_WALLET * useWalletSupportsChain -> useWalletSupportedChains * use TOGGLE_SIZE * remove inline styles * remove inline styles and use better alt text * update Option.test * use a named function for forwardRef arg * fix types --------- Co-authored-by: Jordan Frankfurt <jordan@CORN-Jordan-949.frankfurt>
This commit is contained in:
parent
0891e67528
commit
5788385951
1
.env
1
.env
@ -11,3 +11,4 @@ REACT_APP_MOONPAY_PUBLISHABLE_KEY="pk_test_DycfESRid31UaSxhI5yWKe1r5E5kKSz"
|
|||||||
REACT_APP_SENTRY_DSN="https://a3c62e400b8748b5a8d007150e2f38b7@o1037921.ingest.sentry.io/4504255148851200"
|
REACT_APP_SENTRY_DSN="https://a3c62e400b8748b5a8d007150e2f38b7@o1037921.ingest.sentry.io/4504255148851200"
|
||||||
REACT_APP_STATSIG_PROXY_URL="https://api.uniswap.org/v1/statsig-proxy"
|
REACT_APP_STATSIG_PROXY_URL="https://api.uniswap.org/v1/statsig-proxy"
|
||||||
REACT_APP_TEMP_API_URL="https://temp.api.uniswap.org/v1"
|
REACT_APP_TEMP_API_URL="https://temp.api.uniswap.org/v1"
|
||||||
|
REACT_APP_WALLET_CONNECT_PROJECT_ID="c6c9bacd35afa3eb9e6cccf6d8464395"
|
@ -186,7 +186,7 @@
|
|||||||
"@visx/react-spring": "^2.12.2",
|
"@visx/react-spring": "^2.12.2",
|
||||||
"@visx/responsive": "^2.10.0",
|
"@visx/responsive": "^2.10.0",
|
||||||
"@visx/shape": "^2.11.1",
|
"@visx/shape": "^2.11.1",
|
||||||
"@walletconnect/ethereum-provider": "^1.8.0",
|
"@walletconnect/ethereum-provider": "^2.7.8",
|
||||||
"@web3-react/coinbase-wallet": "^8.2.0",
|
"@web3-react/coinbase-wallet": "^8.2.0",
|
||||||
"@web3-react/core": "^8.2.0",
|
"@web3-react/core": "^8.2.0",
|
||||||
"@web3-react/eip1193": "^8.2.0",
|
"@web3-react/eip1193": "^8.2.0",
|
||||||
@ -197,6 +197,7 @@
|
|||||||
"@web3-react/types": "^8.2.0",
|
"@web3-react/types": "^8.2.0",
|
||||||
"@web3-react/url": "^8.2.0",
|
"@web3-react/url": "^8.2.0",
|
||||||
"@web3-react/walletconnect": "^8.2.0",
|
"@web3-react/walletconnect": "^8.2.0",
|
||||||
|
"@web3-react/walletconnect-v2": "^8.3.1",
|
||||||
"ajv": "^8.11.0",
|
"ajv": "^8.11.0",
|
||||||
"ajv-formats": "^2.1.1",
|
"ajv-formats": "^2.1.1",
|
||||||
"array.prototype.flat": "^1.2.4",
|
"array.prototype.flat": "^1.2.4",
|
||||||
|
@ -44,7 +44,7 @@ export default function UniwalletModal() {
|
|||||||
// Displays the modal if a Uniswap Wallet Connection is pending & qrcode URI is available
|
// Displays the modal if a Uniswap Wallet Connection is pending & qrcode URI is available
|
||||||
const open =
|
const open =
|
||||||
activationState.status === ActivationStatus.PENDING &&
|
activationState.status === ActivationStatus.PENDING &&
|
||||||
activationState.connection.type === ConnectionType.UNIWALLET &&
|
activationState.connection.type === ConnectionType.UNISWAP_WALLET &&
|
||||||
!!uri
|
!!uri
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { darken } from 'polished'
|
import { darken } from 'polished'
|
||||||
|
import { forwardRef } from 'react'
|
||||||
import { Check, ChevronDown } from 'react-feather'
|
import { Check, ChevronDown } from 'react-feather'
|
||||||
import { Button as RebassButton, ButtonProps as ButtonPropsOriginal } from 'rebass/styled-components'
|
import { Button as RebassButton, ButtonProps as ButtonPropsOriginal } from 'rebass/styled-components'
|
||||||
import styled, { DefaultTheme, useTheme } from 'styled-components/macro'
|
import styled, { DefaultTheme, useTheme } from 'styled-components/macro'
|
||||||
@ -524,15 +525,19 @@ const BaseThemeButton = styled.button<BaseThemeButtonProps>`
|
|||||||
`
|
`
|
||||||
|
|
||||||
interface ThemeButtonProps extends React.ComponentPropsWithoutRef<'button'>, BaseThemeButtonProps {}
|
interface ThemeButtonProps extends React.ComponentPropsWithoutRef<'button'>, BaseThemeButtonProps {}
|
||||||
|
type ThemeButtonRef = HTMLButtonElement
|
||||||
|
|
||||||
export const ThemeButton = ({ children, ...rest }: ThemeButtonProps) => {
|
export const ThemeButton = forwardRef<ThemeButtonRef, ThemeButtonProps>(function ThemeButton(
|
||||||
|
{ children, ...rest },
|
||||||
|
ref
|
||||||
|
) {
|
||||||
return (
|
return (
|
||||||
<BaseThemeButton {...rest}>
|
<BaseThemeButton {...rest} ref={ref}>
|
||||||
<ButtonOverlay />
|
<ButtonOverlay />
|
||||||
{children}
|
{children}
|
||||||
</BaseThemeButton>
|
</BaseThemeButton>
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
|
|
||||||
export const ButtonLight = ({ children, ...rest }: BaseButtonProps) => {
|
export const ButtonLight = ({ children, ...rest }: BaseButtonProps) => {
|
||||||
return (
|
return (
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { t } from '@lingui/macro'
|
import { t } from '@lingui/macro'
|
||||||
import { useWeb3React } from '@web3-react/core'
|
import { useWeb3React } from '@web3-react/core'
|
||||||
|
import { WalletConnect } from '@web3-react/walletconnect-v2'
|
||||||
import { MouseoverTooltip } from 'components/Tooltip'
|
import { MouseoverTooltip } from 'components/Tooltip'
|
||||||
import { useGetConnection } from 'connection'
|
import { useGetConnection } from 'connection'
|
||||||
import { ConnectionType } from 'connection/types'
|
import { ConnectionType } from 'connection/types'
|
||||||
@ -15,6 +16,7 @@ import { useIsMobile } from 'nft/hooks'
|
|||||||
import { useCallback, useRef, useState } from 'react'
|
import { useCallback, useRef, useState } from 'react'
|
||||||
import { AlertTriangle, ChevronDown, ChevronUp } from 'react-feather'
|
import { AlertTriangle, ChevronDown, ChevronUp } from 'react-feather'
|
||||||
import { useTheme } from 'styled-components/macro'
|
import { useTheme } from 'styled-components/macro'
|
||||||
|
import { isProductionEnv } from 'utils/env'
|
||||||
|
|
||||||
import * as styles from './ChainSelector.css'
|
import * as styles from './ChainSelector.css'
|
||||||
import ChainSelectorRow from './ChainSelectorRow'
|
import ChainSelectorRow from './ChainSelectorRow'
|
||||||
@ -29,12 +31,44 @@ const NETWORK_SELECTOR_CHAINS = [
|
|||||||
SupportedChainId.BNB,
|
SupportedChainId.BNB,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if (!isProductionEnv()) {
|
||||||
|
NETWORK_SELECTOR_CHAINS.push(SupportedChainId.SEPOLIA)
|
||||||
|
}
|
||||||
|
|
||||||
interface ChainSelectorProps {
|
interface ChainSelectorProps {
|
||||||
leftAlign?: boolean
|
leftAlign?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// accounts is an array of strings in the format of "eip155:<chainId>:<address>"
|
||||||
|
function getChainsFromEIP155Accounts(accounts?: string[]): SupportedChainId[] {
|
||||||
|
if (!accounts) return []
|
||||||
|
return accounts
|
||||||
|
.map((account) => {
|
||||||
|
const splitAccount = account.split(':')
|
||||||
|
return splitAccount[1] ? parseInt(splitAccount[1]) : undefined
|
||||||
|
})
|
||||||
|
.filter((x) => x !== undefined) as SupportedChainId[]
|
||||||
|
}
|
||||||
|
|
||||||
|
function useWalletSupportedChains() {
|
||||||
|
const { connector } = useWeb3React()
|
||||||
|
|
||||||
|
const getConnection = useGetConnection()
|
||||||
|
|
||||||
|
const connectionType = getConnection(connector).type
|
||||||
|
|
||||||
|
switch (connectionType) {
|
||||||
|
case ConnectionType.WALLET_CONNECT_V2:
|
||||||
|
return getChainsFromEIP155Accounts((connector as WalletConnect).provider?.session?.namespaces.eip155.accounts)
|
||||||
|
case ConnectionType.UNISWAP_WALLET:
|
||||||
|
return UniWalletSupportedChains
|
||||||
|
default:
|
||||||
|
return NETWORK_SELECTOR_CHAINS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const ChainSelector = ({ leftAlign }: ChainSelectorProps) => {
|
export const ChainSelector = ({ leftAlign }: ChainSelectorProps) => {
|
||||||
const { chainId, connector } = useWeb3React()
|
const { chainId } = useWeb3React()
|
||||||
const [isOpen, setIsOpen] = useState<boolean>(false)
|
const [isOpen, setIsOpen] = useState<boolean>(false)
|
||||||
const isMobile = useIsMobile()
|
const isMobile = useIsMobile()
|
||||||
|
|
||||||
@ -61,9 +95,7 @@ export const ChainSelector = ({ leftAlign }: ChainSelectorProps) => {
|
|||||||
[selectChain, setIsOpen]
|
[selectChain, setIsOpen]
|
||||||
)
|
)
|
||||||
|
|
||||||
const getConnection = useGetConnection()
|
const walletSupportsChain = useWalletSupportedChains()
|
||||||
const connectionType = getConnection(connector).type
|
|
||||||
const isUniWallet = connectionType === ConnectionType.UNIWALLET
|
|
||||||
|
|
||||||
if (!chainId) {
|
if (!chainId) {
|
||||||
return null
|
return null
|
||||||
@ -74,13 +106,13 @@ export const ChainSelector = ({ leftAlign }: ChainSelectorProps) => {
|
|||||||
const dropdown = (
|
const dropdown = (
|
||||||
<NavDropdown top="56" left={leftAlign ? '0' : 'auto'} right={leftAlign ? 'auto' : '0'} ref={modalRef}>
|
<NavDropdown top="56" left={leftAlign ? '0' : 'auto'} right={leftAlign ? 'auto' : '0'} ref={modalRef}>
|
||||||
<Column paddingX="8">
|
<Column paddingX="8">
|
||||||
{NETWORK_SELECTOR_CHAINS.map((chainId: SupportedChainId) => (
|
{NETWORK_SELECTOR_CHAINS.map((selectorChain: SupportedChainId) => (
|
||||||
<ChainSelectorRow
|
<ChainSelectorRow
|
||||||
disabled={isUniWallet && !UniWalletSupportedChains.includes(chainId)}
|
disabled={!walletSupportsChain.includes(selectorChain)}
|
||||||
onSelectChain={onSelectChain}
|
onSelectChain={onSelectChain}
|
||||||
targetChain={chainId}
|
targetChain={selectorChain}
|
||||||
key={chainId}
|
key={selectorChain}
|
||||||
isPending={chainId === pendingChainId}
|
isPending={selectorChain === pendingChainId}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</Column>
|
</Column>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Connector } from '@web3-react/types'
|
import { Connector } from '@web3-react/types'
|
||||||
import UNIWALLET_ICON from 'assets/images/uniwallet.png'
|
import UNIWALLET_ICON from 'assets/images/uniwallet.png'
|
||||||
import { useCloseAccountDrawer } from 'components/AccountDrawer'
|
import { useAccountDrawer } from 'components/AccountDrawer'
|
||||||
import { Connection, ConnectionType } from 'connection/types'
|
import { Connection, ConnectionType } from 'connection/types'
|
||||||
import { mocked } from 'test-utils/mocked'
|
import { mocked } from 'test-utils/mocked'
|
||||||
import { createDeferredPromise } from 'test-utils/promise'
|
import { createDeferredPromise } from 'test-utils/promise'
|
||||||
@ -8,12 +8,12 @@ import { act, render } from 'test-utils/render'
|
|||||||
|
|
||||||
import Option from './Option'
|
import Option from './Option'
|
||||||
|
|
||||||
const mockCloseDrawer = jest.fn()
|
const mockToggleDrawer = jest.fn()
|
||||||
jest.mock('components/AccountDrawer')
|
jest.mock('components/AccountDrawer')
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.spyOn(console, 'debug').mockReturnValue()
|
jest.spyOn(console, 'debug').mockReturnValue()
|
||||||
mocked(useCloseAccountDrawer).mockReturnValue(mockCloseDrawer)
|
mocked(useAccountDrawer).mockReturnValue([true, mockToggleDrawer])
|
||||||
})
|
})
|
||||||
|
|
||||||
const mockConnection1: Connection = {
|
const mockConnection1: Connection = {
|
||||||
@ -23,7 +23,7 @@ const mockConnection1: Connection = {
|
|||||||
deactivate: jest.fn(),
|
deactivate: jest.fn(),
|
||||||
} as unknown as Connector,
|
} as unknown as Connector,
|
||||||
getIcon: () => UNIWALLET_ICON,
|
getIcon: () => UNIWALLET_ICON,
|
||||||
type: ConnectionType.UNIWALLET,
|
type: ConnectionType.UNISWAP_WALLET,
|
||||||
} as unknown as Connection
|
} as unknown as Connection
|
||||||
|
|
||||||
const mockConnection2: Connection = {
|
const mockConnection2: Connection = {
|
||||||
@ -39,7 +39,7 @@ const mockConnection2: Connection = {
|
|||||||
describe('Wallet Option', () => {
|
describe('Wallet Option', () => {
|
||||||
it('renders default state', () => {
|
it('renders default state', () => {
|
||||||
const component = render(<Option connection={mockConnection1} />)
|
const component = render(<Option connection={mockConnection1} />)
|
||||||
const option = component.getByTestId('wallet-option-UNIWALLET')
|
const option = component.getByTestId('wallet-option-UNISWAP_WALLET')
|
||||||
expect(option).toBeEnabled()
|
expect(option).toBeEnabled()
|
||||||
expect(option).toHaveProperty('selected', false)
|
expect(option).toHaveProperty('selected', false)
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ describe('Wallet Option', () => {
|
|||||||
<Option connection={mockConnection2} />
|
<Option connection={mockConnection2} />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
const option1 = component.getByTestId('wallet-option-UNIWALLET')
|
const option1 = component.getByTestId('wallet-option-UNISWAP_WALLET')
|
||||||
const option2 = component.getByTestId('wallet-option-INJECTED')
|
const option2 = component.getByTestId('wallet-option-INJECTED')
|
||||||
|
|
||||||
expect(option1).toBeEnabled()
|
expect(option1).toBeEnabled()
|
||||||
@ -71,12 +71,8 @@ describe('Wallet Option', () => {
|
|||||||
expect(option2).toBeDisabled()
|
expect(option2).toBeDisabled()
|
||||||
expect(option2).toHaveProperty('selected', false)
|
expect(option2).toHaveProperty('selected', false)
|
||||||
|
|
||||||
expect(mockCloseDrawer).toHaveBeenCalledTimes(0)
|
|
||||||
|
|
||||||
await act(async () => activationResponse.resolve())
|
await act(async () => activationResponse.resolve())
|
||||||
|
|
||||||
expect(mockCloseDrawer).toHaveBeenCalledTimes(1)
|
|
||||||
|
|
||||||
expect(option1).toBeEnabled()
|
expect(option1).toBeEnabled()
|
||||||
expect(option1).toHaveProperty('selected', false)
|
expect(option1).toHaveProperty('selected', false)
|
||||||
expect(option2).toBeEnabled()
|
expect(option2).toBeEnabled()
|
||||||
|
@ -1,12 +1,19 @@
|
|||||||
import { TraceEvent } from '@uniswap/analytics'
|
import { TraceEvent } from '@uniswap/analytics'
|
||||||
import { BrowserEvent, InterfaceElementName, InterfaceEventName } from '@uniswap/analytics-events'
|
import { BrowserEvent, InterfaceElementName, InterfaceEventName } from '@uniswap/analytics-events'
|
||||||
import { useCloseAccountDrawer } from 'components/AccountDrawer'
|
import { useAccountDrawer } from 'components/AccountDrawer'
|
||||||
|
import { ButtonEmphasis, ButtonSize, ThemeButton } from 'components/Button'
|
||||||
import Loader from 'components/Icons/LoadingSpinner'
|
import Loader from 'components/Icons/LoadingSpinner'
|
||||||
|
import { walletConnectV2Connection } from 'connection'
|
||||||
import { ActivationStatus, useActivationState } from 'connection/activate'
|
import { ActivationStatus, useActivationState } from 'connection/activate'
|
||||||
import { Connection } from 'connection/types'
|
import { Connection, ConnectionType } from 'connection/types'
|
||||||
|
import { useOnClickOutside } from 'hooks/useOnClickOutside'
|
||||||
|
import { MouseEvent, useEffect, useRef, useState } from 'react'
|
||||||
|
import { MoreHorizontal } from 'react-feather'
|
||||||
import styled from 'styled-components/macro'
|
import styled from 'styled-components/macro'
|
||||||
|
import { ThemedText } from 'theme'
|
||||||
import { useIsDarkMode } from 'theme/components/ThemeToggle'
|
import { useIsDarkMode } from 'theme/components/ThemeToggle'
|
||||||
import { flexColumnNoWrap, flexRowNoWrap } from 'theme/styles'
|
import { flexColumnNoWrap, flexRowNoWrap } from 'theme/styles'
|
||||||
|
import { Z_INDEX } from 'theme/zIndex'
|
||||||
|
|
||||||
import NewBadge from './NewBadge'
|
import NewBadge from './NewBadge'
|
||||||
|
|
||||||
@ -17,26 +24,17 @@ const OptionCardLeft = styled.div`
|
|||||||
`
|
`
|
||||||
|
|
||||||
const OptionCardClickable = styled.button<{ selected: boolean }>`
|
const OptionCardClickable = styled.button<{ selected: boolean }>`
|
||||||
background-color: ${({ theme }) => theme.backgroundModule};
|
|
||||||
border: none;
|
|
||||||
width: 100% !important;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
background-color: unset;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 18px;
|
|
||||||
|
|
||||||
transition: ${({ theme }) => theme.transition.duration.fast};
|
|
||||||
opacity: ${({ disabled, selected }) => (disabled && !selected ? '0.5' : '1')};
|
opacity: ${({ disabled, selected }) => (disabled && !selected ? '0.5' : '1')};
|
||||||
|
padding: 18px;
|
||||||
&:hover {
|
transition: ${({ theme }) => theme.transition.duration.fast};
|
||||||
cursor: ${({ disabled }) => !disabled && 'pointer'};
|
|
||||||
background-color: ${({ theme, disabled }) => !disabled && theme.hoverState};
|
|
||||||
}
|
|
||||||
&:focus {
|
|
||||||
background-color: ${({ theme, disabled }) => !disabled && theme.hoverState};
|
|
||||||
}
|
|
||||||
`
|
`
|
||||||
|
|
||||||
const HeaderText = styled.div`
|
const HeaderText = styled.div`
|
||||||
@ -48,7 +46,6 @@ const HeaderText = styled.div`
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
`
|
`
|
||||||
|
|
||||||
const IconWrapper = styled.div`
|
const IconWrapper = styled.div`
|
||||||
${flexColumnNoWrap};
|
${flexColumnNoWrap};
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@ -62,38 +59,164 @@ const IconWrapper = styled.div`
|
|||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
`};
|
`};
|
||||||
`
|
`
|
||||||
|
const WCv2PopoverContent = styled(ThemeButton)`
|
||||||
|
background: ${({ theme }) => theme.backgroundSurface};
|
||||||
|
border: 1px solid ${({ theme }) => theme.backgroundOutline};
|
||||||
|
border-radius: 12px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
max-width: 240px;
|
||||||
|
padding: 16px;
|
||||||
|
position: absolute;
|
||||||
|
right: 12px;
|
||||||
|
top: 52px;
|
||||||
|
z-index: ${Z_INDEX.popover};
|
||||||
|
`
|
||||||
|
const TOGGLE_SIZE = 24
|
||||||
|
const WCv2PopoverToggle = styled.button`
|
||||||
|
align-items: center;
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
color: ${({ theme }) => theme.textTertiary};
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
height: ${TOGGLE_SIZE}px;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 0;
|
||||||
|
max-width: 48px;
|
||||||
|
padding: 0;
|
||||||
|
position: absolute;
|
||||||
|
right: 16px;
|
||||||
|
top: calc(50% - ${TOGGLE_SIZE / 2}px);
|
||||||
|
width: ${TOGGLE_SIZE}px;
|
||||||
|
|
||||||
export default function Option({ connection }: { connection: Connection }) {
|
&:hover {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
const Wrapper = styled.div<{ disabled: boolean }>`
|
||||||
|
align-items: stretch;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: space-between;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
background-color: ${({ theme }) => theme.backgroundModule};
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: ${({ disabled }) => !disabled && 'pointer'};
|
||||||
|
background-color: ${({ theme, disabled }) => !disabled && theme.hoverState};
|
||||||
|
}
|
||||||
|
&:focus {
|
||||||
|
background-color: ${({ theme, disabled }) => !disabled && theme.hoverState};
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const WCv2Icon = styled.img`
|
||||||
|
height: 20px !important;
|
||||||
|
width: 20px !important;
|
||||||
|
`
|
||||||
|
const WCv2BodyText = styled(ThemedText.BodyPrimary)`
|
||||||
|
margin-bottom: 4px;
|
||||||
|
text-align: left;
|
||||||
|
`
|
||||||
|
const WCv2Caption = styled(ThemedText.Caption)`
|
||||||
|
text-align: left;
|
||||||
|
`
|
||||||
|
|
||||||
|
interface PopupButtonContentProps {
|
||||||
|
connection: Connection
|
||||||
|
isDarkMode: boolean
|
||||||
|
show: boolean
|
||||||
|
onClick: (e: MouseEvent<HTMLButtonElement>) => void
|
||||||
|
onClose: () => void
|
||||||
|
}
|
||||||
|
function PopupButtonContent({ connection, isDarkMode, show, onClick, onClose }: PopupButtonContentProps) {
|
||||||
|
const popoverElement = useRef<HTMLButtonElement>(null)
|
||||||
|
useOnClickOutside(popoverElement, onClose)
|
||||||
|
if (!show) return null
|
||||||
|
return (
|
||||||
|
<WCv2PopoverContent onClick={onClick} ref={popoverElement} size={ButtonSize.small} emphasis={ButtonEmphasis.medium}>
|
||||||
|
<IconWrapper>
|
||||||
|
<WCv2Icon src={connection.getIcon?.(isDarkMode)} alt={connection.getName()} />
|
||||||
|
</IconWrapper>
|
||||||
|
<div>
|
||||||
|
<WCv2BodyText>Connect with v2</WCv2BodyText>
|
||||||
|
<WCv2Caption color="textSecondary">Under development and unsupported by most wallets</WCv2Caption>
|
||||||
|
</div>
|
||||||
|
</WCv2PopoverContent>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface OptionProps {
|
||||||
|
connection: Connection
|
||||||
|
}
|
||||||
|
export default function Option({ connection }: OptionProps) {
|
||||||
const { activationState, tryActivation } = useActivationState()
|
const { activationState, tryActivation } = useActivationState()
|
||||||
const closeDrawer = useCloseAccountDrawer()
|
const [WC2PromptOpen, setWC2PromptOpen] = useState(false)
|
||||||
const activate = () => tryActivation(connection, closeDrawer)
|
const [accountDrawerOpen, toggleAccountDrawerOpen] = useAccountDrawer()
|
||||||
|
const activate = () => tryActivation(connection, toggleAccountDrawerOpen)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!accountDrawerOpen) setWC2PromptOpen(false)
|
||||||
|
}, [accountDrawerOpen])
|
||||||
|
|
||||||
const isSomeOptionPending = activationState.status === ActivationStatus.PENDING
|
const isSomeOptionPending = activationState.status === ActivationStatus.PENDING
|
||||||
const isCurrentOptionPending = isSomeOptionPending && activationState.connection.type === connection.type
|
const isCurrentOptionPending = isSomeOptionPending && activationState.connection.type === connection.type
|
||||||
const isDarkMode = useIsDarkMode()
|
const isDarkMode = useIsDarkMode()
|
||||||
|
|
||||||
|
const handleClickConnectViaWCv2 = (e: MouseEvent<HTMLButtonElement>) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
tryActivation(walletConnectV2Connection, () => {
|
||||||
|
setWC2PromptOpen(false)
|
||||||
|
toggleAccountDrawerOpen()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
const handleClickOpenWCv2Tooltip = (e: MouseEvent<HTMLButtonElement>) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
setWC2PromptOpen(true)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TraceEvent
|
<Wrapper disabled={isSomeOptionPending}>
|
||||||
events={[BrowserEvent.onClick]}
|
<TraceEvent
|
||||||
name={InterfaceEventName.WALLET_SELECTED}
|
events={[BrowserEvent.onClick]}
|
||||||
properties={{ wallet_type: connection.getName() }}
|
name={InterfaceEventName.WALLET_SELECTED}
|
||||||
element={InterfaceElementName.WALLET_TYPE_OPTION}
|
properties={{ wallet_type: connection.getName() }}
|
||||||
>
|
element={InterfaceElementName.WALLET_TYPE_OPTION}
|
||||||
<OptionCardClickable
|
|
||||||
onClick={activate}
|
|
||||||
disabled={isSomeOptionPending}
|
|
||||||
selected={isCurrentOptionPending}
|
|
||||||
data-testid={`wallet-option-${connection.type}`}
|
|
||||||
>
|
>
|
||||||
<OptionCardLeft>
|
<OptionCardClickable
|
||||||
<IconWrapper>
|
disabled={isSomeOptionPending}
|
||||||
<img src={connection.getIcon?.(isDarkMode)} alt="Icon" />
|
onClick={activate}
|
||||||
</IconWrapper>
|
selected={isCurrentOptionPending}
|
||||||
<HeaderText>{connection.getName()}</HeaderText>
|
data-testid={`wallet-option-${connection.type}`}
|
||||||
{connection.isNew && <NewBadge />}
|
>
|
||||||
</OptionCardLeft>
|
<OptionCardLeft>
|
||||||
{isCurrentOptionPending && <Loader />}
|
<IconWrapper>
|
||||||
</OptionCardClickable>
|
<img src={connection.getIcon?.(isDarkMode)} alt={connection.getName()} />
|
||||||
</TraceEvent>
|
</IconWrapper>
|
||||||
|
<HeaderText>{connection.getName()}</HeaderText>
|
||||||
|
{connection.isNew && <NewBadge />}
|
||||||
|
</OptionCardLeft>
|
||||||
|
{isCurrentOptionPending && <Loader />}
|
||||||
|
</OptionCardClickable>
|
||||||
|
</TraceEvent>
|
||||||
|
|
||||||
|
{connection.type === ConnectionType.WALLET_CONNECT && (
|
||||||
|
<>
|
||||||
|
<WCv2PopoverToggle onClick={handleClickOpenWCv2Tooltip} onMouseDown={handleClickOpenWCv2Tooltip}>
|
||||||
|
<MoreHorizontal />
|
||||||
|
</WCv2PopoverToggle>
|
||||||
|
<PopupButtonContent
|
||||||
|
connection={connection}
|
||||||
|
isDarkMode={isDarkMode}
|
||||||
|
show={WC2PromptOpen}
|
||||||
|
onClick={handleClickConnectViaWCv2}
|
||||||
|
onClose={() => setWC2PromptOpen(false)}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Wrapper>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -19,37 +19,31 @@ exports[`Wallet Option renders default state 1`] = `
|
|||||||
}
|
}
|
||||||
|
|
||||||
.c0 {
|
.c0 {
|
||||||
background-color: #F5F6FC;
|
|
||||||
border: none;
|
|
||||||
width: 100% !important;
|
|
||||||
display: -webkit-box;
|
|
||||||
display: -webkit-flex;
|
|
||||||
display: -ms-flexbox;
|
|
||||||
display: flex;
|
|
||||||
-webkit-flex-direction: row;
|
|
||||||
-ms-flex-direction: row;
|
|
||||||
flex-direction: row;
|
|
||||||
-webkit-align-items: center;
|
-webkit-align-items: center;
|
||||||
-webkit-box-align: center;
|
-webkit-box-align: center;
|
||||||
-ms-flex-align: center;
|
-ms-flex-align: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
background-color: unset;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
display: -webkit-box;
|
||||||
|
display: -webkit-flex;
|
||||||
|
display: -ms-flexbox;
|
||||||
|
display: flex;
|
||||||
|
-webkit-flex: 1 1 auto;
|
||||||
|
-ms-flex: 1 1 auto;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
-webkit-flex-direction: row;
|
||||||
|
-ms-flex-direction: row;
|
||||||
|
flex-direction: row;
|
||||||
-webkit-box-pack: justify;
|
-webkit-box-pack: justify;
|
||||||
-webkit-justify-content: space-between;
|
-webkit-justify-content: space-between;
|
||||||
-ms-flex-pack: justify;
|
-ms-flex-pack: justify;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
opacity: 1;
|
||||||
padding: 18px;
|
padding: 18px;
|
||||||
-webkit-transition: 125ms;
|
-webkit-transition: 125ms;
|
||||||
transition: 125ms;
|
transition: 125ms;
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c0:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
background-color: #ADBCFF3d;
|
|
||||||
}
|
|
||||||
|
|
||||||
.c0:focus {
|
|
||||||
background-color: #ADBCFF3d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.c3 {
|
.c3 {
|
||||||
@ -109,7 +103,7 @@ exports[`Wallet Option renders default state 1`] = `
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
class="c0"
|
class="c0"
|
||||||
data-testid="wallet-option-UNIWALLET"
|
data-testid="wallet-option-UNISWAP_WALLET"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="c1"
|
class="c1"
|
||||||
@ -118,7 +112,7 @@ exports[`Wallet Option renders default state 1`] = `
|
|||||||
class="c2"
|
class="c2"
|
||||||
>
|
>
|
||||||
<img
|
<img
|
||||||
alt="Icon"
|
alt="Mock Connection 1"
|
||||||
src="uniwallet.png"
|
src="uniwallet.png"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
50
src/connection/WalletConnectV2.ts
Normal file
50
src/connection/WalletConnectV2.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import { sendAnalyticsEvent } from '@uniswap/analytics'
|
||||||
|
import { WalletConnect, WalletConnectConstructorArgs } from '@web3-react/walletconnect-v2'
|
||||||
|
import { SupportedChainId } from 'constants/chains'
|
||||||
|
import { Z_INDEX } from 'theme/zIndex'
|
||||||
|
|
||||||
|
import { RPC_URLS } from '../constants/networks'
|
||||||
|
|
||||||
|
// Avoid testing for the best URL by only passing a single URL per chain.
|
||||||
|
// Otherwise, WC will not initialize until all URLs have been tested (see getBestUrl in web3-react).
|
||||||
|
const RPC_URLS_WITHOUT_FALLBACKS = Object.entries(RPC_URLS).reduce(
|
||||||
|
(map, [chainId, urls]) => ({
|
||||||
|
...map,
|
||||||
|
[chainId]: urls[0],
|
||||||
|
}),
|
||||||
|
{}
|
||||||
|
)
|
||||||
|
|
||||||
|
export class WalletConnectV2Popup extends WalletConnect {
|
||||||
|
ANALYTICS_EVENT = 'Wallet Connect QR Scan'
|
||||||
|
constructor({
|
||||||
|
actions,
|
||||||
|
onError,
|
||||||
|
qrcode = true,
|
||||||
|
}: Omit<WalletConnectConstructorArgs, 'options'> & { qrcode?: boolean }) {
|
||||||
|
const darkmode = Boolean(window.matchMedia('(prefers-color-scheme: dark)'))
|
||||||
|
super({
|
||||||
|
actions,
|
||||||
|
options: {
|
||||||
|
projectId: process.env.REACT_APP_WALLET_CONNECT_PROJECT_ID as string,
|
||||||
|
optionalChains: Object.keys(RPC_URLS_WITHOUT_FALLBACKS).map((key) => Number(key)),
|
||||||
|
chains: [SupportedChainId.MAINNET],
|
||||||
|
showQrModal: qrcode,
|
||||||
|
rpcMap: RPC_URLS_WITHOUT_FALLBACKS,
|
||||||
|
qrModalOptions: {
|
||||||
|
themeMode: darkmode ? 'dark' : 'light',
|
||||||
|
themeVariables: {
|
||||||
|
'--w3m-font-family': '"Inter custom", sans-serif',
|
||||||
|
'--w3m-z-index': Z_INDEX.modal.toString(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
onError,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
activate(chainId?: number) {
|
||||||
|
sendAnalyticsEvent(this.ANALYTICS_EVENT)
|
||||||
|
return super.activate(chainId)
|
||||||
|
}
|
||||||
|
}
|
@ -19,7 +19,7 @@ describe('connection utility/metadata tests', () => {
|
|||||||
const getConnection = renderHook(() => useGetConnection()).result.current
|
const getConnection = renderHook(() => useGetConnection()).result.current
|
||||||
const injected = getConnection(ConnectionType.INJECTED)
|
const injected = getConnection(ConnectionType.INJECTED)
|
||||||
const coinbase = getConnection(ConnectionType.COINBASE_WALLET)
|
const coinbase = getConnection(ConnectionType.COINBASE_WALLET)
|
||||||
const uniswap = getConnection(ConnectionType.UNIWALLET)
|
const uniswap = getConnection(ConnectionType.UNISWAP_WALLET)
|
||||||
const walletconnect = getConnection(ConnectionType.WALLET_CONNECT)
|
const walletconnect = getConnection(ConnectionType.WALLET_CONNECT)
|
||||||
|
|
||||||
return { displayed, injected, coinbase, uniswap, walletconnect }
|
return { displayed, injected, coinbase, uniswap, walletconnect }
|
||||||
|
@ -21,6 +21,7 @@ import { RPC_PROVIDERS } from '../constants/providers'
|
|||||||
import { Connection, ConnectionType } from './types'
|
import { Connection, ConnectionType } from './types'
|
||||||
import { getIsCoinbaseWallet, getIsInjected, getIsMetaMaskWallet } from './utils'
|
import { getIsCoinbaseWallet, getIsInjected, getIsMetaMaskWallet } from './utils'
|
||||||
import { UniwalletConnect, WalletConnectPopup } from './WalletConnect'
|
import { UniwalletConnect, WalletConnectPopup } from './WalletConnect'
|
||||||
|
import { WalletConnectV2Popup } from './WalletConnectV2'
|
||||||
|
|
||||||
function onError(error: Error) {
|
function onError(error: Error) {
|
||||||
console.debug(`web3-react error: ${error}`)
|
console.debug(`web3-react error: ${error}`)
|
||||||
@ -87,6 +88,18 @@ export const walletConnectConnection: Connection = {
|
|||||||
shouldDisplay: () => !getIsInjectedMobileBrowser(),
|
shouldDisplay: () => !getIsInjectedMobileBrowser(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const [web3WalletConnectV2, web3WalletConnectV2Hooks] = initializeConnector<WalletConnectV2Popup>(
|
||||||
|
(actions) => new WalletConnectV2Popup({ actions, onError })
|
||||||
|
)
|
||||||
|
export const walletConnectV2Connection: Connection = {
|
||||||
|
getName: () => 'WalletConnectV2',
|
||||||
|
connector: web3WalletConnectV2,
|
||||||
|
hooks: web3WalletConnectV2Hooks,
|
||||||
|
type: ConnectionType.WALLET_CONNECT_V2,
|
||||||
|
getIcon: () => WALLET_CONNECT_ICON,
|
||||||
|
shouldDisplay: () => false,
|
||||||
|
}
|
||||||
|
|
||||||
const [web3UniwalletConnect, web3UniwalletConnectHooks] = initializeConnector<UniwalletConnect>(
|
const [web3UniwalletConnect, web3UniwalletConnectHooks] = initializeConnector<UniwalletConnect>(
|
||||||
(actions) => new UniwalletConnect({ actions, onError })
|
(actions) => new UniwalletConnect({ actions, onError })
|
||||||
)
|
)
|
||||||
@ -94,7 +107,7 @@ export const uniwalletConnectConnection: Connection = {
|
|||||||
getName: () => 'Uniswap Wallet',
|
getName: () => 'Uniswap Wallet',
|
||||||
connector: web3UniwalletConnect,
|
connector: web3UniwalletConnect,
|
||||||
hooks: web3UniwalletConnectHooks,
|
hooks: web3UniwalletConnectHooks,
|
||||||
type: ConnectionType.UNIWALLET,
|
type: ConnectionType.UNISWAP_WALLET,
|
||||||
getIcon: () => UNIWALLET_ICON,
|
getIcon: () => UNIWALLET_ICON,
|
||||||
shouldDisplay: () => Boolean(!getIsInjectedMobileBrowser() && !isNonIOSPhone),
|
shouldDisplay: () => Boolean(!getIsInjectedMobileBrowser() && !isNonIOSPhone),
|
||||||
isNew: true,
|
isNew: true,
|
||||||
@ -137,6 +150,7 @@ export function getConnections() {
|
|||||||
uniwalletConnectConnection,
|
uniwalletConnectConnection,
|
||||||
injectedConnection,
|
injectedConnection,
|
||||||
walletConnectConnection,
|
walletConnectConnection,
|
||||||
|
walletConnectV2Connection,
|
||||||
coinbaseWalletConnection,
|
coinbaseWalletConnection,
|
||||||
gnosisSafeConnection,
|
gnosisSafeConnection,
|
||||||
networkConnection,
|
networkConnection,
|
||||||
@ -159,7 +173,9 @@ export function useGetConnection() {
|
|||||||
return coinbaseWalletConnection
|
return coinbaseWalletConnection
|
||||||
case ConnectionType.WALLET_CONNECT:
|
case ConnectionType.WALLET_CONNECT:
|
||||||
return walletConnectConnection
|
return walletConnectConnection
|
||||||
case ConnectionType.UNIWALLET:
|
case ConnectionType.WALLET_CONNECT_V2:
|
||||||
|
return walletConnectV2Connection
|
||||||
|
case ConnectionType.UNISWAP_WALLET:
|
||||||
return uniwalletConnectConnection
|
return uniwalletConnectConnection
|
||||||
case ConnectionType.NETWORK:
|
case ConnectionType.NETWORK:
|
||||||
return networkConnection
|
return networkConnection
|
||||||
|
@ -2,10 +2,11 @@ import { Web3ReactHooks } from '@web3-react/core'
|
|||||||
import { Connector } from '@web3-react/types'
|
import { Connector } from '@web3-react/types'
|
||||||
|
|
||||||
export enum ConnectionType {
|
export enum ConnectionType {
|
||||||
UNIWALLET = 'UNIWALLET',
|
UNISWAP_WALLET = 'UNISWAP_WALLET',
|
||||||
INJECTED = 'INJECTED',
|
INJECTED = 'INJECTED',
|
||||||
COINBASE_WALLET = 'COINBASE_WALLET',
|
COINBASE_WALLET = 'COINBASE_WALLET',
|
||||||
WALLET_CONNECT = 'WALLET_CONNECT',
|
WALLET_CONNECT = 'WALLET_CONNECT',
|
||||||
|
WALLET_CONNECT_V2 = 'WALLET_CONNECT_V2',
|
||||||
NETWORK = 'NETWORK',
|
NETWORK = 'NETWORK',
|
||||||
GNOSIS_SAFE = 'GNOSIS_SAFE',
|
GNOSIS_SAFE = 'GNOSIS_SAFE',
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ export enum ErrorCode {
|
|||||||
CHAIN_NOT_ADDED = 4902,
|
CHAIN_NOT_ADDED = 4902,
|
||||||
MM_ALREADY_PENDING = -32002,
|
MM_ALREADY_PENDING = -32002,
|
||||||
|
|
||||||
|
WC_V2_MODAL_CLOSED = 'Error: Connection request reset. Please try again.',
|
||||||
WC_MODAL_CLOSED = 'Error: User closed modal',
|
WC_MODAL_CLOSED = 'Error: User closed modal',
|
||||||
CB_REJECTED_REQUEST = 'Error: User denied account authorization',
|
CB_REJECTED_REQUEST = 'Error: User denied account authorization',
|
||||||
}
|
}
|
||||||
@ -32,6 +33,7 @@ export enum ErrorCode {
|
|||||||
export function didUserReject(connection: Connection, error: any): boolean {
|
export function didUserReject(connection: Connection, error: any): boolean {
|
||||||
return (
|
return (
|
||||||
error?.code === ErrorCode.USER_REJECTED_REQUEST ||
|
error?.code === ErrorCode.USER_REJECTED_REQUEST ||
|
||||||
|
(connection.type === ConnectionType.WALLET_CONNECT_V2 && error?.toString?.() === ErrorCode.WC_V2_MODAL_CLOSED) ||
|
||||||
(connection.type === ConnectionType.WALLET_CONNECT && error?.toString?.() === ErrorCode.WC_MODAL_CLOSED) ||
|
(connection.type === ConnectionType.WALLET_CONNECT && error?.toString?.() === ErrorCode.WC_MODAL_CLOSED) ||
|
||||||
(connection.type === ConnectionType.COINBASE_WALLET && error?.toString?.() === ErrorCode.CB_REJECTED_REQUEST)
|
(connection.type === ConnectionType.COINBASE_WALLET && error?.toString?.() === ErrorCode.CB_REJECTED_REQUEST)
|
||||||
)
|
)
|
||||||
|
@ -123,6 +123,7 @@ export function validateUrlChainParam(chainName: string | undefined) {
|
|||||||
export const CHAIN_NAME_TO_CHAIN_ID: { [key in Chain]: SupportedChainId } = {
|
export const CHAIN_NAME_TO_CHAIN_ID: { [key in Chain]: SupportedChainId } = {
|
||||||
[Chain.Ethereum]: SupportedChainId.MAINNET,
|
[Chain.Ethereum]: SupportedChainId.MAINNET,
|
||||||
[Chain.EthereumGoerli]: SupportedChainId.GOERLI,
|
[Chain.EthereumGoerli]: SupportedChainId.GOERLI,
|
||||||
|
[Chain.EthereumSepolia]: SupportedChainId.SEPOLIA,
|
||||||
[Chain.Polygon]: SupportedChainId.POLYGON,
|
[Chain.Polygon]: SupportedChainId.POLYGON,
|
||||||
[Chain.Celo]: SupportedChainId.CELO,
|
[Chain.Celo]: SupportedChainId.CELO,
|
||||||
[Chain.Optimism]: SupportedChainId.OPTIMISM,
|
[Chain.Optimism]: SupportedChainId.OPTIMISM,
|
||||||
|
@ -4,7 +4,7 @@ import { useMemo } from 'react'
|
|||||||
import { useAppSelector } from 'state/hooks'
|
import { useAppSelector } from 'state/hooks'
|
||||||
|
|
||||||
const SELECTABLE_WALLETS = [
|
const SELECTABLE_WALLETS = [
|
||||||
ConnectionType.UNIWALLET,
|
ConnectionType.UNISWAP_WALLET,
|
||||||
ConnectionType.INJECTED,
|
ConnectionType.INJECTED,
|
||||||
ConnectionType.WALLET_CONNECT,
|
ConnectionType.WALLET_CONNECT,
|
||||||
ConnectionType.COINBASE_WALLET,
|
ConnectionType.COINBASE_WALLET,
|
||||||
|
@ -30,13 +30,11 @@ import { useSwapCallback } from 'hooks/useSwapCallback'
|
|||||||
import { useUSDPrice } from 'hooks/useUSDPrice'
|
import { useUSDPrice } from 'hooks/useUSDPrice'
|
||||||
import JSBI from 'jsbi'
|
import JSBI from 'jsbi'
|
||||||
import { formatSwapQuoteReceivedEventProperties } from 'lib/utils/analytics'
|
import { formatSwapQuoteReceivedEventProperties } from 'lib/utils/analytics'
|
||||||
import { useCallback, useEffect, useMemo, useReducer, useState } from 'react'
|
import { ReactNode, useCallback, useEffect, useMemo, useReducer, useState } from 'react'
|
||||||
import { ReactNode } from 'react'
|
|
||||||
import { ArrowDown } from 'react-feather'
|
import { ArrowDown } from 'react-feather'
|
||||||
import { useNavigate } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import { InterfaceTrade } from 'state/routing/types'
|
import { InterfaceTrade, TradeState } from 'state/routing/types'
|
||||||
import { TradeState } from 'state/routing/types'
|
|
||||||
import styled, { useTheme } from 'styled-components/macro'
|
import styled, { useTheme } from 'styled-components/macro'
|
||||||
import { currencyAmountToPreciseFloat, formatTransactionAmount } from 'utils/formatNumbers'
|
import { currencyAmountToPreciseFloat, formatTransactionAmount } from 'utils/formatNumbers'
|
||||||
import { didUserReject } from 'utils/swapErrorToUserReadableMessage'
|
import { didUserReject } from 'utils/swapErrorToUserReadableMessage'
|
||||||
|
@ -7,9 +7,10 @@ interface ConnectionState {
|
|||||||
|
|
||||||
const initialState: ConnectionState = {
|
const initialState: ConnectionState = {
|
||||||
errorByConnectionType: {
|
errorByConnectionType: {
|
||||||
[ConnectionType.UNIWALLET]: undefined,
|
[ConnectionType.UNISWAP_WALLET]: undefined,
|
||||||
[ConnectionType.INJECTED]: undefined,
|
[ConnectionType.INJECTED]: undefined,
|
||||||
[ConnectionType.WALLET_CONNECT]: undefined,
|
[ConnectionType.WALLET_CONNECT]: undefined,
|
||||||
|
[ConnectionType.WALLET_CONNECT_V2]: undefined,
|
||||||
[ConnectionType.COINBASE_WALLET]: undefined,
|
[ConnectionType.COINBASE_WALLET]: undefined,
|
||||||
[ConnectionType.NETWORK]: undefined,
|
[ConnectionType.NETWORK]: undefined,
|
||||||
[ConnectionType.GNOSIS_SAFE]: undefined,
|
[ConnectionType.GNOSIS_SAFE]: undefined,
|
||||||
|
@ -1,5 +1,10 @@
|
|||||||
import { Connector } from '@web3-react/types'
|
import { Connector } from '@web3-react/types'
|
||||||
import { networkConnection, uniwalletConnectConnection, walletConnectConnection } from 'connection'
|
import {
|
||||||
|
networkConnection,
|
||||||
|
uniwalletConnectConnection,
|
||||||
|
walletConnectConnection,
|
||||||
|
walletConnectV2Connection,
|
||||||
|
} from 'connection'
|
||||||
import { getChainInfo } from 'constants/chainInfo'
|
import { getChainInfo } from 'constants/chainInfo'
|
||||||
import { isSupportedChain, SupportedChainId } from 'constants/chains'
|
import { isSupportedChain, SupportedChainId } from 'constants/chains'
|
||||||
import { FALLBACK_URLS, RPC_URLS } from 'constants/networks'
|
import { FALLBACK_URLS, RPC_URLS } from 'constants/networks'
|
||||||
@ -22,9 +27,12 @@ export const switchChain = async (connector: Connector, chainId: SupportedChainI
|
|||||||
if (!isSupportedChain(chainId)) {
|
if (!isSupportedChain(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 (
|
} else if (
|
||||||
connector === walletConnectConnection.connector ||
|
[
|
||||||
connector === uniwalletConnectConnection.connector ||
|
walletConnectV2Connection.connector,
|
||||||
connector === networkConnection.connector
|
walletConnectConnection.connector,
|
||||||
|
uniwalletConnectConnection.connector,
|
||||||
|
networkConnection.connector,
|
||||||
|
].includes(connector)
|
||||||
) {
|
) {
|
||||||
await connector.activate(chainId)
|
await connector.activate(chainId)
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user