import { AbstractConnector } from '@web3-react/abstract-connector' import { UnsupportedChainIdError, useWeb3React } from '@web3-react/core' import React, { useEffect, useState } from 'react' import { isMobile } from 'react-device-detect' import ReactGA from 'react-ga' import styled from 'styled-components/macro' import MetamaskIcon from '../../assets/images/metamask.png' import { ReactComponent as Close } from '../../assets/images/x.svg' import { injected } from '../../connectors' import { SUPPORTED_WALLETS } from '../../constants/wallet' import usePrevious from '../../hooks/usePrevious' import { ApplicationModal } from '../../state/application/actions' import { useModalOpen, useWalletModalToggle } from '../../state/application/hooks' import AccountDetails from '../AccountDetails' import Modal from '../Modal' import Option from './Option' import PendingView from './PendingView' const CloseIcon = styled.div` position: absolute; right: 1rem; top: 14px; &:hover { cursor: pointer; opacity: 0.6; } ` const CloseColor = styled(Close)` path { stroke: ${({ theme }) => theme.text4}; } ` const Wrapper = styled.div` ${({ theme }) => theme.flexColumnNoWrap} margin: 0; padding: 0; width: 100%; ` const HeaderRow = styled.div` ${({ theme }) => theme.flexRowNoWrap}; padding: 1rem 1rem; font-weight: 500; color: ${(props) => (props.color === 'blue' ? ({ theme }) => theme.primary1 : 'inherit')}; ${({ theme }) => theme.mediaWidth.upToMedium` padding: 1rem; `}; ` const ContentWrapper = styled.div` background-color: ${({ theme }) => theme.bg0}; padding: 0 1rem 1rem 1rem; border-bottom-left-radius: 20px; border-bottom-right-radius: 20px; ${({ theme }) => theme.mediaWidth.upToMedium`padding: 0 1rem 1rem 1rem`}; ` const UpperSection = styled.div` position: relative; h5 { margin: 0; margin-bottom: 0.5rem; font-size: 1rem; font-weight: 400; } h5:last-child { margin-bottom: 0px; } h4 { margin-top: 0; font-weight: 500; } ` const OptionGrid = styled.div` display: grid; grid-gap: 10px; ${({ theme }) => theme.mediaWidth.upToMedium` grid-template-columns: 1fr; grid-gap: 10px; `}; ` const HoverText = styled.div` text-decoration: none; color: ${({ theme }) => theme.text1}; display: flex; align-items: center; :hover { cursor: pointer; } ` const WALLET_VIEWS = { OPTIONS: 'options', OPTIONS_SECONDARY: 'options_secondary', ACCOUNT: 'account', PENDING: 'pending', } export default function WalletModal({ pendingTransactions, confirmedTransactions, ENSName, }: { pendingTransactions: string[] // hashes of pending confirmedTransactions: string[] // hashes of confirmed ENSName?: string }) { // important that these are destructed from the account-specific web3-react context const { active, account, connector, activate, error } = useWeb3React() const [walletView, setWalletView] = useState(WALLET_VIEWS.ACCOUNT) const [pendingWallet, setPendingWallet] = useState() const [pendingError, setPendingError] = useState() const walletModalOpen = useModalOpen(ApplicationModal.WALLET) const toggleWalletModal = useWalletModalToggle() const previousAccount = usePrevious(account) // close on connection, when logged out before useEffect(() => { if (account && !previousAccount && walletModalOpen) { toggleWalletModal() } }, [account, previousAccount, toggleWalletModal, walletModalOpen]) // always reset to account view useEffect(() => { if (walletModalOpen) { setPendingError(false) setWalletView(WALLET_VIEWS.ACCOUNT) } }, [walletModalOpen]) // close modal when a connection is successful const activePrevious = usePrevious(active) const connectorPrevious = usePrevious(connector) useEffect(() => { if (walletModalOpen && ((active && !activePrevious) || (connector && connector !== connectorPrevious && !error))) { setWalletView(WALLET_VIEWS.ACCOUNT) } }, [setWalletView, active, error, connector, walletModalOpen, activePrevious, connectorPrevious]) const tryActivation = async (connector: AbstractConnector | undefined) => { let name = '' Object.keys(SUPPORTED_WALLETS).map((key) => { if (connector === SUPPORTED_WALLETS[key].connector) { return (name = SUPPORTED_WALLETS[key].name) } return true }) // log selected wallet ReactGA.event({ category: 'Wallet', action: 'Change Wallet', label: name, }) setPendingWallet(connector) // set wallet for pending view setWalletView(WALLET_VIEWS.PENDING) connector && activate(connector, undefined, true).catch((error) => { if (error instanceof UnsupportedChainIdError) { activate(connector) // a little janky...can't use setError because the connector isn't set } else { setPendingError(true) } }) } // get wallets user can switch too, depending on device/browser function getOptions() { const isMetamask = window.ethereum && window.ethereum.isMetaMask return Object.keys(SUPPORTED_WALLETS).map((key) => { const option = SUPPORTED_WALLETS[key] // check for mobile options if (isMobile) { if (!window.web3 && !window.ethereum && option.mobile) { return (