Commit 3686803c authored by Mike Grabowski's avatar Mike Grabowski Committed by GitHub

refactor: improve metamask error modal (#5818)

* refactor: improve metamask error modal

* chore: rename and use translations

* chore: fix lint

* chore: Fix test
parent 6f147c1f
...@@ -8,7 +8,7 @@ import { Text } from 'rebass' ...@@ -8,7 +8,7 @@ import { Text } from 'rebass'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { CloseIcon, ThemedText } from 'theme' import { CloseIcon, ThemedText } from 'theme'
import { useModalIsOpen, useToggleMetamaskConnectionErrorModal } from '../../state/application/hooks' import { useModalIsOpen, useToggleMetaMaskConnectionErrorModal } from '../../state/application/hooks'
import { ApplicationModal } from '../../state/application/reducer' import { ApplicationModal } from '../../state/application/reducer'
const Wrapper = styled.div` const Wrapper = styled.div`
...@@ -61,12 +61,9 @@ const WarningIcon = styled(AlertTriangle)` ...@@ -61,12 +61,9 @@ const WarningIcon = styled(AlertTriangle)`
const onReconnect = () => window.location.reload() const onReconnect = () => window.location.reload()
const header = 'Wallet disconnected' export default function MetaMaskConnectionErrorModal() {
const description = 'A Metamask error caused your wallet to disconnect. Reload the page to reconnect.'
export default function MetamaskConnectionError() {
const modalOpen = useModalIsOpen(ApplicationModal.METAMASK_CONNECTION_ERROR) const modalOpen = useModalIsOpen(ApplicationModal.METAMASK_CONNECTION_ERROR)
const toggleModal = useToggleMetamaskConnectionErrorModal() const toggleModal = useToggleMetaMaskConnectionErrorModal()
return ( return (
<Modal isOpen={modalOpen} onDismiss={toggleModal} minHeight={false} maxHeight={90}> <Modal isOpen={modalOpen} onDismiss={toggleModal} minHeight={false} maxHeight={90}>
...@@ -83,8 +80,12 @@ export default function MetamaskConnectionError() { ...@@ -83,8 +80,12 @@ export default function MetamaskConnectionError() {
</AutoColumn> </AutoColumn>
<ShortColumn> <ShortColumn>
<InfoText> <InfoText>
<ThemedText.HeadlineSmall marginBottom="8px">{header}</ThemedText.HeadlineSmall> <ThemedText.HeadlineSmall marginBottom="8px">
<ThemedText.BodySmall>{description}</ThemedText.BodySmall> <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> </InfoText>
</ShortColumn> </ShortColumn>
<StyledButton onClick={onReconnect}> <StyledButton onClick={onReconnect}>
......
...@@ -12,6 +12,7 @@ import { ApplicationModal } from 'state/application/reducer' ...@@ -12,6 +12,7 @@ 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)
...@@ -29,6 +30,7 @@ export default function TopLevelModals() { ...@@ -29,6 +30,7 @@ export default function TopLevelModals() {
<Bag /> <Bag />
<TransactionCompleteModal /> <TransactionCompleteModal />
<AirdropModal /> <AirdropModal />
<MetaMaskConnectionErrorModal />
{fiatOnrampFlagEnabled && <FiatOnrampModal />} {fiatOnrampFlagEnabled && <FiatOnrampModal />}
</> </>
) )
......
...@@ -22,6 +22,9 @@ jest.mock('.../../state/application/hooks', () => { ...@@ -22,6 +22,9 @@ 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 { ConnectionType, setMetMaskErrorHandler } 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,18 +9,18 @@ import { TraceJsonRpcVariant, useTraceJsonRpcFlag } from 'featureFlags/flags/tra ...@@ -9,18 +9,18 @@ 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 { updateConnectionError } from 'state/connection/reducer' import { useToggleMetaMaskConnectionErrorModal } from 'state/application/hooks'
import { useAppDispatch } from 'state/hooks'
export default function Web3Provider({ children }: { children: ReactNode }) { export default function Web3Provider({ children }: { children: ReactNode }) {
const dispatch = useAppDispatch() // https://github.com/MetaMask/metamask-extension/issues/13375
const toggleMetaMaskConnectionErrorModal = useToggleMetaMaskConnectionErrorModal()
// Set metamask error handler for metamask disconnection warning modal.
useEffect(() => { useEffect(() => {
setMetMaskErrorHandler((error: Error) => setMetMaskErrorHandler((error) => {
dispatch(updateConnectionError({ connectionType: ConnectionType.INJECTED, error: error.message })) if (error.code === 1013) {
) toggleMetaMaskConnectionErrorModal()
}, [dispatch]) }
})
}, [toggleMetaMaskConnectionErrorModal])
useEagerlyConnect() useEagerlyConnect()
const connections = useOrderedConnections() const connections = useOrderedConnections()
......
...@@ -5,12 +5,12 @@ import { useWeb3React } from '@web3-react/core' ...@@ -5,12 +5,12 @@ import { useWeb3React } from '@web3-react/core'
import { FiatOnrampAnnouncement } from 'components/FiatOnrampAnnouncement' import { FiatOnrampAnnouncement } from 'components/FiatOnrampAnnouncement'
import { IconWrapper } from 'components/Identicon/StatusIcon' import { IconWrapper } from 'components/Identicon/StatusIcon'
import WalletDropdown from 'components/WalletDropdown' import WalletDropdown from 'components/WalletDropdown'
import { getConnection, getIsMetaMask } from 'connection/utils' import { getConnection } from 'connection/utils'
import { Portal } from 'nft/components/common/Portal' import { Portal } from 'nft/components/common/Portal'
import { useIsNftClaimAvailable } from 'nft/hooks/useIsNftClaimAvailable' import { useIsNftClaimAvailable } from 'nft/hooks/useIsNftClaimAvailable'
import { getIsValidSwapQuote } from 'pages/Swap' import { getIsValidSwapQuote } from 'pages/Swap'
import { darken } from 'polished' import { darken } from 'polished'
import { useCallback, useEffect, useMemo, useRef } from 'react' import { useCallback, useMemo, useRef } from 'react'
import { AlertTriangle, ChevronDown, ChevronUp } from 'react-feather' import { AlertTriangle, ChevronDown, ChevronUp } from 'react-feather'
import { useAppSelector } from 'state/hooks' import { useAppSelector } from 'state/hooks'
import { useDerivedSwapInfo } from 'state/swap/hooks' import { useDerivedSwapInfo } from 'state/swap/hooks'
...@@ -22,7 +22,6 @@ import { useOnClickOutside } from '../../hooks/useOnClickOutside' ...@@ -22,7 +22,6 @@ import { useOnClickOutside } from '../../hooks/useOnClickOutside'
import { import {
useCloseModal, useCloseModal,
useModalIsOpen, useModalIsOpen,
useOpenMetamaskConnectionErrorModal,
useToggleWalletDropdown, useToggleWalletDropdown,
useToggleWalletModal, useToggleWalletModal,
} from '../../state/application/hooks' } from '../../state/application/hooks'
...@@ -35,7 +34,6 @@ import StatusIcon from '../Identicon/StatusIcon' ...@@ -35,7 +34,6 @@ import StatusIcon from '../Identicon/StatusIcon'
import Loader from '../Loader' import Loader from '../Loader'
import { RowBetween } from '../Row' import { RowBetween } from '../Row'
import WalletModal from '../WalletModal' import WalletModal from '../WalletModal'
import MetamaskConnectionError from './MetamaskConnectionError'
// https://stackoverflow.com/a/31617326 // https://stackoverflow.com/a/31617326
const FULL_BORDER_RADIUS = 9999 const FULL_BORDER_RADIUS = 9999
...@@ -213,16 +211,10 @@ function Web3StatusInner() { ...@@ -213,16 +211,10 @@ function Web3StatusInner() {
toggleWalletDropdown() toggleWalletDropdown()
}, [toggleWalletDropdown]) }, [toggleWalletDropdown])
const toggleWalletModal = useToggleWalletModal() const toggleWalletModal = useToggleWalletModal()
const openMetamaskConnectionErrorModal = useOpenMetamaskConnectionErrorModal()
const walletIsOpen = useModalIsOpen(ApplicationModal.WALLET_DROPDOWN) const walletIsOpen = useModalIsOpen(ApplicationModal.WALLET_DROPDOWN)
const isClaimAvailable = useIsNftClaimAvailable((state) => state.isClaimAvailable) const isClaimAvailable = useIsNftClaimAvailable((state) => state.isClaimAvailable)
const error = useAppSelector((state) => state.connection.errorByConnectionType[connectionType]) const error = useAppSelector((state) => state.connection.errorByConnectionType[connectionType])
useEffect(() => {
if (getIsMetaMask(connectionType) && error) {
openMetamaskConnectionErrorModal()
}
}, [error, connectionType, openMetamaskConnectionErrorModal])
const allTransactions = useAllTransactions() const allTransactions = useAllTransactions()
...@@ -326,7 +318,6 @@ export default function Web3Status() { ...@@ -326,7 +318,6 @@ export default function Web3Status() {
<Web3StatusInner /> <Web3StatusInner />
<FiatOnrampAnnouncement /> <FiatOnrampAnnouncement />
<WalletModal ENSName={ENSName ?? undefined} pendingTransactions={pending} confirmedTransactions={confirmed} /> <WalletModal ENSName={ENSName ?? undefined} pendingTransactions={pending} confirmedTransactions={confirmed} />
<MetamaskConnectionError />
<Portal> <Portal>
<span ref={walletRef}> <span ref={walletRef}>
<WalletDropdown /> <WalletDropdown />
......
...@@ -25,9 +25,10 @@ export interface Connection { ...@@ -25,9 +25,10 @@ export interface Connection {
type: ConnectionType type: ConnectionType
} }
let metaMaskErrorHandler: (error: Error) => void | undefined type MetaMaskError = Error & { code: number }
export function setMetMaskErrorHandler(errorHandler: (error: Error) => void) { let metaMaskErrorHandler: (error: MetaMaskError) => void | undefined
export function setMetMaskErrorHandler(errorHandler: typeof metaMaskErrorHandler) {
metaMaskErrorHandler = errorHandler metaMaskErrorHandler = errorHandler
} }
...@@ -35,9 +36,9 @@ function onError(error: Error) { ...@@ -35,9 +36,9 @@ function onError(error: Error) {
console.debug(`web3-react error: ${error}`) console.debug(`web3-react error: ${error}`)
} }
function onMetamaskError(error: Error) { function onMetaMaskError(error: Error) {
onError(error) onError(error)
metaMaskErrorHandler?.(error) metaMaskErrorHandler?.(error as MetaMaskError)
} }
const [web3Network, web3NetworkHooks] = initializeConnector<Network>( const [web3Network, web3NetworkHooks] = initializeConnector<Network>(
...@@ -50,7 +51,7 @@ export const networkConnection: Connection = { ...@@ -50,7 +51,7 @@ export const networkConnection: Connection = {
} }
const [web3Injected, web3InjectedHooks] = initializeConnector<MetaMask>( const [web3Injected, web3InjectedHooks] = initializeConnector<MetaMask>(
(actions) => new MetaMask({ actions, onError: onMetamaskError }) (actions) => new MetaMask({ actions, onError: onMetaMaskError })
) )
export const injectedConnection: Connection = { export const injectedConnection: Connection = {
connector: web3Injected, connector: web3Injected,
......
...@@ -93,14 +93,10 @@ export function useCloseModal(): () => void { ...@@ -93,14 +93,10 @@ export function useCloseModal(): () => void {
return useCallback(() => dispatch(setOpenModal(null)), [dispatch]) return useCallback(() => dispatch(setOpenModal(null)), [dispatch])
} }
export function useToggleMetamaskConnectionErrorModal(): () => void { export function useToggleMetaMaskConnectionErrorModal(): () => void {
return useToggleModal(ApplicationModal.METAMASK_CONNECTION_ERROR) return useToggleModal(ApplicationModal.METAMASK_CONNECTION_ERROR)
} }
export function useOpenMetamaskConnectionErrorModal(): () => void {
return useOpenModal(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])
......
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