import { Currency, CurrencyAmount, Token } from "@uniswap/sdk-core"; import React, { CSSProperties, MutableRefObject, useCallback, useMemo, } from "react"; import { FixedSizeList } from "react-window"; import { Text } from "rebass"; import styled from "styled-components/macro"; import { useWeb3 } from "../../web3"; import { useCombinedActiveList } from "../../state/glists/hooks"; import { WrappedTokenInfo } from "../../state/glists/wrappedTokenInfo"; import { useCurrencyBalance } from "../../hooks/Balances"; import { TYPE } from "../../theme"; import { useIsUserAddedToken } from "../../hooks/Tokens"; import Column from "../Column"; import { RowFixed, RowBetween } from "../Row"; import CurrencyLogo from "../CurrencyLogo"; import { MouseoverTooltip } from "../Tooltip"; import { MenuItem } from "./styleds"; import Loader from "../Loader"; import { isTokenOnList } from "../../utils"; import ImportRow from "./ImportRow"; import { LightGreyCard } from "../Card"; import useTheme from "../../hooks/useTheme"; import QuestionHelper from "../QuestionHelper"; import TokenListLogo from "../../assets/svg/tokenlist.svg"; function currencyKey(currency: Currency): string { return currency.isToken ? currency.address : "ETHER"; } const StyledBalanceText = styled(Text)` white-space: nowrap; overflow: hidden; max-width: 5rem; text-overflow: ellipsis; `; const Tag = styled.div` background-color: ${({ theme }) => theme.bg3}; color: ${({ theme }) => theme.text2}; font-size: 14px; border-radius: 4px; padding: 0.25rem 0.3rem 0.25rem 0.3rem; max-width: 6rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; justify-self: flex-end; margin-right: 4px; `; const FixedContentRow = styled.div` padding: 4px 20px; height: 56px; display: grid; grid-gap: 16px; align-items: center; `; function Balance({ balance }: { balance: CurrencyAmount }) { return ( {balance.toSignificant(4)} ); } const TagContainer = styled.div` display: flex; justify-content: flex-end; `; const TokenListLogoWrapper = styled.img` height: 20px; `; function TokenTags({ currency }: { currency: Currency }) { if (!(currency instanceof WrappedTokenInfo)) { return ; } const tags = currency.tags; if (!tags || tags.length === 0) return ; const tag = tags[0]; return ( {tag.name} {tags.length > 1 ? ( `${name}: ${description}`) .join("; \n")} > ... ) : null} ); } function CurrencyRow({ currency, onSelect, isSelected, otherSelected, style, }: { currency: Currency; onSelect: () => void; isSelected: boolean; otherSelected: boolean; style: CSSProperties; }) { const { account } = useWeb3(); const key = currencyKey(currency); const selectedTokenList = useCombinedActiveList(); const isOnSelectedList = isTokenOnList( selectedTokenList, currency.isToken ? currency : undefined ); const customAdded = useIsUserAddedToken(currency); const balance = useCurrencyBalance(account ?? undefined, currency); // only show add or remove buttons if not on selected list return ( (isSelected ? null : onSelect())} disabled={isSelected} selected={otherSelected} > {currency.symbol} {currency.name}{" "} {!currency.isNative && !isOnSelectedList && customAdded && "• Added by user"} {balance ? : account ? : null} ); } const BREAK_LINE = "BREAK"; type BreakLine = typeof BREAK_LINE; function isBreakLine(x: unknown): x is BreakLine { return x === BREAK_LINE; } function BreakLineComponent({ style }: { style: CSSProperties }) { const theme = useTheme(); return ( Expanded results from inactive Token Lists ); } export default function CurrencyList({ height, currencies, otherListTokens, selectedCurrency, onCurrencySelect, otherCurrency, fixedListRef, showImportView, setImportToken, }: { height: number; currencies: Currency[]; otherListTokens?: WrappedTokenInfo[]; selectedCurrency?: Currency | null; onCurrencySelect: (currency: Currency) => void; otherCurrency?: Currency | null; fixedListRef?: MutableRefObject; showImportView: () => void; setImportToken: (token: Token) => void; }) { const itemData: (Currency | BreakLine)[] = useMemo(() => { if (otherListTokens && otherListTokens?.length > 0) { return [...currencies, BREAK_LINE, ...otherListTokens]; } return currencies; }, [currencies, otherListTokens]); const Row = useCallback( function TokenRow({ data, index, style }) { const row: Currency | BreakLine = data[index]; if (isBreakLine(row)) { return ; } const currency = row; const isSelected = Boolean( currency && selectedCurrency && selectedCurrency.equals(currency) ); const otherSelected = Boolean( currency && otherCurrency && otherCurrency.equals(currency) ); const handleSelect = () => currency && onCurrencySelect(currency); // TODO: fix native multi chain const token = currency.isNative ? undefined : currency?.wrapped; const showImport = index > currencies.length; if (showImport && token) { return ( ); } else if (currency) { return ( ); } else { return null; } }, // eslint-disable-next-line react-hooks/exhaustive-deps [currencies.length] ); const itemKey = useCallback((index: number, data: typeof itemData) => { const currency = data[index]; if (isBreakLine(currency)) return BREAK_LINE; return currencyKey(currency); }, []); return ( {Row} ); }