2022-01-04 11:48:49 -08:00
|
|
|
import { FunctionComponent, useEffect, useMemo, useState } from 'react'
|
2021-12-31 04:17:48 -08:00
|
|
|
import { EyeOffIcon } from '@heroicons/react/outline'
|
|
|
|
import { ChevronDownIcon } from '@heroicons/react/solid'
|
|
|
|
import { Disclosure } from '@headlessui/react'
|
2021-12-30 03:44:14 -08:00
|
|
|
import dayjs from 'dayjs'
|
2022-01-02 16:52:03 -08:00
|
|
|
import relativeTime from 'dayjs/plugin/relativeTime'
|
2021-12-30 03:44:14 -08:00
|
|
|
import { AreaChart, Area, XAxis, YAxis, Tooltip } from 'recharts'
|
|
|
|
import useDimensions from 'react-cool-dimensions'
|
2021-12-31 04:17:48 -08:00
|
|
|
import { IconButton } from './Button'
|
2021-12-31 19:07:14 -08:00
|
|
|
import { LineChartIcon } from './icons'
|
|
|
|
|
|
|
|
dayjs.extend(relativeTime)
|
2021-12-30 03:44:14 -08:00
|
|
|
|
|
|
|
interface SwapTokenInfoProps {
|
|
|
|
inputTokenId?: string
|
|
|
|
outputTokenId?: string
|
|
|
|
}
|
|
|
|
|
2022-01-02 04:20:42 -08:00
|
|
|
export const numberFormatter = Intl.NumberFormat('en', {
|
|
|
|
minimumSignificantDigits: 1,
|
|
|
|
maximumSignificantDigits: 5,
|
|
|
|
notation: 'compact',
|
|
|
|
})
|
|
|
|
|
2021-12-30 03:44:14 -08:00
|
|
|
const SwapTokenInfo: FunctionComponent<SwapTokenInfoProps> = ({
|
|
|
|
inputTokenId,
|
|
|
|
outputTokenId,
|
|
|
|
}) => {
|
2021-12-31 04:17:48 -08:00
|
|
|
const [chartData, setChartData] = useState([])
|
|
|
|
const [hideChart, setHideChart] = useState(false)
|
2022-01-04 13:46:38 -08:00
|
|
|
const [baseTokenId, setBaseTokenId] = useState('mango-markets')
|
|
|
|
const [quoteTokenId, setQuoteTokenId] = useState('usd-coin')
|
2021-12-31 19:07:14 -08:00
|
|
|
const [inputTokenInfo, setInputTokenInfo] = useState(null)
|
2021-12-30 03:44:14 -08:00
|
|
|
const [outputTokenInfo, setOutputTokenInfo] = useState(null)
|
|
|
|
const [mouseData, setMouseData] = useState<string | null>(null)
|
2022-01-02 04:20:42 -08:00
|
|
|
const [daysToShow, setDaysToShow] = useState(1)
|
2021-12-30 03:44:14 -08:00
|
|
|
const { observe, width, height } = useDimensions()
|
|
|
|
|
|
|
|
const handleMouseMove = (coords) => {
|
|
|
|
if (coords.activePayload) {
|
|
|
|
setMouseData(coords.activePayload[0].payload)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const handleMouseLeave = () => {
|
|
|
|
setMouseData(null)
|
|
|
|
}
|
|
|
|
|
2022-01-04 11:48:49 -08:00
|
|
|
useEffect(() => {
|
|
|
|
if (['usd-coin', 'tether'].includes(inputTokenId)) {
|
|
|
|
setBaseTokenId(outputTokenId)
|
|
|
|
setQuoteTokenId(inputTokenId)
|
|
|
|
} else {
|
|
|
|
setBaseTokenId(inputTokenId)
|
|
|
|
setQuoteTokenId(outputTokenId)
|
|
|
|
}
|
|
|
|
}, [inputTokenId, outputTokenId])
|
|
|
|
|
2022-01-02 04:20:42 -08:00
|
|
|
// Use ohlc data
|
2021-12-31 04:17:48 -08:00
|
|
|
|
2021-12-30 03:44:14 -08:00
|
|
|
const getChartData = async () => {
|
|
|
|
const inputResponse = await fetch(
|
2022-01-04 11:48:49 -08:00
|
|
|
`https://api.coingecko.com/api/v3/coins/${baseTokenId}/ohlc?vs_currency=usd&days=${daysToShow}`
|
2021-12-30 03:44:14 -08:00
|
|
|
)
|
|
|
|
const outputResponse = await fetch(
|
2022-01-04 11:48:49 -08:00
|
|
|
`https://api.coingecko.com/api/v3/coins/${quoteTokenId}/ohlc?vs_currency=usd&days=${daysToShow}`
|
2021-12-30 03:44:14 -08:00
|
|
|
)
|
|
|
|
const inputData = await inputResponse.json()
|
|
|
|
const outputData = await outputResponse.json()
|
|
|
|
|
2022-01-02 04:20:42 -08:00
|
|
|
const data = inputData.concat(outputData)
|
2021-12-30 03:44:14 -08:00
|
|
|
|
|
|
|
const formattedData = data.reduce((a, c) => {
|
2022-01-02 04:20:42 -08:00
|
|
|
const found = a.find((price) => price.time === c[0])
|
2021-12-30 03:44:14 -08:00
|
|
|
if (found) {
|
2022-01-02 04:20:42 -08:00
|
|
|
found.price = found.inputPrice / c[4]
|
2021-12-30 03:44:14 -08:00
|
|
|
} else {
|
2022-01-02 04:20:42 -08:00
|
|
|
a.push({ time: c[0], inputPrice: c[4] })
|
2021-12-30 03:44:14 -08:00
|
|
|
}
|
|
|
|
return a
|
|
|
|
}, [])
|
2022-01-02 04:20:42 -08:00
|
|
|
formattedData[formattedData.length - 1].time = Date.now()
|
2021-12-30 03:44:14 -08:00
|
|
|
setChartData(formattedData.filter((d) => d.price))
|
|
|
|
}
|
|
|
|
|
2022-01-02 04:20:42 -08:00
|
|
|
// Alternative chart data. Needs a timestamp tolerance to get data points for each asset
|
|
|
|
|
|
|
|
// const getChartData = async () => {
|
|
|
|
// const now = Date.now() / 1000
|
|
|
|
// const inputResponse = await fetch(
|
|
|
|
// `https://api.coingecko.com/api/v3/coins/${inputTokenId}/market_chart/range?vs_currency=usd&from=${
|
|
|
|
// now - 1 * 86400
|
|
|
|
// }&to=${now}`
|
|
|
|
// )
|
|
|
|
|
|
|
|
// const outputResponse = await fetch(
|
|
|
|
// `https://api.coingecko.com/api/v3/coins/${outputTokenId}/market_chart/range?vs_currency=usd&from=${
|
|
|
|
// now - 1 * 86400
|
|
|
|
// }&to=${now}`
|
|
|
|
// )
|
|
|
|
// const inputData = await inputResponse.json()
|
|
|
|
// const outputData = await outputResponse.json()
|
|
|
|
|
|
|
|
// const data = inputData?.prices.concat(outputData?.prices)
|
|
|
|
|
|
|
|
// const formattedData = data.reduce((a, c) => {
|
|
|
|
// const found = a.find(
|
|
|
|
// (price) => c[0] >= price.time - 120000 && c[0] <= price.time + 120000
|
|
|
|
// )
|
|
|
|
// if (found) {
|
|
|
|
// found.price = found.inputPrice / c[1]
|
|
|
|
// } else {
|
|
|
|
// a.push({ time: c[0], inputPrice: c[1] })
|
|
|
|
// }
|
|
|
|
// return a
|
|
|
|
// }, [])
|
|
|
|
// setChartData(formattedData.filter((d) => d.price))
|
|
|
|
// }
|
|
|
|
|
2021-12-31 19:07:14 -08:00
|
|
|
const getInputTokenInfo = async () => {
|
|
|
|
const response = await fetch(
|
2022-01-04 11:48:49 -08:00
|
|
|
`https://api.coingecko.com/api/v3/coins/${baseTokenId}?localization=false&tickers=false&developer_data=false&sparkline=false
|
2021-12-31 19:07:14 -08:00
|
|
|
`
|
|
|
|
)
|
|
|
|
const data = await response.json()
|
|
|
|
setInputTokenInfo(data)
|
|
|
|
}
|
|
|
|
|
2021-12-30 03:44:14 -08:00
|
|
|
const getOutputTokenInfo = async () => {
|
|
|
|
const response = await fetch(
|
2022-01-04 11:48:49 -08:00
|
|
|
`https://api.coingecko.com/api/v3/coins/${quoteTokenId}?localization=false&tickers=false&developer_data=false&sparkline=false
|
2021-12-30 03:44:14 -08:00
|
|
|
`
|
|
|
|
)
|
|
|
|
const data = await response.json()
|
|
|
|
setOutputTokenInfo(data)
|
|
|
|
}
|
|
|
|
|
|
|
|
useMemo(() => {
|
2022-01-04 11:48:49 -08:00
|
|
|
if (baseTokenId && quoteTokenId) {
|
2021-12-30 03:44:14 -08:00
|
|
|
getChartData()
|
|
|
|
}
|
2022-01-04 11:48:49 -08:00
|
|
|
}, [daysToShow, baseTokenId, quoteTokenId])
|
2021-12-30 03:44:14 -08:00
|
|
|
|
|
|
|
useMemo(() => {
|
2022-01-04 11:48:49 -08:00
|
|
|
if (baseTokenId) {
|
2021-12-31 19:07:14 -08:00
|
|
|
getInputTokenInfo()
|
|
|
|
}
|
2022-01-04 11:48:49 -08:00
|
|
|
if (quoteTokenId) {
|
2021-12-30 03:44:14 -08:00
|
|
|
getOutputTokenInfo()
|
|
|
|
}
|
2022-01-04 11:48:49 -08:00
|
|
|
}, [baseTokenId, quoteTokenId])
|
2021-12-30 03:44:14 -08:00
|
|
|
|
2021-12-31 04:17:48 -08:00
|
|
|
const chartChange = chartData.length
|
|
|
|
? ((chartData[chartData.length - 1]['price'] - chartData[0]['price']) /
|
|
|
|
chartData[0]['price']) *
|
|
|
|
100
|
|
|
|
: 0
|
|
|
|
|
2021-12-30 03:44:14 -08:00
|
|
|
return (
|
|
|
|
<div>
|
2022-01-04 11:48:49 -08:00
|
|
|
{chartData.length && baseTokenId && quoteTokenId ? (
|
2022-01-01 04:34:46 -08:00
|
|
|
<div className="py-6">
|
2022-01-02 04:20:42 -08:00
|
|
|
<div className="flex items-start justify-between">
|
2021-12-30 03:44:14 -08:00
|
|
|
<div>
|
2022-01-04 11:48:49 -08:00
|
|
|
{inputTokenInfo && outputTokenInfo ? (
|
|
|
|
<div className="text-th-fgd-3 text-sm">{`${inputTokenInfo.symbol.toUpperCase()}/${outputTokenInfo.symbol.toUpperCase()}`}</div>
|
2021-12-30 03:44:14 -08:00
|
|
|
) : null}
|
|
|
|
{mouseData ? (
|
|
|
|
<>
|
|
|
|
<div className="font-bold text-lg text-th-fgd-1">
|
2021-12-31 19:07:14 -08:00
|
|
|
{numberFormatter.format(mouseData['price'])}
|
2021-12-31 04:17:48 -08:00
|
|
|
<span
|
2022-01-02 04:20:42 -08:00
|
|
|
className={`ml-2 text-xs ${
|
2021-12-31 04:17:48 -08:00
|
|
|
chartChange >= 0 ? 'text-th-green' : 'text-th-red'
|
|
|
|
}`}
|
|
|
|
>
|
|
|
|
{chartChange.toFixed(2)}%
|
|
|
|
</span>
|
2021-12-30 03:44:14 -08:00
|
|
|
</div>
|
2022-01-02 04:20:42 -08:00
|
|
|
<div className="text-xs font-normal text-th-fgd-3">
|
2021-12-30 03:44:14 -08:00
|
|
|
{dayjs(mouseData['time']).format('DD MMM YY, h:mma')}
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
) : (
|
|
|
|
<>
|
|
|
|
<div className="font-bold text-lg text-th-fgd-1">
|
2021-12-31 19:07:14 -08:00
|
|
|
{numberFormatter.format(
|
|
|
|
chartData[chartData.length - 1]['price']
|
2021-12-30 03:44:14 -08:00
|
|
|
)}
|
2021-12-31 04:17:48 -08:00
|
|
|
<span
|
2022-01-01 04:34:46 -08:00
|
|
|
className={`ml-2 text-xs ${
|
2021-12-31 04:17:48 -08:00
|
|
|
chartChange >= 0 ? 'text-th-green' : 'text-th-red'
|
|
|
|
}`}
|
|
|
|
>
|
|
|
|
{chartChange.toFixed(2)}%
|
|
|
|
</span>
|
2021-12-30 03:44:14 -08:00
|
|
|
</div>
|
2022-01-01 04:34:46 -08:00
|
|
|
<div className="text-xs font-normal text-th-fgd-3">
|
2021-12-30 03:44:14 -08:00
|
|
|
{dayjs(chartData[chartData.length - 1]['time']).format(
|
|
|
|
'DD MMM YY, h:mma'
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
</div>
|
2021-12-31 04:17:48 -08:00
|
|
|
<IconButton onClick={() => setHideChart(!hideChart)}>
|
|
|
|
{hideChart ? (
|
2021-12-31 19:07:14 -08:00
|
|
|
<LineChartIcon className="w-4 h-4" />
|
2021-12-31 04:17:48 -08:00
|
|
|
) : (
|
|
|
|
<EyeOffIcon className="w-4 h-4" />
|
|
|
|
)}
|
|
|
|
</IconButton>
|
2021-12-30 03:44:14 -08:00
|
|
|
</div>
|
2021-12-31 04:17:48 -08:00
|
|
|
{!hideChart ? (
|
|
|
|
<div className="h-52 mt-4 w-full" ref={observe}>
|
|
|
|
<AreaChart
|
|
|
|
width={width}
|
|
|
|
height={height}
|
|
|
|
data={chartData}
|
|
|
|
onMouseMove={handleMouseMove}
|
|
|
|
onMouseLeave={handleMouseLeave}
|
|
|
|
>
|
|
|
|
<Tooltip
|
|
|
|
cursor={{
|
|
|
|
strokeOpacity: 0,
|
|
|
|
}}
|
|
|
|
content={<></>}
|
|
|
|
/>
|
|
|
|
<defs>
|
|
|
|
<linearGradient id="gradientArea" x1="0" y1="0" x2="0" y2="1">
|
|
|
|
<stop offset="0%" stopColor="#FF9C24" stopOpacity={0.5} />
|
|
|
|
<stop offset="100%" stopColor="#FF9C24" stopOpacity={0} />
|
|
|
|
</linearGradient>
|
|
|
|
</defs>
|
|
|
|
<Area
|
|
|
|
isAnimationActive={true}
|
|
|
|
type="monotone"
|
|
|
|
dataKey="price"
|
|
|
|
stroke="#FF9C24"
|
|
|
|
fill="url(#gradientArea)"
|
|
|
|
/>
|
|
|
|
<XAxis dataKey="time" hide />
|
|
|
|
<YAxis
|
|
|
|
dataKey="price"
|
|
|
|
type="number"
|
|
|
|
domain={['dataMin', 'dataMax']}
|
|
|
|
hide
|
|
|
|
/>
|
|
|
|
</AreaChart>
|
2022-01-02 04:20:42 -08:00
|
|
|
<div className="flex justify-end">
|
|
|
|
<button
|
|
|
|
className={`default-transition font-bold px-3 py-2 text-th-fgd-1 text-xs hover:text-th-primary focus:outline-none ${
|
|
|
|
daysToShow === 1 && 'text-th-primary'
|
|
|
|
}`}
|
|
|
|
onClick={() => setDaysToShow(1)}
|
|
|
|
>
|
|
|
|
24H
|
|
|
|
</button>
|
|
|
|
<button
|
|
|
|
className={`default-transition font-bold px-3 py-2 text-th-fgd-1 text-xs hover:text-th-primary focus:outline-none ${
|
|
|
|
daysToShow === 7 && 'text-th-primary'
|
|
|
|
}`}
|
|
|
|
onClick={() => setDaysToShow(7)}
|
|
|
|
>
|
|
|
|
7D
|
|
|
|
</button>
|
|
|
|
<button
|
|
|
|
className={`default-transition font-bold px-3 py-2 text-th-fgd-1 text-xs hover:text-th-primary focus:outline-none ${
|
|
|
|
daysToShow === 30 && 'text-th-primary'
|
|
|
|
}`}
|
|
|
|
onClick={() => setDaysToShow(30)}
|
|
|
|
>
|
|
|
|
30D
|
|
|
|
</button>
|
|
|
|
</div>
|
2021-12-31 04:17:48 -08:00
|
|
|
</div>
|
|
|
|
) : null}
|
2021-12-30 03:44:14 -08:00
|
|
|
</div>
|
|
|
|
) : (
|
2022-01-02 04:20:42 -08:00
|
|
|
<div className="bg-th-bkg-3 mt-4 md:mt-0 p-4 rounded-md text-center text-th-fgd-3">
|
|
|
|
<LineChartIcon className="h-6 mx-auto text-th-primary w-6" />
|
2021-12-30 03:44:14 -08:00
|
|
|
Chart not available
|
|
|
|
</div>
|
|
|
|
)}
|
2021-12-31 04:17:48 -08:00
|
|
|
|
2022-01-02 04:20:42 -08:00
|
|
|
{inputTokenInfo && inputTokenId ? (
|
2022-01-01 04:34:46 -08:00
|
|
|
<div className="w-full">
|
2021-12-31 04:17:48 -08:00
|
|
|
<Disclosure>
|
|
|
|
{({ open }) => (
|
|
|
|
<>
|
|
|
|
<Disclosure.Button
|
2022-01-02 04:20:42 -08:00
|
|
|
className={`border border-th-bkg-4 default-transition flex items-center justify-between mt-6 p-3 rounded-md w-full hover:bg-th-bkg-2 ${
|
2021-12-31 04:17:48 -08:00
|
|
|
open
|
|
|
|
? 'border-b-transparent rounded-b-none'
|
|
|
|
: 'transform rotate-360'
|
|
|
|
}`}
|
|
|
|
>
|
2021-12-31 19:07:14 -08:00
|
|
|
<div className="flex items-center">
|
|
|
|
{inputTokenInfo.image?.small ? (
|
|
|
|
<img
|
|
|
|
src={inputTokenInfo.image?.small}
|
|
|
|
width="32"
|
|
|
|
height="32"
|
|
|
|
alt={inputTokenInfo.name}
|
|
|
|
/>
|
|
|
|
) : null}
|
|
|
|
<div className="ml-2.5 text-left">
|
|
|
|
<h2 className="font-bold text-base text-th-fgd-1">
|
|
|
|
{inputTokenInfo.symbol.toUpperCase()}
|
|
|
|
</h2>
|
|
|
|
<div className="font-normal text-th-fgd-3 text-xs">
|
|
|
|
{inputTokenInfo.name}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className="flex items-center">
|
2022-01-01 04:34:46 -08:00
|
|
|
<div className="flex items-center space-x-3">
|
2021-12-31 19:07:14 -08:00
|
|
|
{inputTokenInfo.market_data?.current_price?.usd ? (
|
|
|
|
<div className="font-normal text-th-fgd-1">
|
|
|
|
$
|
|
|
|
{numberFormatter.format(
|
|
|
|
inputTokenInfo.market_data.current_price.usd
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
{inputTokenInfo.market_data
|
|
|
|
?.price_change_percentage_24h ? (
|
|
|
|
<div
|
|
|
|
className={`font-normal text-th-fgd-1 ${
|
|
|
|
inputTokenInfo.market_data
|
|
|
|
.price_change_percentage_24h >= 0
|
|
|
|
? 'text-th-green'
|
|
|
|
: 'text-th-red'
|
|
|
|
}`}
|
|
|
|
>
|
|
|
|
{inputTokenInfo.market_data.price_change_percentage_24h.toFixed(
|
|
|
|
2
|
|
|
|
)}
|
|
|
|
%
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
</div>
|
|
|
|
<ChevronDownIcon
|
|
|
|
className={`default-transition h-6 ml-2 w-6 text-th-fgd-3 ${
|
|
|
|
open ? 'transform rotate-180' : 'transform rotate-360'
|
|
|
|
}`}
|
|
|
|
/>
|
|
|
|
</div>
|
2021-12-31 04:17:48 -08:00
|
|
|
</Disclosure.Button>
|
|
|
|
<Disclosure.Panel>
|
2021-12-31 19:07:14 -08:00
|
|
|
<div className="border border-th-bkg-4 border-t-0 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-2 xl:grid-cols-3 grid-flow-row p-3 rounded-b-md">
|
|
|
|
{inputTokenInfo.market_cap_rank ? (
|
2021-12-31 04:17:48 -08:00
|
|
|
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
2021-12-31 19:07:14 -08:00
|
|
|
<div className="text-th-fgd-3 text-xs">
|
2021-12-31 04:17:48 -08:00
|
|
|
Market Cap Rank
|
|
|
|
</div>
|
|
|
|
<div className="font-bold text-th-fgd-1 text-lg">
|
2021-12-31 19:07:14 -08:00
|
|
|
#{inputTokenInfo.market_cap_rank}
|
2021-12-31 04:17:48 -08:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
) : null}
|
2021-12-31 19:07:14 -08:00
|
|
|
{inputTokenInfo.market_data?.market_cap ? (
|
2021-12-31 04:17:48 -08:00
|
|
|
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
2021-12-31 19:07:14 -08:00
|
|
|
<div className="text-th-fgd-3 text-xs">Market Cap</div>
|
2021-12-31 04:17:48 -08:00
|
|
|
<div className="font-bold text-th-fgd-1 text-lg">
|
|
|
|
$
|
2021-12-31 19:07:14 -08:00
|
|
|
{numberFormatter.format(
|
|
|
|
inputTokenInfo.market_data?.market_cap?.usd
|
|
|
|
)}
|
2021-12-31 04:17:48 -08:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
) : null}
|
2021-12-31 19:07:14 -08:00
|
|
|
{inputTokenInfo.market_data.total_volume?.usd ? (
|
|
|
|
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
|
|
|
<div className="text-th-fgd-3 text-xs">24h Volume</div>
|
|
|
|
<div className="font-bold text-th-fgd-1 text-lg">
|
|
|
|
$
|
|
|
|
{numberFormatter.format(
|
|
|
|
inputTokenInfo.market_data.total_volume?.usd
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
{inputTokenInfo.market_data?.circulating_supply ? (
|
|
|
|
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
|
|
|
<div className="text-th-fgd-3 text-xs">
|
|
|
|
Token Supply
|
|
|
|
</div>
|
|
|
|
<div className="font-bold text-th-fgd-1 text-lg">
|
|
|
|
{numberFormatter.format(
|
|
|
|
inputTokenInfo.market_data.circulating_supply
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
{inputTokenInfo.market_data?.max_supply ? (
|
|
|
|
<div className="text-th-fgd-2 text-xs">
|
|
|
|
Max Supply:{' '}
|
|
|
|
{numberFormatter.format(
|
|
|
|
inputTokenInfo.market_data.max_supply
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
{inputTokenInfo.market_data?.ath?.usd ? (
|
|
|
|
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
|
|
|
<div className="text-th-fgd-3 text-xs">
|
|
|
|
All-Time High
|
|
|
|
</div>
|
|
|
|
<div className="flex">
|
|
|
|
<div className="font-bold text-th-fgd-1 text-lg">
|
|
|
|
$
|
|
|
|
{numberFormatter.format(
|
|
|
|
inputTokenInfo.market_data.ath.usd
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
{inputTokenInfo.market_data?.ath_change_percentage
|
|
|
|
?.usd ? (
|
|
|
|
<div
|
|
|
|
className={`ml-1.5 mt-2 text-xs ${
|
|
|
|
inputTokenInfo.market_data
|
|
|
|
?.ath_change_percentage?.usd >= 0
|
|
|
|
? 'text-th-green'
|
|
|
|
: 'text-th-red'
|
|
|
|
}`}
|
|
|
|
>
|
|
|
|
{(inputTokenInfo.market_data?.ath_change_percentage?.usd).toFixed(
|
|
|
|
2
|
|
|
|
)}
|
|
|
|
%
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
</div>
|
|
|
|
{inputTokenInfo.market_data?.ath_date?.usd ? (
|
|
|
|
<div className="text-th-fgd-2 text-xs">
|
|
|
|
{dayjs(
|
|
|
|
inputTokenInfo.market_data.ath_date.usd
|
|
|
|
).fromNow()}
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
{inputTokenInfo.market_data?.atl?.usd ? (
|
|
|
|
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
|
|
|
<div className="text-th-fgd-3 text-xs">
|
|
|
|
All-Time Low
|
|
|
|
</div>
|
|
|
|
<div className="flex">
|
|
|
|
<div className="font-bold text-th-fgd-1 text-lg">
|
|
|
|
$
|
|
|
|
{numberFormatter.format(
|
|
|
|
inputTokenInfo.market_data.atl.usd
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
{inputTokenInfo.market_data?.atl_change_percentage
|
|
|
|
?.usd ? (
|
|
|
|
<div
|
|
|
|
className={`ml-1.5 mt-2 text-xs ${
|
|
|
|
inputTokenInfo.market_data
|
|
|
|
?.atl_change_percentage?.usd >= 0
|
|
|
|
? 'text-th-green'
|
|
|
|
: 'text-th-red'
|
|
|
|
}`}
|
|
|
|
>
|
|
|
|
{(inputTokenInfo.market_data?.atl_change_percentage?.usd).toLocaleString(
|
|
|
|
undefined,
|
|
|
|
{
|
|
|
|
minimumFractionDigits: 0,
|
|
|
|
maximumFractionDigits: 2,
|
|
|
|
}
|
|
|
|
)}
|
|
|
|
%
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
</div>
|
|
|
|
{inputTokenInfo.market_data?.atl_date?.usd ? (
|
|
|
|
<div className="text-th-fgd-2 text-xs">
|
|
|
|
{dayjs(
|
|
|
|
inputTokenInfo.market_data.atl_date.usd
|
|
|
|
).fromNow()}
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
</div>
|
|
|
|
</Disclosure.Panel>
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
</Disclosure>
|
|
|
|
</div>
|
|
|
|
) : (
|
2022-01-02 04:20:42 -08:00
|
|
|
<div className="bg-th-bkg-3 mt-3 p-4 rounded-md text-center text-th-fgd-3">
|
|
|
|
Input token information is not available.
|
2021-12-31 19:07:14 -08:00
|
|
|
</div>
|
|
|
|
)}
|
|
|
|
|
2022-01-02 04:20:42 -08:00
|
|
|
{outputTokenInfo && outputTokenId ? (
|
2022-01-01 04:34:46 -08:00
|
|
|
<div className="w-full">
|
2021-12-31 19:07:14 -08:00
|
|
|
<Disclosure>
|
|
|
|
{({ open }) => (
|
|
|
|
<>
|
|
|
|
<Disclosure.Button
|
2022-01-01 04:34:46 -08:00
|
|
|
className={`border border-th-bkg-4 default-transition flex items-center justify-between mt-3 p-3 rounded-md w-full hover:bg-th-bkg-2 ${
|
2021-12-31 19:07:14 -08:00
|
|
|
open
|
|
|
|
? 'border-b-transparent rounded-b-none'
|
|
|
|
: 'transform rotate-360'
|
|
|
|
}`}
|
|
|
|
>
|
|
|
|
<div className="flex items-center">
|
|
|
|
{outputTokenInfo.image?.small ? (
|
|
|
|
<img
|
|
|
|
src={outputTokenInfo.image?.small}
|
|
|
|
width="32"
|
|
|
|
height="32"
|
|
|
|
alt={outputTokenInfo.name}
|
|
|
|
/>
|
|
|
|
) : null}
|
|
|
|
<div className="ml-2.5 text-left">
|
|
|
|
<h2 className="font-bold text-base text-th-fgd-1">
|
|
|
|
{outputTokenInfo.symbol.toUpperCase()}
|
|
|
|
</h2>
|
|
|
|
<div className="font-normal text-th-fgd-3 text-xs">
|
|
|
|
{outputTokenInfo.name}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div className="flex items-center">
|
2022-01-01 04:34:46 -08:00
|
|
|
<div className="flex items-center space-x-3">
|
2021-12-31 19:07:14 -08:00
|
|
|
{outputTokenInfo.market_data?.current_price?.usd ? (
|
|
|
|
<div className="font-normal text-th-fgd-1">
|
|
|
|
$
|
|
|
|
{numberFormatter.format(
|
|
|
|
outputTokenInfo.market_data.current_price.usd
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
{outputTokenInfo.market_data
|
|
|
|
?.price_change_percentage_24h ? (
|
|
|
|
<div
|
|
|
|
className={`font-normal text-th-fgd-1 ${
|
|
|
|
outputTokenInfo.market_data
|
|
|
|
.price_change_percentage_24h >= 0
|
|
|
|
? 'text-th-green'
|
|
|
|
: 'text-th-red'
|
|
|
|
}`}
|
|
|
|
>
|
|
|
|
{outputTokenInfo.market_data.price_change_percentage_24h.toFixed(
|
|
|
|
2
|
|
|
|
)}
|
|
|
|
%
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
</div>
|
|
|
|
<ChevronDownIcon
|
|
|
|
className={`default-transition h-6 ml-2 w-6 text-th-fgd-3 ${
|
|
|
|
open ? 'transform rotate-180' : 'transform rotate-360'
|
|
|
|
}`}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</Disclosure.Button>
|
|
|
|
<Disclosure.Panel>
|
|
|
|
<div className="border border-th-bkg-4 border-t-0 grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-2 xl:grid-cols-3 grid-flow-row p-3 rounded-b-md">
|
2021-12-31 04:17:48 -08:00
|
|
|
{outputTokenInfo.market_cap_rank ? (
|
|
|
|
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
2021-12-31 19:07:14 -08:00
|
|
|
<div className="text-th-fgd-3 text-xs">
|
2021-12-31 04:17:48 -08:00
|
|
|
Market Cap Rank
|
|
|
|
</div>
|
|
|
|
<div className="font-bold text-th-fgd-1 text-lg">
|
|
|
|
#{outputTokenInfo.market_cap_rank}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
{outputTokenInfo.market_data?.market_cap ? (
|
|
|
|
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
2021-12-31 19:07:14 -08:00
|
|
|
<div className="text-th-fgd-3 text-xs">Market Cap</div>
|
|
|
|
<div className="font-bold text-th-fgd-1 text-lg">
|
|
|
|
$
|
|
|
|
{numberFormatter.format(
|
|
|
|
outputTokenInfo.market_data?.market_cap?.usd
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
{outputTokenInfo.market_data.total_volume?.usd ? (
|
|
|
|
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
|
|
|
<div className="text-th-fgd-3 text-xs">24h Volume</div>
|
2021-12-31 04:17:48 -08:00
|
|
|
<div className="font-bold text-th-fgd-1 text-lg">
|
|
|
|
$
|
2021-12-31 19:07:14 -08:00
|
|
|
{numberFormatter.format(
|
|
|
|
outputTokenInfo.market_data.total_volume?.usd
|
|
|
|
)}
|
2021-12-31 04:17:48 -08:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
) : null}
|
2021-12-31 19:07:14 -08:00
|
|
|
{outputTokenInfo.market_data?.circulating_supply ? (
|
|
|
|
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
|
|
|
<div className="text-th-fgd-3 text-xs">
|
|
|
|
Token Supply
|
|
|
|
</div>
|
|
|
|
<div className="font-bold text-th-fgd-1 text-lg">
|
|
|
|
{numberFormatter.format(
|
|
|
|
outputTokenInfo.market_data.circulating_supply
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
{outputTokenInfo.market_data?.max_supply ? (
|
|
|
|
<div className="text-th-fgd-2 text-xs">
|
|
|
|
Max Supply:{' '}
|
|
|
|
{numberFormatter.format(
|
|
|
|
outputTokenInfo.market_data.max_supply
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
{outputTokenInfo.market_data?.ath?.usd ? (
|
|
|
|
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
|
|
|
<div className="text-th-fgd-3 text-xs">
|
|
|
|
All-Time High
|
|
|
|
</div>
|
|
|
|
<div className="flex">
|
|
|
|
<div className="font-bold text-th-fgd-1 text-lg">
|
|
|
|
$
|
|
|
|
{numberFormatter.format(
|
|
|
|
outputTokenInfo.market_data.ath.usd
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
{outputTokenInfo.market_data?.ath_change_percentage
|
|
|
|
?.usd ? (
|
|
|
|
<div
|
|
|
|
className={`ml-1.5 mt-2 text-xs ${
|
|
|
|
outputTokenInfo.market_data
|
|
|
|
?.ath_change_percentage?.usd >= 0
|
|
|
|
? 'text-th-green'
|
|
|
|
: 'text-th-red'
|
|
|
|
}`}
|
|
|
|
>
|
|
|
|
{(outputTokenInfo.market_data?.ath_change_percentage?.usd).toFixed(
|
|
|
|
2
|
|
|
|
)}
|
|
|
|
%
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
</div>
|
|
|
|
{outputTokenInfo.market_data?.ath_date?.usd ? (
|
|
|
|
<div className="text-th-fgd-2 text-xs">
|
|
|
|
{dayjs(
|
|
|
|
outputTokenInfo.market_data.ath_date.usd
|
|
|
|
).fromNow()}
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
{outputTokenInfo.market_data?.atl?.usd ? (
|
|
|
|
<div className="border border-th-bkg-4 m-1 p-3 rounded-md">
|
|
|
|
<div className="text-th-fgd-3 text-xs">
|
|
|
|
All-Time Low
|
|
|
|
</div>
|
|
|
|
<div className="flex">
|
|
|
|
<div className="font-bold text-th-fgd-1 text-lg">
|
|
|
|
$
|
|
|
|
{numberFormatter.format(
|
|
|
|
outputTokenInfo.market_data.atl.usd
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
{outputTokenInfo.market_data?.atl_change_percentage
|
|
|
|
?.usd ? (
|
|
|
|
<div
|
|
|
|
className={`ml-1.5 mt-2 text-xs ${
|
|
|
|
outputTokenInfo.market_data
|
|
|
|
?.atl_change_percentage?.usd >= 0
|
|
|
|
? 'text-th-green'
|
|
|
|
: 'text-th-red'
|
|
|
|
}`}
|
|
|
|
>
|
|
|
|
{(outputTokenInfo.market_data?.atl_change_percentage?.usd).toLocaleString(
|
|
|
|
undefined,
|
|
|
|
{
|
|
|
|
minimumFractionDigits: 0,
|
|
|
|
maximumFractionDigits: 2,
|
|
|
|
}
|
|
|
|
)}
|
|
|
|
%
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
</div>
|
|
|
|
{outputTokenInfo.market_data?.atl_date?.usd ? (
|
|
|
|
<div className="text-th-fgd-2 text-xs">
|
|
|
|
{dayjs(
|
|
|
|
outputTokenInfo.market_data.atl_date.usd
|
|
|
|
).fromNow()}
|
|
|
|
</div>
|
|
|
|
) : null}
|
|
|
|
</div>
|
|
|
|
) : null}
|
2021-12-31 04:17:48 -08:00
|
|
|
</div>
|
|
|
|
</Disclosure.Panel>
|
|
|
|
</>
|
|
|
|
)}
|
|
|
|
</Disclosure>
|
2021-12-30 03:44:14 -08:00
|
|
|
</div>
|
2021-12-31 19:07:14 -08:00
|
|
|
) : (
|
2022-01-02 04:20:42 -08:00
|
|
|
<div className="bg-th-bkg-3 mt-3 p-4 rounded-md text-center text-th-fgd-3">
|
|
|
|
Output token information is not available.
|
2021-12-31 19:07:14 -08:00
|
|
|
</div>
|
|
|
|
)}
|
2021-12-30 03:44:14 -08:00
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
export default SwapTokenInfo
|