2023-07-13 22:47:05 -07:00
|
|
|
import { MinusSmallIcon } from '@heroicons/react/20/solid'
|
|
|
|
import { DownTriangle, UpTriangle } from './DirectionTriangles'
|
|
|
|
import FormatNumericValue from './FormatNumericValue'
|
|
|
|
import { PerpMarket, Serum3Market } from '@blockworks-foundation/mango-v4'
|
|
|
|
import { useMemo } from 'react'
|
|
|
|
import SheenLoader from './SheenLoader'
|
2023-07-21 05:03:44 -07:00
|
|
|
import useMarketsData from 'hooks/useMarketsData'
|
|
|
|
import mangoStore from '@store/mangoStore'
|
|
|
|
import { MarketData } from 'types'
|
2023-07-13 22:47:05 -07:00
|
|
|
|
|
|
|
const MarketChange = ({
|
|
|
|
market,
|
|
|
|
size,
|
|
|
|
}: {
|
|
|
|
market: PerpMarket | Serum3Market | undefined
|
|
|
|
size?: 'small'
|
|
|
|
}) => {
|
2023-07-21 05:03:44 -07:00
|
|
|
const { data: marketsData, isLoading, isFetching } = useMarketsData()
|
|
|
|
|
|
|
|
const currentSpotPrice = useMemo(() => {
|
|
|
|
const group = mangoStore.getState().group
|
|
|
|
if (!group || !market || market instanceof PerpMarket) return 0
|
|
|
|
const baseBank = group.getFirstBankByTokenIndex(market.baseTokenIndex)
|
|
|
|
const quoteBank = group.getFirstBankByTokenIndex(market.quoteTokenIndex)
|
|
|
|
if (!baseBank || !quoteBank) return 0
|
|
|
|
return baseBank.uiPrice / quoteBank.uiPrice
|
|
|
|
}, [market])
|
|
|
|
|
2023-07-23 15:40:59 -07:00
|
|
|
const change = useMemo(() => {
|
|
|
|
if (!market || !marketsData) return
|
2023-07-27 17:21:26 -07:00
|
|
|
const isPerp = market instanceof PerpMarket
|
2023-07-23 15:40:59 -07:00
|
|
|
let pastPrice = 0
|
2023-07-27 17:21:26 -07:00
|
|
|
let dailyVolume = 0
|
|
|
|
if (isPerp) {
|
2023-07-21 05:03:44 -07:00
|
|
|
const perpData: MarketData = marketsData?.perpData
|
|
|
|
const perpEntries = Object.entries(perpData).find(
|
2023-07-23 15:15:46 -07:00
|
|
|
(e) => e[0].toLowerCase() === market.name.toLowerCase(),
|
2023-07-21 05:03:44 -07:00
|
|
|
)
|
2023-07-23 15:40:59 -07:00
|
|
|
pastPrice = perpEntries ? perpEntries[1][0]?.price_24h : 0
|
2023-07-27 17:21:26 -07:00
|
|
|
dailyVolume = perpEntries ? perpEntries[1][0]?.quote_volume_24h : 0
|
2023-07-21 05:03:44 -07:00
|
|
|
} else {
|
|
|
|
const spotData: MarketData = marketsData?.spotData
|
|
|
|
const spotEntries = Object.entries(spotData).find(
|
2023-07-23 15:15:46 -07:00
|
|
|
(e) => e[0].toLowerCase() === market.name.toLowerCase(),
|
2023-07-21 05:03:44 -07:00
|
|
|
)
|
2023-07-23 15:40:59 -07:00
|
|
|
pastPrice = spotEntries ? spotEntries[1][0]?.price_24h : 0
|
2023-07-27 17:21:26 -07:00
|
|
|
dailyVolume = spotEntries ? spotEntries[1][0]?.quote_volume_24h : 0
|
2023-07-21 05:03:44 -07:00
|
|
|
}
|
2023-07-27 17:21:26 -07:00
|
|
|
const currentPrice = isPerp ? market.uiPrice : currentSpotPrice
|
|
|
|
const change =
|
|
|
|
dailyVolume > 0 || isPerp
|
|
|
|
? ((currentPrice - pastPrice) / pastPrice) * 100
|
|
|
|
: 0
|
2023-07-21 05:03:44 -07:00
|
|
|
return change
|
2023-07-23 15:40:59 -07:00
|
|
|
}, [marketsData, currentSpotPrice])
|
2023-07-21 05:03:44 -07:00
|
|
|
|
|
|
|
const loading = isLoading || isFetching
|
2023-07-13 22:47:05 -07:00
|
|
|
|
|
|
|
return loading ? (
|
|
|
|
<SheenLoader className="mt-0.5">
|
|
|
|
<div className="h-3.5 w-12 bg-th-bkg-2" />
|
|
|
|
</SheenLoader>
|
|
|
|
) : change && !isNaN(change) ? (
|
|
|
|
<div className="flex items-center space-x-1.5">
|
|
|
|
{change > 0 ? (
|
|
|
|
<div className="mt-[1px]">
|
|
|
|
<UpTriangle size={size} />
|
|
|
|
</div>
|
|
|
|
) : change < 0 ? (
|
|
|
|
<div className="mt-[1px]">
|
|
|
|
<DownTriangle size={size} />
|
|
|
|
</div>
|
|
|
|
) : (
|
|
|
|
<MinusSmallIcon
|
|
|
|
className={`-mr-1 ${
|
|
|
|
size === 'small' ? 'h-4 w-4' : 'h-6 w-6'
|
|
|
|
} text-th-fgd-4`}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
<p
|
|
|
|
className={`font-mono font-normal ${
|
|
|
|
size === 'small' ? 'text-xs' : 'text-sm'
|
|
|
|
} ${
|
|
|
|
change > 0
|
|
|
|
? 'text-th-up'
|
|
|
|
: change < 0
|
|
|
|
? 'text-th-down'
|
|
|
|
: 'text-th-fgd-4'
|
|
|
|
}`}
|
|
|
|
>
|
|
|
|
<FormatNumericValue
|
|
|
|
value={isNaN(change) ? '0.00' : Math.abs(change)}
|
|
|
|
decimals={2}
|
|
|
|
/>
|
|
|
|
%
|
|
|
|
</p>
|
|
|
|
</div>
|
|
|
|
) : (
|
2023-07-21 05:20:12 -07:00
|
|
|
<div className="flex items-center space-x-1.5">
|
|
|
|
<MinusSmallIcon
|
|
|
|
className={`-mr-1 ${
|
|
|
|
size === 'small' ? 'h-4 w-4' : 'h-6 w-6'
|
|
|
|
} text-th-fgd-4`}
|
|
|
|
/>
|
|
|
|
<p
|
|
|
|
className={`font-mono font-normal ${
|
|
|
|
size === 'small' ? 'text-xs' : 'text-sm'
|
|
|
|
} text-th-fgd-2`}
|
|
|
|
>
|
|
|
|
0%
|
|
|
|
</p>
|
|
|
|
</div>
|
2023-07-13 22:47:05 -07:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
export default MarketChange
|