import { AbstractConnector } from '@web3-react/abstract-connector' import { UnsupportedChainIdError, useWeb3React } from '@web3-react/core' import { darken, lighten } from 'polished' import React, { useMemo } from 'react' import { Activity } from 'react-feather' import { useTranslation } from 'react-i18next' import styled, { css } from 'styled-components' import { injected } from '../../connectors' import { NetworkContextName } from '../../constants/misc' import useENSName from '../../hooks/useENSName' import { useWalletModalToggle } from '../../state/application/hooks' import { isTransactionRecent, useAllTransactions } from '../../state/transactions/hooks' import { TransactionDetails } from '../../state/transactions/reducer' import { shortenAddress } from '../../utils' import { ButtonSecondary } from '../Button' import Identicon from '../Identicon' import Loader from '../Loader' import { RowBetween } from '../Row' 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)` ${({ theme }) => theme.flexRowNoWrap} width: 100%; align-items: center; padding: 0.5rem; border-radius: 12px; cursor: pointer; user-select: none; :focus { outline: none; } ` const Web3StatusError = styled(Web3StatusGeneric)` background-color: ${({ theme }) => theme.red1}; border: 1px solid ${({ theme }) => theme.red1}; color: ${({ theme }) => theme.white}; font-weight: 500; :hover, :focus { background-color: ${({ theme }) => darken(0.1, theme.red1)}; } ` const Web3StatusConnect = styled(Web3StatusGeneric)<{ faded?: boolean }>` background-color: ${({ theme }) => theme.primary4}; border: none; color: ${({ theme }) => theme.primaryText1}; font-weight: 500; :hover, :focus { border: 1px solid ${({ theme }) => darken(0.05, theme.primary4)}; color: ${({ theme }) => theme.primaryText1}; } ${({ faded }) => faded && css` background-color: ${({ theme }) => theme.primary5}; border: 1px solid ${({ theme }) => theme.primary5}; color: ${({ theme }) => theme.primaryText1}; :hover, :focus { border: 1px solid ${({ theme }) => darken(0.05, theme.primary4)}; color: ${({ theme }) => darken(0.05, theme.primaryText1)}; } `} ` const Web3StatusConnected = styled(Web3StatusGeneric)<{ pending?: boolean }>` background-color: ${({ pending, theme }) => (pending ? theme.primary1 : theme.bg1)}; border: 1px solid ${({ pending, theme }) => (pending ? theme.primary1 : theme.bg2)}; color: ${({ pending, theme }) => (pending ? theme.white : theme.text1)}; font-weight: 500; :hover, :focus { background-color: ${({ pending, theme }) => (pending ? darken(0.05, theme.primary1) : lighten(0.05, theme.bg1))}; :focus { border: 1px solid ${({ pending, theme }) => (pending ? darken(0.1, theme.primary1) : darken(0.1, theme.bg2))}; } } ` const Text = styled.p` flex: 1 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin: 0 0.5rem 0 0.25rem; font-size: 1rem; width: fit-content; font-weight: 500; ` const NetworkIcon = styled(Activity)` margin-left: 0.25rem; margin-right: 0.5rem; width: 16px; height: 16px; ` // we want the latest one to come first, so return negative if a is after b function newTransactionsFirst(a: TransactionDetails, b: TransactionDetails) { return b.addedTime - a.addedTime } // eslint-disable-next-line react/prop-types function StatusIcon({ connector }: { connector: AbstractConnector }) { if (connector === injected) { return } return null } function Web3StatusInner() { const { t } = useTranslation() const { account, connector, error } = useWeb3React() const { ENSName } = useENSName(account ?? undefined) const allTransactions = useAllTransactions() const sortedRecentTransactions = useMemo(() => { const txs = Object.values(allTransactions) return txs.filter(isTransactionRecent).sort(newTransactionsFirst) }, [allTransactions]) const pending = sortedRecentTransactions.filter((tx) => !tx.receipt).map((tx) => tx.hash) const hasPendingTransactions = !!pending.length const toggleWalletModal = useWalletModalToggle() if (account) { return ( {hasPendingTransactions ? ( {pending?.length} Pending ) : ( <> {ENSName || shortenAddress(account)} )} {!hasPendingTransactions && connector && } ) } else if (error) { return ( {error instanceof UnsupportedChainIdError ? 'Wrong Network' : 'Error'} ) } else { return ( {t('Connect to a wallet')} ) } } export default function Web3Status() { const { active, account } = useWeb3React() const contextNetwork = useWeb3React(NetworkContextName) const { ENSName } = useENSName(account ?? undefined) const allTransactions = useAllTransactions() const sortedRecentTransactions = useMemo(() => { const txs = Object.values(allTransactions) return txs.filter(isTransactionRecent).sort(newTransactionsFirst) }, [allTransactions]) const pending = sortedRecentTransactions.filter((tx) => !tx.receipt).map((tx) => tx.hash) const confirmed = sortedRecentTransactions.filter((tx) => tx.receipt).map((tx) => tx.hash) if (!contextNetwork.active && !active) { return null } return ( <> ) }