2022-12-06 16:22:32 -08:00
|
|
|
import { Bank } from '@blockworks-foundation/mango-v4'
|
|
|
|
import Change from '@components/shared/Change'
|
|
|
|
import ChartRangeButtons from '@components/shared/ChartRangeButtons'
|
2022-12-11 15:21:40 -08:00
|
|
|
import { ArrowSmallUpIcon, NoSymbolIcon } from '@heroicons/react/20/solid'
|
2022-12-06 16:22:32 -08:00
|
|
|
import dayjs from 'dayjs'
|
|
|
|
import relativeTime from 'dayjs/plugin/relativeTime'
|
|
|
|
import { useCoingecko } from 'hooks/useCoingecko'
|
|
|
|
import parse from 'html-react-parser'
|
|
|
|
import { useTranslation } from 'next-i18next'
|
|
|
|
import dynamic from 'next/dynamic'
|
2022-12-11 15:44:37 -08:00
|
|
|
import { useLayoutEffect, useMemo, useRef, useState } from 'react'
|
2022-12-06 16:22:32 -08:00
|
|
|
import { formatFixedDecimals } from 'utils/numbers'
|
|
|
|
const PriceChart = dynamic(() => import('@components/token/PriceChart'), {
|
|
|
|
ssr: false,
|
|
|
|
})
|
|
|
|
dayjs.extend(relativeTime)
|
|
|
|
|
|
|
|
const DEFAULT_COINGECKO_VALUES = {
|
|
|
|
ath: 0,
|
|
|
|
atl: 0,
|
|
|
|
ath_change_percentage: 0,
|
|
|
|
atl_change_percentage: 0,
|
|
|
|
ath_date: 0,
|
|
|
|
atl_date: 0,
|
|
|
|
high_24h: 0,
|
|
|
|
circulating_supply: 0,
|
|
|
|
fully_diluted_valuation: 0,
|
|
|
|
low_24h: 0,
|
|
|
|
market_cap: 0,
|
|
|
|
max_supply: 0,
|
|
|
|
price_change_percentage_24h: 0,
|
|
|
|
total_supply: 0,
|
|
|
|
total_volume: 0,
|
|
|
|
}
|
|
|
|
|
|
|
|
const CoingeckoStats = ({
|
|
|
|
bank,
|
|
|
|
coingeckoData,
|
|
|
|
coingeckoId,
|
|
|
|
}: {
|
|
|
|
bank: Bank
|
|
|
|
coingeckoData: any
|
|
|
|
coingeckoId: string
|
|
|
|
}) => {
|
|
|
|
const { t } = useTranslation(['common', 'token'])
|
|
|
|
const [showFullDesc, setShowFullDesc] = useState(false)
|
|
|
|
const [daysToShow, setDaysToShow] = useState<string>('1')
|
|
|
|
const [chartData, setChartData] = useState<{ prices: any[] } | null>(null)
|
|
|
|
const [loadChartData, setLoadChartData] = useState(true)
|
|
|
|
const { isLoading: loadingPrices, data: coingeckoPrices } = useCoingecko()
|
2022-12-11 15:44:37 -08:00
|
|
|
const descWidthRef = useRef<any>(null)
|
|
|
|
|
|
|
|
const [width, setWidth] = useState<number>(0)
|
|
|
|
|
|
|
|
useLayoutEffect(() => {
|
|
|
|
if (!descWidthRef.current) return
|
|
|
|
setWidth(descWidthRef.current.clientWidth)
|
|
|
|
}, [])
|
2022-12-06 16:22:32 -08:00
|
|
|
|
|
|
|
const handleDaysToShow = async (days: string) => {
|
|
|
|
if (days !== '1') {
|
|
|
|
try {
|
|
|
|
const response = await fetch(
|
|
|
|
`https://api.coingecko.com/api/v3/coins/${coingeckoId}/market_chart?vs_currency=usd&days=${days}`
|
|
|
|
)
|
|
|
|
const data = await response.json()
|
|
|
|
setLoadChartData(false)
|
|
|
|
setChartData(data)
|
|
|
|
} catch {
|
|
|
|
setLoadChartData(false)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
setDaysToShow(days)
|
|
|
|
}
|
|
|
|
|
|
|
|
const {
|
|
|
|
ath,
|
|
|
|
atl,
|
|
|
|
ath_change_percentage,
|
|
|
|
atl_change_percentage,
|
|
|
|
ath_date,
|
|
|
|
atl_date,
|
|
|
|
circulating_supply,
|
|
|
|
fully_diluted_valuation,
|
|
|
|
market_cap,
|
|
|
|
max_supply,
|
|
|
|
total_supply,
|
|
|
|
total_volume,
|
|
|
|
} = coingeckoData ? coingeckoData.market_data : DEFAULT_COINGECKO_VALUES
|
|
|
|
|
|
|
|
const loadingChart = useMemo(() => {
|
|
|
|
return daysToShow == '1' ? loadingPrices : loadChartData
|
|
|
|
}, [loadChartData, loadingPrices])
|
|
|
|
|
|
|
|
const coingeckoTokenPrices = useMemo(() => {
|
|
|
|
if (daysToShow === '1' && coingeckoPrices.length && bank) {
|
|
|
|
const tokenPriceData = coingeckoPrices.find(
|
|
|
|
(asset) => asset.symbol === bank.name
|
|
|
|
)
|
|
|
|
|
|
|
|
if (tokenPriceData) {
|
|
|
|
return tokenPriceData.prices
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (chartData && !loadingChart) {
|
|
|
|
return chartData.prices
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return []
|
|
|
|
}, [coingeckoPrices, bank, daysToShow, chartData, loadingChart])
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<div className="border-b border-th-bkg-3 py-4 px-6">
|
|
|
|
<h2 className="mb-1 text-xl">About {bank.name}</h2>
|
|
|
|
<div className="flex items-end">
|
|
|
|
<p
|
|
|
|
className={`${
|
|
|
|
showFullDesc ? 'h-full' : 'h-5'
|
|
|
|
} max-w-[720px] overflow-hidden`}
|
2022-12-11 15:44:37 -08:00
|
|
|
ref={descWidthRef}
|
2022-12-06 16:22:32 -08:00
|
|
|
>
|
|
|
|
{parse(coingeckoData.description.en)}
|
|
|
|
</p>
|
2022-12-11 15:44:37 -08:00
|
|
|
{width === 720 ? (
|
|
|
|
<span
|
|
|
|
className="default-transition ml-4 flex cursor-pointer items-end font-normal underline hover:text-th-fgd-2 md:hover:no-underline"
|
|
|
|
onClick={() => setShowFullDesc(!showFullDesc)}
|
|
|
|
>
|
|
|
|
{showFullDesc ? 'Less' : 'More'}
|
|
|
|
<ArrowSmallUpIcon
|
|
|
|
className={`h-5 w-5 ${
|
|
|
|
showFullDesc ? 'rotate-360' : 'rotate-180'
|
|
|
|
} default-transition`}
|
|
|
|
/>
|
|
|
|
</span>
|
|
|
|
) : null}
|
2022-12-06 16:22:32 -08:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
{!loadingChart ? (
|
|
|
|
coingeckoTokenPrices.length ? (
|
|
|
|
<>
|
|
|
|
<div className="mt-4 flex w-full items-center justify-between px-6">
|
|
|
|
<h2 className="text-base">{bank.name} Price Chart</h2>
|
|
|
|
<ChartRangeButtons
|
|
|
|
activeValue={daysToShow}
|
|
|
|
names={['24H', '7D', '30D']}
|
|
|
|
values={['1', '7', '30']}
|
|
|
|
onChange={(v) => handleDaysToShow(v)}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
<PriceChart
|
|
|
|
daysToShow={parseInt(daysToShow)}
|
|
|
|
prices={coingeckoTokenPrices}
|
|
|
|
/>
|
|
|
|
</>
|
|
|
|
) : bank?.name === 'USDC' || bank?.name === 'USDT' ? null : (
|
|
|
|
<div className="flex flex-col items-center p-6">
|
2022-12-11 15:21:40 -08:00
|
|
|
<NoSymbolIcon className="mb-1 h-6 w-6 text-th-fgd-4" />
|
2022-12-06 16:22:32 -08:00
|
|
|
<p className="mb-0 text-th-fgd-4">{t('token:chart-unavailable')}</p>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
) : (
|
|
|
|
<div className="h-10 w-[104px] animate-pulse rounded bg-th-bkg-3" />
|
|
|
|
)}
|
|
|
|
<div className="grid grid-cols-1 border-b border-th-bkg-3 md:grid-cols-2">
|
|
|
|
<div className="col-span-1 border-y border-th-bkg-3 px-6 py-4 md:col-span-2">
|
|
|
|
<h2 className="text-base">{bank.name} Stats</h2>
|
|
|
|
</div>
|
|
|
|
<div className="col-span-1 border-r border-th-bkg-3 px-6 py-4">
|
|
|
|
<div className="flex justify-between pb-4">
|
|
|
|
<p>{t('token:market-cap')}</p>
|
|
|
|
<p className="font-mono text-th-fgd-2">
|
2022-12-11 15:03:14 -08:00
|
|
|
{market_cap?.usd ? (
|
|
|
|
formatFixedDecimals(market_cap.usd, true)
|
|
|
|
) : (
|
|
|
|
<span className="font-body text-th-fgd-4">
|
|
|
|
{t('unavailable')}
|
|
|
|
</span>
|
|
|
|
)}{' '}
|
2022-12-06 16:22:32 -08:00
|
|
|
<span className="text-th-fgd-4">
|
2022-12-11 15:03:14 -08:00
|
|
|
{coingeckoData.market_cap_rank
|
|
|
|
? `#${coingeckoData.market_cap_rank}`
|
|
|
|
: ''}
|
2022-12-06 16:22:32 -08:00
|
|
|
</span>
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div className="flex justify-between border-t border-th-bkg-3 py-4">
|
|
|
|
<p>{t('token:volume')}</p>
|
|
|
|
<p className="font-mono text-th-fgd-2">
|
2022-12-11 15:03:14 -08:00
|
|
|
{total_volume?.usd ? (
|
|
|
|
formatFixedDecimals(total_volume.usd, true)
|
|
|
|
) : (
|
|
|
|
<span className="font-body text-th-fgd-4">
|
|
|
|
{t('unavailable')}
|
|
|
|
</span>
|
|
|
|
)}
|
2022-12-06 16:22:32 -08:00
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div className="flex justify-between border-t border-th-bkg-3 py-4">
|
|
|
|
<p>{t('token:all-time-high')}</p>
|
|
|
|
<div className="flex flex-col items-end">
|
|
|
|
<div className="flex items-center font-mono text-th-fgd-2">
|
|
|
|
<span className="mr-2">
|
2022-12-11 15:03:14 -08:00
|
|
|
{ath?.usd ? (
|
|
|
|
formatFixedDecimals(ath.usd, true)
|
|
|
|
) : (
|
|
|
|
<span className="font-body text-th-fgd-4">
|
|
|
|
{t('unavailable')}
|
|
|
|
</span>
|
|
|
|
)}
|
2022-12-06 16:22:32 -08:00
|
|
|
</span>
|
2022-12-11 15:03:14 -08:00
|
|
|
{ath_change_percentage.usd ? (
|
|
|
|
<Change change={ath_change_percentage.usd} suffix="%" />
|
|
|
|
) : null}
|
2022-12-06 16:22:32 -08:00
|
|
|
</div>
|
|
|
|
<p className="text-xs text-th-fgd-4">
|
|
|
|
{dayjs(ath_date.usd).format('MMM, D, YYYY')} (
|
|
|
|
{dayjs(ath_date.usd).fromNow()})
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className="flex justify-between border-b border-t border-th-bkg-3 py-4 md:border-b-0 md:pb-0">
|
|
|
|
<p>{t('token:all-time-low')}</p>
|
|
|
|
<div className="flex flex-col items-end">
|
|
|
|
<div className="flex items-center font-mono text-th-fgd-2">
|
|
|
|
<span className="mr-2">
|
2022-12-11 15:03:14 -08:00
|
|
|
{atl?.usd ? (
|
|
|
|
formatFixedDecimals(atl.usd, true)
|
|
|
|
) : (
|
|
|
|
<span className="font-body text-th-fgd-4">
|
|
|
|
{t('unavailable')}
|
|
|
|
</span>
|
|
|
|
)}
|
2022-12-06 16:22:32 -08:00
|
|
|
</span>
|
|
|
|
<Change change={atl_change_percentage.usd} suffix="%" />
|
|
|
|
</div>
|
|
|
|
<p className="text-xs text-th-fgd-4">
|
|
|
|
{dayjs(atl_date.usd).format('MMM, D, YYYY')} (
|
|
|
|
{dayjs(atl_date.usd).fromNow()})
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className="col-span-1 px-6 pb-4 md:pt-4">
|
|
|
|
{fully_diluted_valuation.usd ? (
|
|
|
|
<div className="flex justify-between pb-4">
|
|
|
|
<p>{t('token:fdv')}</p>
|
|
|
|
<p className="font-mono text-th-fgd-2">
|
2022-12-11 15:03:14 -08:00
|
|
|
{fully_diluted_valuation?.usd ? (
|
|
|
|
formatFixedDecimals(fully_diluted_valuation.usd, true)
|
|
|
|
) : (
|
|
|
|
<span className="font-body text-th-fgd-4">
|
|
|
|
{t('unavailable')}
|
|
|
|
</span>
|
|
|
|
)}
|
2022-12-06 16:22:32 -08:00
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
<div
|
|
|
|
className={`flex justify-between ${
|
|
|
|
fully_diluted_valuation.usd
|
|
|
|
? 'border-t border-th-bkg-3 py-4'
|
|
|
|
: 'pb-4'
|
|
|
|
}`}
|
|
|
|
>
|
|
|
|
<p>{t('token:circulating-supply')}</p>
|
|
|
|
<p className="font-mono text-th-fgd-2">
|
2022-12-11 15:03:14 -08:00
|
|
|
{circulating_supply ? (
|
|
|
|
formatFixedDecimals(circulating_supply)
|
|
|
|
) : (
|
|
|
|
<span className="font-body text-th-fgd-4">
|
|
|
|
{t('unavailable')}
|
|
|
|
</span>
|
|
|
|
)}
|
2022-12-06 16:22:32 -08:00
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
className={`flex justify-between border-t border-th-bkg-3 ${
|
|
|
|
max_supply ? 'py-4' : 'border-b pt-4 md:pb-4'
|
|
|
|
}`}
|
|
|
|
>
|
|
|
|
<p>{t('token:total-supply')}</p>
|
|
|
|
<p className="font-mono text-th-fgd-2">
|
2022-12-11 15:03:14 -08:00
|
|
|
{total_supply ? (
|
|
|
|
formatFixedDecimals(total_supply)
|
|
|
|
) : (
|
|
|
|
<span className="font-body text-th-fgd-4">
|
|
|
|
{t('unavailable')}
|
|
|
|
</span>
|
|
|
|
)}
|
2022-12-06 16:22:32 -08:00
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
{max_supply ? (
|
|
|
|
<div className="flex justify-between border-t border-th-bkg-3 pt-4">
|
|
|
|
<p>{t('token:max-supply')}</p>
|
|
|
|
<p className="font-mono text-th-fgd-2">
|
2022-12-11 15:03:14 -08:00
|
|
|
{max_supply ? (
|
|
|
|
formatFixedDecimals(max_supply)
|
|
|
|
) : (
|
|
|
|
<span className="font-body text-th-fgd-4">
|
|
|
|
{t('unavailable')}
|
|
|
|
</span>
|
|
|
|
)}
|
2022-12-06 16:22:32 -08:00
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
export default CoingeckoStats
|