import { useTranslation } from 'next-i18next' import MarketLogos from '@components/trade/MarketLogos' import { Table, Td, Th, TrBody, TrHead } from '@components/shared/TableElements' import { formatFunding, usePerpFundingRate, } from '@components/trade/PerpFundingRate' import { ChevronDownIcon, ChevronRightIcon } from '@heroicons/react/20/solid' import FormatNumericValue from '@components/shared/FormatNumericValue' import { getDecimalCount, numberCompacter } from 'utils/numbers' import Tooltip from '@components/shared/Tooltip' import { useRouter } from 'next/router' import SimpleAreaChart from '@components/shared/SimpleAreaChart' import { Disclosure, Transition } from '@headlessui/react' import { LinkButton } from '@components/shared/Button' import SoonBadge from '@components/shared/SoonBadge' import MarketChange from '@components/shared/MarketChange' import useThemeWrapper from 'hooks/useThemeWrapper' import useListedMarketsWithMarketData, { PerpMarketWithMarketData, } from 'hooks/useListedMarketsWithMarketData' import { sortPerpMarkets } from 'utils/markets' import { useViewport } from 'hooks/useViewport' import { breakpoints } from 'utils/theme' import ContentBox from '@components/shared/ContentBox' import { COLORS } from 'styles/colors' import { goToPerpMarketDetails } from '@components/stats/perps/PerpMarketDetailsTable' const PerpMarketsTable = () => { const { t } = useTranslation(['common', 'trade']) const { theme } = useThemeWrapper() const { width } = useViewport() const showTableView = width ? width > breakpoints.md : false const rate = usePerpFundingRate() const router = useRouter() const { perpMarketsWithData, isLoading } = useListedMarketsWithMarketData() return ( {showTableView ? (
{sortPerpMarkets(perpMarketsWithData, 'quote_volume_24h').map( (market) => { const symbol = market.name.split('-')[0] const priceHistory = market?.marketData?.price_history const volumeData = market?.marketData?.quote_volume_24h const volume = volumeData ? volumeData : 0 let fundingRate let fundingRateApr if (rate.isSuccess) { const marketRate = rate?.data?.find( (r) => r.market_index === market.perpMarketIndex, ) if (marketRate) { fundingRate = formatFunding.format( marketRate.funding_rate_hourly, ) fundingRateApr = formatFunding.format( marketRate.funding_rate_hourly * 8760, ) } else { fundingRate = '–' fundingRateApr = '–' } } else { fundingRate = '–' fundingRateApr = '–' } const openInterest = market.baseLotsToUi(market.openInterest) const isComingSoon = market.oracleLastUpdatedSlot == 0 const isUp = priceHistory && priceHistory.length ? market.uiPrice >= priceHistory[0].price : false return ( goToPerpMarketDetails(market.name, router)} > ) }, )}
{t('market')} {t('price')} {t('rolling-change')} {t('trade:24h-volume')} {t('trade:funding-rate')} {t('trade:open-interest')}

{market.name}

{isComingSoon ? : null}

{market.uiPrice ? ( ) : ( '–' )}

{!isLoading ? ( priceHistory && priceHistory?.length ? (
) : symbol === 'USDC' || symbol === 'USDT' ? null : (

{t('unavailable')}

) ) : (
)}

{volume ? `$${numberCompacter.format(volume)}` : '$0'}

{fundingRate !== '–' ? ( {fundingRateApr ? (
The 1hr rate as an APR is{' '} {fundingRateApr}
) : null}
Funding is paid continuously. The 1hr rate displayed is a rolling average of the past 60 mins.
When positive, longs will pay shorts and when negative shorts pay longs.
} >

{fundingRate}

) : (

)}
{openInterest ? ( <>

$ {numberCompacter.format( openInterest * market.uiPrice, )}

) : ( <>

)}
) : (
{sortPerpMarkets(perpMarketsWithData, 'quote_volume_24h').map( (market) => { return ( ) }, )}
)}
) } export default PerpMarketsTable const MobilePerpMarketItem = ({ market, loadingMarketData, }: { market: PerpMarketWithMarketData loadingMarketData: boolean }) => { const { t } = useTranslation('common') const { theme } = useThemeWrapper() const router = useRouter() const rate = usePerpFundingRate() const priceHistory = market?.marketData?.price_history const volumeData = market?.marketData?.quote_volume_24h const volume = volumeData ? volumeData : 0 const symbol = market.name.split('-')[0] const openInterest = market.baseLotsToUi(market.openInterest) const isComingSoon = market.oracleLastUpdatedSlot == 0 const isUp = priceHistory && priceHistory.length ? market.uiPrice >= priceHistory[0].price : false let fundingRate: string let fundingRateApr: string if (rate.isSuccess) { const marketRate = rate?.data?.find( (r) => r.market_index === market.perpMarketIndex, ) if (marketRate) { fundingRate = formatFunding.format(marketRate.funding_rate_hourly) fundingRateApr = formatFunding.format( marketRate.funding_rate_hourly * 8760, ) } else { fundingRate = '–' fundingRateApr = '–' } } else { fundingRate = '–' fundingRateApr = '–' } return ( {({ open }) => ( <>

{market.name}

{isComingSoon ? : null}
{!loadingMarketData ? ( priceHistory && priceHistory.length ? (
) : symbol === 'USDC' || symbol === 'USDT' ? null : (

{t('unavailable')}

) ) : (
)}

{market.uiPrice ? ( ) : ( '–' )}

{t('price')}

{market.uiPrice ? ( ) : ( '–' )}

{t('trade:24h-volume')}

{volume ? ( {numberCompacter.format(volume)} ) : ( '$0' )}

{t('trade:funding-rate')}

{fundingRate !== '–' ? ( {fundingRateApr ? (
The 1hr rate as an APR is{' '} {fundingRateApr}
) : null}
Funding is paid continuously. The 1hr rate displayed is a rolling average of the past 60 mins.
When positive, longs will pay shorts and when negative shorts pay longs.
} > {fundingRate}
) : (

)}

{t('trade:open-interest')}

{openInterest ? (

|$ {numberCompacter.format(openInterest * market.uiPrice)}

) : (

)}
goToPerpMarketDetails(market.name, router)} > {t('token:token-stats', { token: market.name })}
)} ) }