import { useTranslation } from 'next-i18next' import { useCallback } from 'react' import { useViewport } from '../../../hooks/useViewport' import { COLORS } from '../../../styles/colors' import { breakpoints } from '../../../utils/theme' import ContentBox from '../../shared/ContentBox' import MarketLogos from '@components/trade/MarketLogos' import useMangoGroup from 'hooks/useMangoGroup' import { SortableColumnHeader, Table, Td, Th, TrBody, TrHead, } from '@components/shared/TableElements' import FormatNumericValue from '@components/shared/FormatNumericValue' import { floorToDecimal, getDecimalCount, numberCompacter } from 'utils/numbers' import SimpleAreaChart from '@components/shared/SimpleAreaChart' import { Disclosure, Transition } from '@headlessui/react' import { ChevronDownIcon } from '@heroicons/react/20/solid' import useThemeWrapper from 'hooks/useThemeWrapper' import useListedMarketsWithMarketData, { SerumMarketWithMarketData, } from 'hooks/useListedMarketsWithMarketData' import { sortSpotMarkets } from 'utils/markets' import { useSortableData } from 'hooks/useSortableData' import Change from '@components/shared/Change' import { Bank } from '@blockworks-foundation/mango-v4' type TableData = { baseBank: Bank | undefined change: number market: SerumMarketWithMarketData marketName: string price: number priceHistory: | { price: number time: string }[] | undefined quoteBank: Bank | undefined volume: number isUp: boolean } const SpotMarketsTable = () => { const { t } = useTranslation('common') const { group } = useMangoGroup() const { theme } = useThemeWrapper() const { width } = useViewport() const showTableView = width ? width > breakpoints.md : false const { serumMarketsWithData, isLoading, isFetching } = useListedMarketsWithMarketData() const formattedTableData = useCallback( (markets: SerumMarketWithMarketData[]) => { const formatted = [] for (const m of markets) { const baseBank = group?.getFirstBankByTokenIndex(m.baseTokenIndex) const quoteBank = group?.getFirstBankByTokenIndex(m.quoteTokenIndex) const market = group?.getSerum3ExternalMarket(m.serumMarketExternal) let price = 0 if (baseBank && market && quoteBank) { price = floorToDecimal( baseBank.uiPrice / quoteBank.uiPrice, getDecimalCount(market.tickSize), ).toNumber() } const pastPrice = m?.marketData?.price_24h || 0 const priceHistory = m?.marketData?.price_history const volume = m?.marketData?.quote_volume_24h || 0 const change = volume > 0 ? ((price - pastPrice) / pastPrice) * 100 : 0 const marketName = m.name const isUp = price && priceHistory && priceHistory.length ? price >= priceHistory[0].price : false const data = { baseBank, change, market: m, marketName, price, priceHistory, quoteBank, volume, isUp, } formatted.push(data) } return formatted }, [group], ) const { items: tableData, requestSort, sortConfig, } = useSortableData( formattedTableData( sortSpotMarkets(serumMarketsWithData, 'quote_volume_24h'), ), ) const loadingMarketData = isLoading || isFetching return ( {showTableView ? ( {tableData.map((data) => { const { baseBank, change, market, marketName, price, priceHistory, quoteBank, volume, isUp, } = data return ( ) })}
requestSort('marketName')} sortConfig={sortConfig} title={t('market')} />
requestSort('price')} sortConfig={sortConfig} title={t('price')} />
requestSort('change')} sortConfig={sortConfig} title={t('rolling-change')} />
requestSort('volume')} sortConfig={sortConfig} title={t('trade:24h-volume')} />

{marketName}

{price ? ( <> {' '} {quoteBank?.name !== 'USDC' ? ( {quoteBank?.name} ) : null} ) : ( '–' )}

{!loadingMarketData ? ( priceHistory && priceHistory.length ? (
) : baseBank?.name === 'USDC' || baseBank?.name === 'USDT' ? null : (

{t('unavailable')}

) ) : (
)}

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

) : (
{tableData.map((data) => { return ( ) })}
)}
) } export default SpotMarketsTable const MobileSpotMarketItem = ({ data, loadingMarketData, }: { data: TableData loadingMarketData: boolean }) => { const { t } = useTranslation('common') const { theme } = useThemeWrapper() const { baseBank, change, market, marketName, price, priceHistory, quoteBank, volume, isUp, } = data return ( {({ open }) => ( <>

{marketName}

{!loadingMarketData ? ( priceHistory && priceHistory.length ? (
) : (

{t('unavailable')}

) ) : (
)}

{t('price')}

{price ? ( <> {' '} {quoteBank?.name !== 'USDC' ? ( {quoteBank?.name} ) : null} ) : ( '-' )}

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

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

)} ) }