state/user/hooks#useWatchlistTokens TypeScript Examples
The following examples show how to use
state/user/hooks#useWatchlistTokens.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx From glide-frontend with GNU General Public License v3.0 | 6 votes |
TokensOverview: React.FC = () => {
const { t } = useTranslation()
useEffect(() => {
window.scrollTo(0, 0)
}, [])
const allTokens = useAllTokenData()
const formattedTokens = useMemo(() => {
return Object.values(allTokens)
.map((token) => token.data)
.filter((token) => token)
}, [allTokens])
const [savedTokens] = useWatchlistTokens()
const watchListTokens = useTokenDatas(savedTokens)
return (
<Page>
<Heading scale="lg" mb="16px">
{t('Your Watchlist')}
</Heading>
{savedTokens.length > 0 ? (
<TokenTable tokenDatas={watchListTokens} />
) : (
<Card>
<Text py="16px" px="24px">
{t('Saved tokens will appear here')}
</Text>
</Card>
)}
<TopTokenMovers />
<Heading scale="lg" mt="40px" mb="16px" id="info-tokens-title">
{t('All Tokens')}
</Heading>
<TokenTable tokenDatas={formattedTokens} />
</Page>
)
}
Example #2
Source File: index.tsx From vvs-ui with GNU General Public License v3.0 | 6 votes |
TokensOverview: React.FC = () => {
const { t } = useTranslation()
useEffect(() => {
window.scrollTo(0, 0)
}, [])
const allTokens = useAllTokenData()
const formattedTokens = useMemo(() => {
return Object.values(allTokens)
.map((token) => token.data)
.filter((token) => token)
}, [allTokens])
const [savedTokens] = useWatchlistTokens()
const watchListTokens = useTokenDatas(savedTokens)
return (
<Page>
<Heading scale="lg" mb="16px">
{t('Your Watchlist')}
</Heading>
{savedTokens.length > 0 ? (
<TokenTable tokenDatas={watchListTokens} />
) : (
<WatchlistCard justifyContent="center">
<Text py="16px" px="24px" bold>
{t('Saved tokens will appear here')}
</Text>
</WatchlistCard>
)}
<TopTokenMovers />
<Heading scale="lg" mt="40px" mb="16px" id="info-tokens-title">
{t('All Tokens')}
</Heading>
<TokenTable tokenDatas={formattedTokens} />
</Page>
)
}
Example #3
Source File: TokenPage.tsx From glide-frontend with GNU General Public License v3.0 | 4 votes |
TokenPage: React.FC<RouteComponentProps<{ address: string }>> = ({
match: {
params: { address: routeAddress },
},
}) => {
const { isXs, isSm } = useMatchBreakpoints()
const { t } = useTranslation()
// Needed to scroll up if user comes to this page by clicking on entry in the table
useEffect(() => {
window.scrollTo(0, 0)
}, [])
// In case somebody pastes checksummed address into url (since GraphQL expects lowercase address)
const address = routeAddress.toLowerCase()
const cmcLink = useCMCLink(address)
const tokenData = useTokenData(address)
const poolsForToken = usePoolsForToken(address)
const poolDatas = usePoolDatas(poolsForToken ?? [])
const transactions = useTokenTransactions(address)
const chartData = useTokenChartData(address)
// pricing data
const priceData = useTokenPriceData(address, ONE_HOUR_SECONDS, DEFAULT_TIME_WINDOW)
const adjustedPriceData = useMemo(() => {
// Include latest available price
if (priceData && tokenData && priceData.length > 0) {
return [
...priceData,
{
time: new Date().getTime() / 1000,
open: priceData[priceData.length - 1].close,
close: tokenData?.priceUSD,
high: tokenData?.priceUSD,
low: priceData[priceData.length - 1].close,
},
]
}
return undefined
}, [priceData, tokenData])
const [watchlistTokens, addWatchlistToken] = useWatchlistTokens()
return (
<Page1 symbol={tokenData?.symbol}>
{tokenData ? (
!tokenData.exists ? (
<Card>
<Box p="16px">
<Text>
{t('No pool has been created with this token yet. Create one')}
<Link style={{ display: 'inline', marginLeft: '6px' }} to={`/add/${address}`}>
{t('here.')}
</Link>
</Text>
</Box>
</Card>
) : (
<>
{/* Stuff on top */}
<Flex justifyContent="space-between" mb="24px" flexDirection={['column', 'column', 'row']}>
<Breadcrumbs mb="32px">
<Link to="/info">
<Text color="primary">{t('Info')}</Text>
</Link>
<Link to="/info/tokens">
<Text color="primary">{t('Tokens')}</Text>
</Link>
<Flex>
<Text mr="8px">{tokenData.symbol}</Text>
<Text>{`(${truncateHash(address)})`}</Text>
</Flex>
</Breadcrumbs>
<Flex justifyContent={[null, null, 'flex-end']} mt={['8px', '8px', 0]}>
<LinkExternal mr="8px" color="primary" href={getBscScanLink(address, 'address')}>
{t('View on explorer')}
</LinkExternal>
{cmcLink && (
<StyledCMCLink href={cmcLink} rel="noopener noreferrer nofollow" target="_blank">
<Image src="/images/CMC-logo.svg" height={22} width={22} alt={t('View token on CoinMarketCap')} />
</StyledCMCLink>
)}
<SaveIcon fill={watchlistTokens.includes(address)} onClick={() => addWatchlistToken(address)} />
</Flex>
</Flex>
<Flex justifyContent="space-between" flexDirection={['column', 'column', 'column', 'row']}>
<Flex flexDirection="column" mb={['8px', null]}>
<Flex alignItems="center">
<CurrencyLogo size="32px" address={address} />
<Text
ml="12px"
bold
lineHeight="0.7"
fontSize={isXs || isSm ? '24px' : '40px'}
id="info-token-name-title"
>
{tokenData.name}
</Text>
<Text ml="12px" lineHeight="1" color="textSubtle" fontSize={isXs || isSm ? '14px' : '20px'}>
({tokenData.symbol})
</Text>
</Flex>
<Flex mt="8px" ml="46px" alignItems="center">
<Text mr="16px" bold fontSize="24px">
${formatAmount(tokenData.priceUSD, { notation: 'standard' })}
</Text>
<Percent value={tokenData.priceUSDChange} fontWeight={600} />
</Flex>
</Flex>
<Flex>
<Link to={`/add/${address}`}>
<Button mr="8px" variant="secondary">
{t('Add Liquidity')}
</Button>
</Link>
<Link to={`/swap?inputCurrency=${address}`}>
<Button>{t('Trade')}</Button>
</Link>
</Flex>
</Flex>
{/* data on the right side of chart */}
<ContentLayout>
<Card>
<Box p="24px">
<Text bold small color="secondary" fontSize="12px" textTransform="uppercase">
{t('Liquidity')}
</Text>
<Text bold fontSize="24px">
${formatAmount(tokenData.liquidityUSD)}
</Text>
<Percent value={tokenData.liquidityUSDChange} />
<Text mt="24px" bold color="secondary" fontSize="12px" textTransform="uppercase">
{t('Volume 24H')}
</Text>
<Text bold fontSize="24px" textTransform="uppercase">
${formatAmount(tokenData.volumeUSD)}
</Text>
<Percent value={tokenData.volumeUSDChange} />
<Text mt="24px" bold color="secondary" fontSize="12px" textTransform="uppercase">
{t('Volume 7D')}
</Text>
<Text bold fontSize="24px">
${formatAmount(tokenData.volumeUSDWeek)}
</Text>
<Text mt="24px" bold color="secondary" fontSize="12px" textTransform="uppercase">
{t('Transactions 24H')}
</Text>
<Text bold fontSize="24px">
{formatAmount(tokenData.txCount, { isInteger: true })}
</Text>
</Box>
</Card>
{/* charts card */}
<ChartCard
variant="token"
chartData={chartData}
tokenData={tokenData}
tokenPriceData={adjustedPriceData}
/>
</ContentLayout>
{/* pools and transaction tables */}
<Heading scale="lg" mb="16px" mt="40px">
{t('Pools')}
</Heading>
<PoolTable poolDatas={poolDatas} />
<Heading scale="lg" mb="16px" mt="40px">
{t('Transactions')}
</Heading>
<TransactionTable transactions={transactions} />
</>
)
) : (
<Flex mt="80px" justifyContent="center">
<ButterflyLoader />
</Flex>
)}
</Page1>
)
}
Example #4
Source File: index.tsx From glide-frontend with GNU General Public License v3.0 | 4 votes |
Search = () => {
const history = useHistory()
const { isXs, isSm } = useMatchBreakpoints()
const { t } = useTranslation()
const inputRef = useRef<HTMLInputElement>(null)
const menuRef = useRef<HTMLDivElement>(null)
const showMoreRef = useRef<HTMLDivElement>(null)
const [showMenu, setShowMenu] = useState(false)
const [value, setValue] = useState('')
const debouncedSearchTerm = useDebounce(value, 600)
const { tokens, pools, tokensLoading, poolsLoading, error } = useFetchSearchResults(debouncedSearchTerm)
const [tokensShown, setTokensShown] = useState(3)
const [poolsShown, setPoolsShown] = useState(3)
useEffect(() => {
setTokensShown(3)
setPoolsShown(3)
}, [debouncedSearchTerm])
const handleOutsideClick = (e: any) => {
const menuClick = menuRef.current && menuRef.current.contains(e.target)
const inputCLick = inputRef.current && inputRef.current.contains(e.target)
const showMoreClick = showMoreRef.current && showMoreRef.current.contains(e.target)
if (!menuClick && !inputCLick && !showMoreClick) {
setPoolsShown(3)
setTokensShown(3)
setShowMenu(false)
}
}
useEffect(() => {
if (showMenu) {
document.addEventListener('click', handleOutsideClick)
document.querySelector('body').style.overflow = 'hidden'
} else {
document.removeEventListener('click', handleOutsideClick)
document.querySelector('body').style.overflow = 'visible'
}
return () => {
document.removeEventListener('click', handleOutsideClick)
}
}, [showMenu])
// watchlist
const [savedTokens, addSavedToken] = useWatchlistTokens()
const [savedPools, addSavedPool] = useWatchlistPools()
const handleItemClick = (to: string) => {
setShowMenu(false)
setPoolsShown(3)
setTokensShown(3)
history.push(to)
}
// get date for watchlist
const watchListTokenData = useTokenDatas(savedTokens)
const watchListTokenLoading = watchListTokenData.length !== savedTokens.length
const watchListPoolData = usePoolDatas(savedPools)
const watchListPoolLoading = watchListPoolData.length !== savedPools.length
// filter on view
const [showWatchlist, setShowWatchlist] = useState(false)
const tokensForList = useMemo(() => {
if (showWatchlist) {
return watchListTokenData.filter((token) => tokenIncludesSearchTerm(token, value))
}
return tokens.sort((t0, t1) => (t0.volumeUSD > t1.volumeUSD ? -1 : 1))
}, [showWatchlist, tokens, watchListTokenData, value])
const poolForList = useMemo(() => {
if (showWatchlist) {
return watchListPoolData.filter((pool) => poolIncludesSearchTerm(pool, value))
}
return pools.sort((p0, p1) => (p0.volumeUSD > p1.volumeUSD ? -1 : 1))
}, [pools, showWatchlist, watchListPoolData, value])
const contentUnderTokenList = () => {
const isLoading = showWatchlist ? watchListTokenLoading : tokensLoading
const noTokensFound =
tokensForList.length === 0 && !isLoading && debouncedSearchTerm.length >= MINIMUM_SEARCH_CHARACTERS
const noWatchlistTokens = tokensForList.length === 0 && !isLoading
const showMessage = showWatchlist ? noWatchlistTokens : noTokensFound
const noTokensMessage = showWatchlist ? t('Saved tokens will appear here') : t('No results')
return (
<>
{isLoading && <Skeleton />}
{showMessage && <Text>{noTokensMessage}</Text>}
{!showWatchlist && debouncedSearchTerm.length < MINIMUM_SEARCH_CHARACTERS && (
<Text>{t('Search pools or tokens')}</Text>
)}
</>
)
}
const contentUnderPoolList = () => {
const isLoading = showWatchlist ? watchListPoolLoading : poolsLoading
const noPoolsFound =
poolForList.length === 0 && !poolsLoading && debouncedSearchTerm.length >= MINIMUM_SEARCH_CHARACTERS
const noWatchlistPools = poolForList.length === 0 && !isLoading
const showMessage = showWatchlist ? noWatchlistPools : noPoolsFound
const noPoolsMessage = showWatchlist ? t('Saved tokens will appear here') : t('No results')
return (
<>
{isLoading && <Skeleton />}
{showMessage && <Text>{noPoolsMessage}</Text>}
{!showWatchlist && debouncedSearchTerm.length < MINIMUM_SEARCH_CHARACTERS && (
<Text>{t('Search pools or tokens')}</Text>
)}
</>
)
}
return (
<>
{showMenu ? <Blackout /> : null}
<Container>
<StyledInput
type="text"
value={value}
onChange={(e) => {
setValue(e.target.value)
}}
placeholder={t('Search pools or tokens')}
ref={inputRef}
onFocus={() => {
setShowMenu(true)
}}
/>
<Menu hide={!showMenu} ref={menuRef}>
<Flex mb="16px">
<OptionButton enabled={!showWatchlist} onClick={() => setShowWatchlist(false)}>
{t('Search')}
</OptionButton>
<OptionButton enabled={showWatchlist} onClick={() => setShowWatchlist(true)}>
{t('Watchlist')}
</OptionButton>
</Flex>
{error && <Text color="failure">{t('Error occurred, please try again')}</Text>}
<ResponsiveGrid>
<Text bold color="secondary">
{t('Tokens')}
</Text>
{!isXs && !isSm && (
<Text textAlign="end" fontSize="12px">
{t('Price')}
</Text>
)}
{!isXs && !isSm && (
<Text textAlign="end" fontSize="12px">
{t('Volume 24H')}
</Text>
)}
{!isXs && !isSm && (
<Text textAlign="end" fontSize="12px">
{t('Liquidity')}
</Text>
)}
</ResponsiveGrid>
{tokensForList.slice(0, tokensShown).map((token, i) => {
return (
// eslint-disable-next-line react/no-array-index-key
<HoverRowLink onClick={() => handleItemClick(`/info/token/${token.address}`)} key={i}>
<ResponsiveGrid>
<Flex>
<CurrencyLogo address={token.address} />
<Text ml="10px">
<Text>{`${token.name} (${token.symbol})`}</Text>
</Text>
<SaveIcon
id="watchlist-icon"
style={{ marginLeft: '8px' }}
fill={savedTokens.includes(token.address)}
onClick={(e) => {
e.stopPropagation()
addSavedToken(token.address)
}}
/>
</Flex>
{!isXs && !isSm && <Text textAlign="end">${formatAmount(token.priceUSD)}</Text>}
{!isXs && !isSm && <Text textAlign="end">${formatAmount(token.volumeUSD)}</Text>}
{!isXs && !isSm && <Text textAlign="end">${formatAmount(token.liquidityUSD)}</Text>}
</ResponsiveGrid>
</HoverRowLink>
)
})}
{contentUnderTokenList()}
<HoverText
onClick={() => {
setTokensShown(tokensShown + 5)
}}
hide={tokensForList.length <= tokensShown}
ref={showMoreRef}
>
{t('See more...')}
</HoverText>
<Break />
<ResponsiveGrid>
<Text bold color="secondary" mb="8px">
{t('Pools')}
</Text>
{!isXs && !isSm && (
<Text textAlign="end" fontSize="12px">
{t('Volume 24H')}
</Text>
)}
{!isXs && !isSm && (
<Text textAlign="end" fontSize="12px">
{t('Volume 7D')}
</Text>
)}
{!isXs && !isSm && (
<Text textAlign="end" fontSize="12px">
{t('Liquidity')}
</Text>
)}
</ResponsiveGrid>
{poolForList.slice(0, poolsShown).map((p, i) => {
return (
// eslint-disable-next-line react/no-array-index-key
<HoverRowLink onClick={() => handleItemClick(`/info/pool/${p.address}`)} key={i}>
<ResponsiveGrid>
<Flex>
<DoubleCurrencyLogo address0={p.token0.address} address1={p.token1.address} />
<Text ml="10px" style={{ whiteSpace: 'nowrap' }}>
<Text>{`${p.token0.symbol} / ${p.token1.symbol}`}</Text>
</Text>
<SaveIcon
id="watchlist-icon"
style={{ marginLeft: '10px' }}
fill={savedPools.includes(p.address)}
onClick={(e) => {
e.stopPropagation()
addSavedPool(p.address)
}}
/>
</Flex>
{!isXs && !isSm && <Text textAlign="end">${formatAmount(p.volumeUSD)}</Text>}
{!isXs && !isSm && <Text textAlign="end">${formatAmount(p.volumeUSDWeek)}</Text>}
{!isXs && !isSm && <Text textAlign="end">${formatAmount(p.liquidityUSD)}</Text>}
</ResponsiveGrid>
</HoverRowLink>
)
})}
{contentUnderPoolList()}
<HoverText
onClick={() => {
setPoolsShown(poolsShown + 5)
}}
hide={poolForList.length <= poolsShown}
ref={showMoreRef}
>
{t('See more...')}
</HoverText>
</Menu>
</Container>
</>
)
}
Example #5
Source File: TokenPage.tsx From vvs-ui with GNU General Public License v3.0 | 4 votes |
TokenPage: React.FC<RouteComponentProps<{ address: string }>> = ({
match: {
params: { address: routeAddress },
},
}) => {
const { isXs, isSm } = useMatchBreakpoints()
const { t } = useTranslation()
// Needed to scroll up if user comes to this page by clicking on entry in the table
useEffect(() => {
window.scrollTo(0, 0)
}, [])
// In case somebody pastes checksummed address into url (since GraphQL expects lowercase address)
const address = routeAddress.toLowerCase()
const cmcLink = useCMCLink(address)
const tokenData = useTokenData(address)
const poolsForToken = usePoolsForToken(address)
const poolDatas = usePoolDatas(poolsForToken ?? [])
const transactions = useTokenTransactions(address)
const chartData = useTokenChartData(address)
// pricing data
const priceData = useTokenPriceData(address, ONE_HOUR_SECONDS, DEFAULT_TIME_WINDOW)
const adjustedPriceData = useMemo(() => {
// Include latest available price
if (priceData && tokenData && priceData.length > 0) {
return [
...priceData,
{
time: new Date().getTime() / 1000,
open: priceData[priceData.length - 1].close,
close: tokenData?.priceUSD,
high: tokenData?.priceUSD,
low: priceData[priceData.length - 1].close,
},
]
}
return undefined
}, [priceData, tokenData])
const [watchlistTokens, addWatchlistToken] = useWatchlistTokens()
return (
<Page symbol={tokenData?.symbol}>
{tokenData ? (
!tokenData.exists ? (
<Card>
<Box p="16px">
<Text>
{t('No pool has been created with this token yet. Create one')}
<Link style={{ display: 'inline', marginLeft: '6px' }} to={`/add/${address}`}>
{t('here.')}
</Link>
</Text>
</Box>
</Card>
) : (
<>
{/* Stuff on top */}
<Flex justifyContent="space-between" mb="24px" flexDirection={['column', 'column', 'row']}>
<Breadcrumbs mb="32px">
<Link to="/info">
<Text color="primary">{t('Info')}</Text>
</Link>
<Link to="/info/tokens">
<Text color="primary">{t('Tokens')}</Text>
</Link>
<Flex>
<Text mr="8px">{tokenData.symbol}</Text>
<Text>{`(${truncateHash(address)})`}</Text>
</Flex>
</Breadcrumbs>
<Flex justifyContent={[null, null, 'flex-end']} mt={['8px', '8px', 0]}>
<LinkExternal mr="8px" color="primary" href={getExplorerLink(address, 'address')}>
{t('View on Cronos Explorer')}
</LinkExternal>
{cmcLink && (
<StyledCMCLink href={cmcLink} rel="noopener noreferrer nofollow" target="_blank">
<Image src="/images/CMC-logo.svg" height={22} width={22} alt={t('View token on CoinMarketCap')} />
</StyledCMCLink>
)}
<SaveIcon fill={watchlistTokens.includes(address)} onClick={() => addWatchlistToken(address)} />
</Flex>
</Flex>
<Flex justifyContent="space-between" flexDirection={['column', 'column', 'column', 'row']}>
<Flex flexDirection="column" mb={['8px', null]}>
<Flex alignItems="center">
<CurrencyLogo size="32px" address={address} />
<Text
ml="12px"
bold
lineHeight="0.7"
fontSize={isXs || isSm ? '24px' : '40px'}
id="info-token-name-title"
>
{tokenData.name}
</Text>
<Text ml="12px" lineHeight="1" color="textSubtle" fontSize={isXs || isSm ? '14px' : '20px'}>
({tokenData.symbol})
</Text>
</Flex>
<Flex mt="8px" ml="46px" alignItems="center">
<Text mr="16px" bold fontSize="24px">
${formatAmount(tokenData.priceUSD, { notation: 'standard' })}
</Text>
<Percent value={tokenData.priceUSDChange} fontWeight={600} />
</Flex>
</Flex>
<Flex>
<Link to={`/add/${address}`}>
<Button mr="8px" variant="secondary">
{t('Add Liquidity')}
</Button>
</Link>
<Link to={`/swap?inputCurrency=${address}`}>
<Button>{t('Trade')}</Button>
</Link>
</Flex>
</Flex>
{/* data on the right side of chart */}
<ContentLayout>
<Card>
<Box p="24px">
<Text bold small color="secondary" fontSize="12px" textTransform="uppercase">
{t('Liquidity')}
</Text>
<Text bold fontSize="24px">
${formatAmount(tokenData.liquidityUSD)}
</Text>
<Percent value={tokenData.liquidityUSDChange} />
<Text mt="24px" bold color="secondary" fontSize="12px" textTransform="uppercase">
{t('Volume 24H')}
</Text>
<Text bold fontSize="24px" textTransform="uppercase">
${formatAmount(tokenData.volumeUSD)}
</Text>
<Percent value={tokenData.volumeUSDChange} />
<Text mt="24px" bold color="secondary" fontSize="12px" textTransform="uppercase">
{t('Volume 7D')}
</Text>
<Text bold fontSize="24px">
${formatAmount(tokenData.volumeUSDWeek)}
</Text>
<Text mt="24px" bold color="secondary" fontSize="12px" textTransform="uppercase">
{t('Transactions 24H')}
</Text>
<Text bold fontSize="24px">
{formatAmount(tokenData.txCount, { isInteger: true })}
</Text>
</Box>
</Card>
{/* charts card */}
<ChartCard
variant="token"
chartData={chartData}
tokenData={tokenData}
tokenPriceData={adjustedPriceData}
/>
</ContentLayout>
{/* pools and transaction tables */}
<Heading scale="lg" mb="16px" mt="40px">
Farms
</Heading>
<PoolTable poolDatas={poolDatas} />
<Heading scale="lg" mb="16px" mt="40px">
{t('Transactions')}
</Heading>
<TransactionTable transactions={transactions} />
</>
)
) : (
<Flex mt="80px" justifyContent="center">
<Spinner />
</Flex>
)}
</Page>
)
}
Example #6
Source File: index.tsx From vvs-ui with GNU General Public License v3.0 | 4 votes |
Search = () => {
const history = useHistory()
const { isXs, isSm } = useMatchBreakpoints()
const { t } = useTranslation()
const inputRef = useRef<HTMLInputElement>(null)
const menuRef = useRef<HTMLDivElement>(null)
const showMoreRef = useRef<HTMLDivElement>(null)
const [showMenu, setShowMenu] = useState(false)
const [value, setValue] = useState('')
const debouncedSearchTerm = useDebounce(value, 600)
const { tokens, pools, tokensLoading, poolsLoading, error } = useFetchSearchResults(debouncedSearchTerm)
const [tokensShown, setTokensShown] = useState(3)
const [poolsShown, setPoolsShown] = useState(3)
useEffect(() => {
setTokensShown(3)
setPoolsShown(3)
}, [debouncedSearchTerm])
const handleOutsideClick = (e: any) => {
const menuClick = menuRef.current && menuRef.current.contains(e.target)
const inputCLick = inputRef.current && inputRef.current.contains(e.target)
const showMoreClick = showMoreRef.current && showMoreRef.current.contains(e.target)
if (!menuClick && !inputCLick && !showMoreClick) {
setPoolsShown(3)
setTokensShown(3)
setShowMenu(false)
}
}
useEffect(() => {
if (showMenu) {
document.addEventListener('click', handleOutsideClick)
document.querySelector('body').style.overflow = 'hidden'
} else {
document.removeEventListener('click', handleOutsideClick)
document.querySelector('body').style.overflow = 'visible'
}
return () => {
document.removeEventListener('click', handleOutsideClick)
document.querySelector('body').style.overflow = 'visible'
}
}, [showMenu])
// watchlist
const [savedTokens, addSavedToken] = useWatchlistTokens()
const [savedPools, addSavedPool] = useWatchlistPools()
const handleItemClick = (to: string) => {
setShowMenu(false)
setPoolsShown(3)
setTokensShown(3)
history.push(to)
}
// get date for watchlist
const watchListTokenData = useTokenDatas(savedTokens)
const watchListTokenLoading = watchListTokenData.length !== savedTokens.length
const watchListPoolData = usePoolDatas(savedPools)
const watchListPoolLoading = watchListPoolData.length !== savedPools.length
// filter on view
const [showWatchlist, setShowWatchlist] = useState(false)
const tokensForList = useMemo(() => {
if (showWatchlist) {
return watchListTokenData.filter((token) => tokenIncludesSearchTerm(token, value))
}
return tokens.sort((t0, t1) => (t0.volumeUSD > t1.volumeUSD ? -1 : 1))
}, [showWatchlist, tokens, watchListTokenData, value])
const poolForList = useMemo(() => {
if (showWatchlist) {
return watchListPoolData.filter((pool) => poolIncludesSearchTerm(pool, value))
}
return pools.sort((p0, p1) => (p0.volumeUSD > p1.volumeUSD ? -1 : 1))
}, [pools, showWatchlist, watchListPoolData, value])
const contentUnderTokenList = () => {
const isLoading = showWatchlist ? watchListTokenLoading : tokensLoading
const noTokensFound =
tokensForList.length === 0 && !isLoading && debouncedSearchTerm.length >= MINIMUM_SEARCH_CHARACTERS
const noWatchlistTokens = tokensForList.length === 0 && !isLoading
const showMessage = showWatchlist ? noWatchlistTokens : noTokensFound
const noTokensMessage = showWatchlist ? t('Saved tokens will appear here') : t('No results')
return (
<>
{isLoading && <Skeleton />}
{showMessage && <Text>{noTokensMessage}</Text>}
{!showWatchlist && debouncedSearchTerm.length < MINIMUM_SEARCH_CHARACTERS && (
<Text>{t('Search farms or tokens')}</Text>
)}
</>
)
}
const contentUnderPoolList = () => {
const isLoading = showWatchlist ? watchListPoolLoading : poolsLoading
const noPoolsFound =
poolForList.length === 0 && !poolsLoading && debouncedSearchTerm.length >= MINIMUM_SEARCH_CHARACTERS
const noWatchlistPools = poolForList.length === 0 && !isLoading
const showMessage = showWatchlist ? noWatchlistPools : noPoolsFound
const noPoolsMessage = showWatchlist ? t('Saved tokens will appear here') : t('No results')
return (
<>
{isLoading && <Skeleton />}
{showMessage && <Text>{noPoolsMessage}</Text>}
{!showWatchlist && debouncedSearchTerm.length < MINIMUM_SEARCH_CHARACTERS && (
<Text>{t('Search farms or tokens')}</Text>
)}
</>
)
}
return (
<>
{showMenu ? <Blackout /> : null}
<Container>
<StyledInput
type="text"
value={value}
onChange={(e) => {
setValue(e.target.value)
}}
placeholder={t('Search farms or tokens')}
ref={inputRef}
onFocus={() => {
setShowMenu(true)
}}
/>
<Menu hide={!showMenu} ref={menuRef}>
<Flex mb="16px">
<OptionButton enabled={!showWatchlist} onClick={() => setShowWatchlist(false)}>
{t('Search')}
</OptionButton>
<OptionButton enabled={showWatchlist} onClick={() => setShowWatchlist(true)}>
{t('Watchlist')}
</OptionButton>
</Flex>
{error && <Text color="failure">{t('Error occurred, please try again')}</Text>}
<ResponsiveGrid>
<Text bold color="secondary">
{t('Tokens')}
</Text>
{!isXs && !isSm && (
<Text textAlign="end" fontSize="12px">
{t('Price')}
</Text>
)}
{!isXs && !isSm && (
<Text textAlign="end" fontSize="12px">
{t('Volume 24H')}
</Text>
)}
{!isXs && !isSm && (
<Text textAlign="end" fontSize="12px">
{t('Liquidity')}
</Text>
)}
</ResponsiveGrid>
{tokensForList.slice(0, tokensShown).map((token, i) => {
return (
// eslint-disable-next-line react/no-array-index-key
<HoverRowLink onClick={() => handleItemClick(`/info/token/${token.address}`)} key={i}>
<ResponsiveGrid>
<Flex>
<CurrencyLogo address={token.address} />
<Text ml="10px">
<Text>{`${token.name} (${token.symbol})`}</Text>
</Text>
<SaveIcon
id="watchlist-icon"
style={{ marginLeft: '8px' }}
fill={savedTokens.includes(token.address)}
onClick={(e) => {
e.stopPropagation()
addSavedToken(token.address)
}}
/>
</Flex>
{!isXs && !isSm && <Text textAlign="end">${formatAmount(token.priceUSD)}</Text>}
{!isXs && !isSm && <Text textAlign="end">${formatAmount(token.volumeUSD)}</Text>}
{!isXs && !isSm && <Text textAlign="end">${formatAmount(token.liquidityUSD)}</Text>}
</ResponsiveGrid>
</HoverRowLink>
)
})}
{contentUnderTokenList()}
<HoverText
onClick={() => {
setTokensShown(tokensShown + 5)
}}
hide={tokensForList.length <= tokensShown}
ref={showMoreRef}
>
{t('See more...')}
</HoverText>
<Break />
<ResponsiveGrid>
<Text bold color="secondary" mb="8px">
Mines
</Text>
{!isXs && !isSm && (
<Text textAlign="end" fontSize="12px">
{t('Volume 24H')}
</Text>
)}
{!isXs && !isSm && (
<Text textAlign="end" fontSize="12px">
{t('Volume 7D')}
</Text>
)}
{!isXs && !isSm && (
<Text textAlign="end" fontSize="12px">
{t('Liquidity')}
</Text>
)}
</ResponsiveGrid>
{poolForList.slice(0, poolsShown).map((p, i) => {
return (
// eslint-disable-next-line react/no-array-index-key
<HoverRowLink onClick={() => handleItemClick(`/info/farm/${p.address}`)} key={i}>
<ResponsiveGrid>
<Flex>
<DoubleCurrencyLogo address0={p.token0.address} address1={p.token1.address} />
<Text ml="10px" style={{ whiteSpace: 'nowrap' }}>
<Text>{`${p.token0.symbol} / ${p.token1.symbol}`}</Text>
</Text>
<SaveIcon
id="watchlist-icon"
style={{ marginLeft: '10px' }}
fill={savedPools.includes(p.address)}
onClick={(e) => {
e.stopPropagation()
addSavedPool(p.address)
}}
/>
</Flex>
{!isXs && !isSm && <Text textAlign="end">${formatAmount(p.volumeUSD)}</Text>}
{!isXs && !isSm && <Text textAlign="end">${formatAmount(p.volumeUSDWeek)}</Text>}
{!isXs && !isSm && <Text textAlign="end">${formatAmount(p.liquidityUSD)}</Text>}
</ResponsiveGrid>
</HoverRowLink>
)
})}
{contentUnderPoolList()}
<HoverText
onClick={() => {
setPoolsShown(poolsShown + 5)
}}
hide={poolForList.length <= poolsShown}
ref={showMoreRef}
>
{t('See more...')}
</HoverText>
</Menu>
</Container>
</>
)
}