Commit 53caa51a authored by Mike Grabowski's avatar Mike Grabowski Committed by GitHub

fix: disconnection error while switching networks with MetaMask (#5871)

* fix: disconnection error while switching networks with MetaMask

* nit: oops

* fix: tests
parent 409ba72f
import { Trans } from '@lingui/macro'
import { ButtonPrimary } from 'components/Button'
import { AutoColumn } from 'components/Column'
import Modal from 'components/Modal'
import { RowBetween } from 'components/Row'
import { AlertTriangle } from 'react-feather'
import { Text } from 'rebass'
import styled from 'styled-components/macro'
import { CloseIcon, ThemedText } from 'theme'
import { useModalIsOpen, useToggleMetaMaskConnectionErrorModal } from '../../state/application/hooks'
import { ApplicationModal } from '../../state/application/reducer'
const Wrapper = styled.div`
width: 100%;
position: relative;
display: flex;
flex-flow: column;
align-items: center;
`
const Container = styled.div`
width: 100%;
padding: 32px 32px;
display: flex;
flex-flow: column;
align-items: center;
`
const LogoContainer = styled.div`
display: flex;
gap: 16px;
`
const ShortColumn = styled(AutoColumn)`
margin-top: 10px;
`
const InfoText = styled(Text)`
padding: 0 12px 0 12px;
font-size: 14px;
line-height: 20px;
text-align: center;
`
const StyledButton = styled(ButtonPrimary)`
margin-top: 24px;
width: 100%;
font-weight: 600;
`
const WarningIcon = styled(AlertTriangle)`
width: 76px;
height: 76px;
margin-top: 4px;
margin-bottom: 28px;
stroke-width: 1px;
margin-right: 4px;
color: ${({ theme }) => theme.accentCritical};
`
const onReconnect = () => window.location.reload()
export default function MetaMaskConnectionErrorModal() {
const modalOpen = useModalIsOpen(ApplicationModal.METAMASK_CONNECTION_ERROR)
const toggleModal = useToggleMetaMaskConnectionErrorModal()
return (
<Modal isOpen={modalOpen} onDismiss={toggleModal} minHeight={false} maxHeight={90}>
<Wrapper>
<RowBetween style={{ padding: '1rem' }}>
<div />
<CloseIcon onClick={toggleModal} />
</RowBetween>
<Container>
<AutoColumn>
<LogoContainer>
<WarningIcon />
</LogoContainer>
</AutoColumn>
<ShortColumn>
<InfoText>
<ThemedText.HeadlineSmall marginBottom="8px">
<Trans>Wallet disconnected</Trans>
</ThemedText.HeadlineSmall>
<ThemedText.BodySmall>
<Trans>A MetaMask error caused your wallet to disconnect. Reload the page to reconnect.</Trans>
</ThemedText.BodySmall>
</InfoText>
</ShortColumn>
<StyledButton onClick={onReconnect}>
<Trans>Reload</Trans>
</StyledButton>
</Container>
</Wrapper>
</Modal>
)
}
...@@ -12,7 +12,6 @@ import { ApplicationModal } from 'state/application/reducer' ...@@ -12,7 +12,6 @@ import { ApplicationModal } from 'state/application/reducer'
const Bag = lazy(() => import('nft/components/bag/Bag')) const Bag = lazy(() => import('nft/components/bag/Bag'))
const TransactionCompleteModal = lazy(() => import('nft/components/collection/TransactionCompleteModal')) const TransactionCompleteModal = lazy(() => import('nft/components/collection/TransactionCompleteModal'))
const AirdropModal = lazy(() => import('components/AirdropModal')) const AirdropModal = lazy(() => import('components/AirdropModal'))
const MetaMaskConnectionErrorModal = lazy(() => import('components/MetaMaskConnectionErrorModal'))
export default function TopLevelModals() { export default function TopLevelModals() {
const addressClaimOpen = useModalIsOpen(ApplicationModal.ADDRESS_CLAIM) const addressClaimOpen = useModalIsOpen(ApplicationModal.ADDRESS_CLAIM)
...@@ -30,7 +29,6 @@ export default function TopLevelModals() { ...@@ -30,7 +29,6 @@ export default function TopLevelModals() {
<Bag /> <Bag />
<TransactionCompleteModal /> <TransactionCompleteModal />
<AirdropModal /> <AirdropModal />
<MetaMaskConnectionErrorModal />
{fiatOnrampFlagEnabled && <FiatOnrampModal />} {fiatOnrampFlagEnabled && <FiatOnrampModal />}
</> </>
) )
......
...@@ -22,9 +22,6 @@ jest.mock('.../../state/application/hooks', () => { ...@@ -22,9 +22,6 @@ jest.mock('.../../state/application/hooks', () => {
useToggleWalletModal: () => { useToggleWalletModal: () => {
return return
}, },
useToggleMetaMaskConnectionErrorModal: () => {
return
},
} }
}) })
......
import { useWeb3React, Web3ReactHooks, Web3ReactProvider } from '@web3-react/core' import { useWeb3React, Web3ReactHooks, Web3ReactProvider } from '@web3-react/core'
import { Connector } from '@web3-react/types' import { Connector } from '@web3-react/types'
import { Connection } from 'connection' import { Connection } from 'connection'
import { setMetMaskErrorHandler } from 'connection'
import { getConnectionName } from 'connection/utils' import { getConnectionName } from 'connection/utils'
import { isSupportedChain } from 'constants/chains' import { isSupportedChain } from 'constants/chains'
import { RPC_PROVIDERS } from 'constants/providers' import { RPC_PROVIDERS } from 'constants/providers'
...@@ -9,19 +8,8 @@ import { TraceJsonRpcVariant, useTraceJsonRpcFlag } from 'featureFlags/flags/tra ...@@ -9,19 +8,8 @@ import { TraceJsonRpcVariant, useTraceJsonRpcFlag } from 'featureFlags/flags/tra
import useEagerlyConnect from 'hooks/useEagerlyConnect' import useEagerlyConnect from 'hooks/useEagerlyConnect'
import useOrderedConnections from 'hooks/useOrderedConnections' import useOrderedConnections from 'hooks/useOrderedConnections'
import { ReactNode, useEffect, useMemo } from 'react' import { ReactNode, useEffect, useMemo } from 'react'
import { useToggleMetaMaskConnectionErrorModal } from 'state/application/hooks'
export default function Web3Provider({ children }: { children: ReactNode }) { export default function Web3Provider({ children }: { children: ReactNode }) {
// https://github.com/MetaMask/metamask-extension/issues/13375
const toggleMetaMaskConnectionErrorModal = useToggleMetaMaskConnectionErrorModal()
useEffect(() => {
setMetMaskErrorHandler((error) => {
if (error.code === 1013) {
toggleMetaMaskConnectionErrorModal()
}
})
}, [toggleMetaMaskConnectionErrorModal])
useEagerlyConnect() useEagerlyConnect()
const connections = useOrderedConnections() const connections = useOrderedConnections()
const connectors: [Connector, Web3ReactHooks][] = connections.map(({ hooks, connector }) => [connector, hooks]) const connectors: [Connector, Web3ReactHooks][] = connections.map(({ hooks, connector }) => [connector, hooks])
......
...@@ -25,22 +25,10 @@ export interface Connection { ...@@ -25,22 +25,10 @@ export interface Connection {
type: ConnectionType type: ConnectionType
} }
type MetaMaskError = Error & { code: number }
let metaMaskErrorHandler: (error: MetaMaskError) => void | undefined
export function setMetMaskErrorHandler(errorHandler: typeof metaMaskErrorHandler) {
metaMaskErrorHandler = errorHandler
}
function onError(error: Error) { function onError(error: Error) {
console.debug(`web3-react error: ${error}`) console.debug(`web3-react error: ${error}`)
} }
function onMetaMaskError(error: Error) {
onError(error)
metaMaskErrorHandler?.(error as MetaMaskError)
}
const [web3Network, web3NetworkHooks] = initializeConnector<Network>( const [web3Network, web3NetworkHooks] = initializeConnector<Network>(
(actions) => new Network({ actions, urlMap: RPC_PROVIDERS, defaultChainId: 1 }) (actions) => new Network({ actions, urlMap: RPC_PROVIDERS, defaultChainId: 1 })
) )
...@@ -50,9 +38,7 @@ export const networkConnection: Connection = { ...@@ -50,9 +38,7 @@ export const networkConnection: Connection = {
type: ConnectionType.NETWORK, type: ConnectionType.NETWORK,
} }
const [web3Injected, web3InjectedHooks] = initializeConnector<MetaMask>( const [web3Injected, web3InjectedHooks] = initializeConnector<MetaMask>((actions) => new MetaMask({ actions, onError }))
(actions) => new MetaMask({ actions, onError: onMetaMaskError })
)
export const injectedConnection: Connection = { export const injectedConnection: Connection = {
connector: web3Injected, connector: web3Injected,
hooks: web3InjectedHooks, hooks: web3InjectedHooks,
......
...@@ -93,10 +93,6 @@ export function useCloseModal(): () => void { ...@@ -93,10 +93,6 @@ export function useCloseModal(): () => void {
return useCallback(() => dispatch(setOpenModal(null)), [dispatch]) return useCallback(() => dispatch(setOpenModal(null)), [dispatch])
} }
export function useToggleMetaMaskConnectionErrorModal(): () => void {
return useToggleModal(ApplicationModal.METAMASK_CONNECTION_ERROR)
}
export function useOpenModal(modal: ApplicationModal): () => void { export function useOpenModal(modal: ApplicationModal): () => void {
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
return useCallback(() => dispatch(setOpenModal(modal)), [dispatch, modal]) return useCallback(() => dispatch(setOpenModal(modal)), [dispatch, modal])
......
...@@ -5792,6 +5792,14 @@ ...@@ -5792,6 +5792,14 @@
"@metamask/detect-provider" "^1.2.0" "@metamask/detect-provider" "^1.2.0"
"@web3-react/types" "^8.0.20-beta.0" "@web3-react/types" "^8.0.20-beta.0"
"@web3-react/metamask@8.0.29-beta.0":
version "8.0.29-beta.0"
resolved "https://registry.yarnpkg.com/@web3-react/metamask/-/metamask-8.0.29-beta.0.tgz#536536b8d4f22f21d3e109efaa8149939833f21b"
integrity sha512-UPaVmNum6cJ/CwW5WYFMrm6GwiuY1hnuCYB+bV1Bs0xghdag2Laj8/mSfpFCsCHcvg1ZWTcr4bH+WyuYAHgUxw==
dependencies:
"@metamask/detect-provider" "^1.2.0"
"@web3-react/types" "^8.0.20-beta.0"
"@web3-react/network@8.0.27-beta.0": "@web3-react/network@8.0.27-beta.0":
version "8.0.27-beta.0" version "8.0.27-beta.0"
resolved "https://registry.yarnpkg.com/@web3-react/network/-/network-8.0.27-beta.0.tgz#7cb522b02efc9d0f877ac285f350810fbf322292" resolved "https://registry.yarnpkg.com/@web3-react/network/-/network-8.0.27-beta.0.tgz#7cb522b02efc9d0f877ac285f350810fbf322292"
......
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