mango-ui-v3/components/MarketDetails.tsx

192 lines
6.9 KiB
TypeScript

import React, { useMemo } from 'react'
import useMangoStore from '../stores/useMangoStore'
import UiLock from './UiLock'
import ManualRefresh from './ManualRefresh'
import useOraclePrice from '../hooks/useOraclePrice'
import DayHighLow from './DayHighLow'
import {
getPrecisionDigits,
perpContractPrecision,
usdFormatter,
} from '../utils'
import { useViewport } from '../hooks/useViewport'
import { breakpoints } from './TradePageGrid'
import { useTranslation } from 'next-i18next'
import SwitchMarketDropdown from './SwitchMarketDropdown'
import Tooltip from './Tooltip'
import { useWallet } from '@solana/wallet-adapter-react'
import { InformationCircleIcon } from '@heroicons/react/solid'
const OraclePrice = () => {
const oraclePrice = useOraclePrice()
const selectedMarket = useMangoStore((s) => s.selectedMarket.current)
const decimals = useMemo(
() =>
selectedMarket?.tickSize !== undefined
? getPrecisionDigits(selectedMarket?.tickSize)
: null,
[selectedMarket]
)
return (
<div className="text-th-fgd-1 md:text-xs">
{decimals && oraclePrice && selectedMarket
? oraclePrice.toNumber().toLocaleString(undefined, {
minimumFractionDigits: decimals,
maximumFractionDigits: decimals,
})
: '--'}
</div>
)
}
const MarketDetails = () => {
const { t } = useTranslation('common')
const { connected } = useWallet()
const marketConfig = useMangoStore((s) => s.selectedMarket.config)
const baseSymbol = marketConfig.baseSymbol
const selectedMarketName = marketConfig.name
const isPerpMarket = marketConfig.kind === 'perp'
const { width } = useViewport()
const isMobile = width ? width < breakpoints.sm : false
const marketsInfo = useMangoStore((s) => s.marketsInfo)
const market = useMemo(
() => marketsInfo.find((market) => market.name === selectedMarketName),
[marketsInfo, selectedMarketName]
)
return (
<div
className={`relative flex flex-col md:px-3 md:pt-3 md:pb-2 lg:flex-row lg:items-end lg:justify-between`}
>
<div className="flex flex-col lg:flex-row lg:flex-wrap">
<div className="hidden md:block md:pr-6 lg:pb-0">
<div className="flex items-center">
<SwitchMarketDropdown />
</div>
</div>
<div className="grid grid-flow-row grid-cols-1 gap-2 md:mt-2.5 md:grid-cols-3 md:pr-20 lg:grid-flow-col lg:grid-cols-none lg:grid-rows-1 lg:gap-6">
<div className="flex items-center justify-between md:block">
<div className="text-th-fgd-3 md:pb-0.5 md:text-[0.65rem]">
{t('oracle-price')}
</div>
<OraclePrice />
</div>
{market ? (
<>
<div className="flex items-center justify-between md:block">
<div className="text-th-fgd-3 md:pb-0.5 md:text-[0.65rem]">
{t('rolling-change')}
</div>
<div
className={`md:text-xs ${
market.change24h > 0
? `text-th-green`
: market.change24h < 0
? `text-th-red`
: `text-th-fgd-1`
}`}
>
{(market.change24h * 100).toFixed(2) + '%'}
</div>
</div>
{isPerpMarket ? (
<>
<div className="flex items-center justify-between md:block">
<div className="text-th-fgd-3 md:pb-0.5 md:text-[0.65rem]">
{t('daily-volume')}
</div>
<div className="text-th-fgd-1 md:text-xs">
{usdFormatter(market?.volumeUsd24h, 0)}
</div>
</div>
<div className="flex items-center justify-between md:block">
<div className="flex items-center text-th-fgd-3 md:pb-0.5 md:text-[0.65rem]">
{t('average-funding')}
<Tooltip
content={t('tooltip-funding')}
placement={'bottom'}
>
<InformationCircleIcon className="ml-1.5 h-4 w-4 text-th-fgd-4 hover:cursor-help" />
</Tooltip>
</div>
<div className="text-th-fgd-1 md:text-xs">
{`${market?.funding1h.toFixed(4)}% (${(
market?.funding1h *
24 *
365
).toFixed(2)}% APR)`}
</div>
</div>
<div className="flex items-center justify-between md:block">
<div className="text-th-fgd-3 md:pb-0.5 md:text-[0.65rem]">
{t('open-interest')}
</div>
<div className="flex items-center text-th-fgd-1 md:text-xs">
{usdFormatter(market?.openInterestUsd, 0)}
<Tooltip
content={`${market?.openInterest.toLocaleString(
undefined,
{
maximumFractionDigits:
perpContractPrecision[baseSymbol],
}
)} ${baseSymbol}`}
placement={'bottom'}
>
<InformationCircleIcon className="ml-1.5 h-4 w-4 text-th-fgd-4 hover:cursor-help" />
</Tooltip>
</div>
</div>
</>
) : null}
<div className="flex items-center justify-between md:block">
<div className="text-left text-th-fgd-3 md:pb-0.5 md:text-[0.65rem] xl:text-center">
{t('daily-range')}
</div>
<DayHighLow high={market?.high24h} low={market?.low24h} />
</div>
</>
) : (
<>
<MarketDataLoader />
<MarketDataLoader />
{isPerpMarket ? (
<>
<MarketDataLoader />
<MarketDataLoader />
<MarketDataLoader />
</>
) : null}
</>
)}
</div>
</div>
<div className="absolute right-0 bottom-0 flex items-center justify-end space-x-2 sm:bottom-auto lg:right-3">
{!isMobile ? (
<div id="layout-tip">
<UiLock />
</div>
) : null}
<div id="data-refresh-tip">
{!isMobile && connected ? <ManualRefresh /> : null}
</div>
</div>
</div>
)
}
export default MarketDetails
export const MarketDataLoader = ({ width }: { width?: string }) => (
<div
className={`mt-0.5 h-8 ${
width ? width : 'w-24'
} animate-pulse rounded bg-th-bkg-3`}
/>
)