mango-ui-v3/components/Orderbook.tsx

796 lines
26 KiB
TypeScript
Raw Normal View History

import React, { useRef, useEffect, useState, useMemo } from 'react'
import Big from 'big.js'
2022-03-29 19:46:21 -07:00
import isEqualLodash from 'lodash/isEqual'
import useInterval from '../hooks/useInterval'
import usePrevious from '../hooks/usePrevious'
import {
isEqual,
getDecimalCount,
getPrecisionDigits,
usdFormatter,
} from '../utils/'
2021-04-26 05:53:27 -07:00
import {
ArrowUpIcon,
ArrowDownIcon,
SwitchHorizontalIcon,
} from '@heroicons/react/solid'
import { CumulativeSizeIcon, StepSizeIcon } from './icons'
2021-04-02 11:26:21 -07:00
import useMarkPrice from '../hooks/useMarkPrice'
2021-04-05 13:48:24 -07:00
import { ElementTitle } from './styles'
2021-04-13 16:41:04 -07:00
import useMangoStore from '../stores/useMangoStore'
2021-04-26 05:53:27 -07:00
import Tooltip from './Tooltip'
2021-09-04 21:42:37 -07:00
import GroupSize from './GroupSize'
import { useViewport } from '../hooks/useViewport'
import { breakpoints } from './TradePageGrid'
2021-09-24 05:24:17 -07:00
import {
FlipCard,
FlipCardBack,
FlipCardFront,
FlipCardInner,
} from './FlipCard'
import { useTranslation } from 'next-i18next'
import FloatingElement from './FloatingElement'
2021-11-21 00:57:13 -08:00
import useLocalStorageState from '../hooks/useLocalStorageState'
import { ORDERBOOK_FLASH_KEY } from './SettingsModal'
2021-12-05 17:13:23 -08:00
import {
mangoGroupConfigSelector,
marketConfigSelector,
marketSelector,
orderbookSelector,
setStoreSelector,
} from '../stores/selectors'
import { Market } from '@project-serum/serum'
import { PerpMarket } from '@blockworks-foundation/mango-client'
const Line = (props) => {
return (
<div
2022-01-31 07:52:28 -08:00
className={`${props.className}`}
style={{
2021-11-30 21:38:05 -08:00
textAlign: props.invert ? 'left' : 'right',
height: '100%',
width: `${props['data-width'] ? props['data-width'] : ''}`,
}}
/>
)
}
2021-04-07 08:44:22 -07:00
const groupBy = (ordersArray, market, grouping: number, isBids: boolean) => {
if (!ordersArray || !market || !grouping || grouping == market?.tickSize) {
return ordersArray || []
2021-09-04 20:36:10 -07:00
}
const groupFloors = {}
for (let i = 0; i < ordersArray.length; i++) {
if (typeof ordersArray[i] == 'undefined') {
2021-09-04 20:36:10 -07:00
break
}
2021-09-06 02:36:30 -07:00
const bigGrouping = Big(grouping)
const bigOrder = Big(ordersArray[i][0])
const floor = isBids
? bigOrder.div(bigGrouping).round(0, Big.roundDown).times(bigGrouping)
: bigOrder.div(bigGrouping).round(0, Big.roundUp).times(bigGrouping)
2021-09-04 20:36:10 -07:00
if (typeof groupFloors[floor] == 'undefined') {
groupFloors[floor] = ordersArray[i][1]
2021-09-04 20:36:10 -07:00
} else {
groupFloors[floor] = ordersArray[i][1] + groupFloors[floor]
2021-09-04 20:36:10 -07:00
}
}
const sortedGroups = Object.entries(groupFloors)
.map((entry) => {
return [
+parseFloat(entry[0]).toFixed(getDecimalCount(grouping)),
entry[1],
]
})
.sort(function (a: number[], b: number[]) {
if (!a || !b) {
return -1
}
2021-09-06 02:36:30 -07:00
return isBids ? b[0] - a[0] : a[0] - b[0]
})
return sortedGroups
2021-09-04 20:36:10 -07:00
}
const getCumulativeOrderbookSide = (
orders,
totalSize,
maxSize,
depth,
backwards = false
) => {
2021-09-04 21:42:37 -07:00
let cumulative = orders
.slice(0, depth)
.reduce((cumulative, [price, size], i) => {
const cumulativeSize = (cumulative[i - 1]?.cumulativeSize || 0) + size
cumulative.push({
price,
size,
cumulativeSize,
sizePercent: Math.round((cumulativeSize / (totalSize || 1)) * 100),
maxSizePercent: Math.round((size / (maxSize || 1)) * 100),
})
return cumulative
}, [])
if (backwards) {
cumulative = cumulative.reverse()
}
return cumulative
}
const hasOpenOrderForPriceGroup = (openOrderPrices, price, grouping) => {
return !!openOrderPrices.find((ooPrice) => {
return ooPrice >= parseFloat(price) && ooPrice < price + grouping
})
}
2021-04-26 05:53:27 -07:00
export default function Orderbook({ depth = 8 }) {
const { t } = useTranslation('common')
2021-12-05 17:13:23 -08:00
const groupConfig = useMangoStore(mangoGroupConfigSelector)
const marketConfig = useMangoStore(marketConfigSelector)
const orderbook = useMangoStore(orderbookSelector)
const market = useMangoStore(marketSelector)
const markPrice = useMarkPrice()
2022-01-27 08:57:36 -08:00
const { width } = useViewport()
const isMobile = width ? width < breakpoints.sm : false
2022-03-28 07:18:35 -07:00
const currentOrderbookData = useRef<any>(null)
2022-03-30 04:08:05 -07:00
const nextOrderbookData = useRef<any>(null)
const previousDepth = usePrevious(depth)
2022-03-30 04:08:05 -07:00
const [openOrderPrices, setOpenOrderPrices] = useState<any[]>([])
2022-03-28 07:18:35 -07:00
const [orderbookData, setOrderbookData] = useState<any | null>(null)
2021-04-26 05:53:27 -07:00
const [defaultLayout, setDefaultLayout] = useState(true)
const [displayCumulativeSize, setDisplayCumulativeSize] = useState(false)
const [grouping, setGrouping] = useState(0.01)
const [tickSize, setTickSize] = useState(0)
const previousGrouping = usePrevious(grouping)
2021-09-04 21:42:37 -07:00
useEffect(() => {
if (market && market.tickSize !== tickSize) {
setTickSize(market.tickSize)
2021-09-04 21:42:37 -07:00
setGrouping(market.tickSize)
}
2021-09-06 06:34:05 -07:00
}, [market])
useInterval(() => {
if (
2022-03-30 04:08:05 -07:00
nextOrderbookData?.current?.bids &&
(!currentOrderbookData.current ||
!isEqualLodash(
currentOrderbookData.current.bids,
nextOrderbookData.current.bids
) ||
!isEqualLodash(
currentOrderbookData.current.asks,
nextOrderbookData.current.asks
) ||
previousDepth !== depth ||
previousGrouping !== grouping)
) {
2022-01-27 08:57:36 -08:00
// check if user has open orders so we can highlight them on orderbook
const openOrders =
useMangoStore.getState().selectedMangoAccount.openOrders
const newOpenOrderPrices = openOrders?.length
? openOrders
.filter(({ market }) =>
market.account.publicKey.equals(marketConfig.publicKey)
)
.map(({ order }) => order.price)
2022-01-27 08:57:36 -08:00
: []
if (!isEqualLodash(newOpenOrderPrices, openOrderPrices)) {
2022-01-27 08:57:36 -08:00
setOpenOrderPrices(newOpenOrderPrices)
}
// updated orderbook data
const bids = groupBy(orderbook?.bids, market, grouping, true) || []
const asks = groupBy(orderbook?.asks, market, grouping, false) || []
const sum = (total, [, size], index) =>
index < depth ? total + size : total
const totalSize = bids.reduce(sum, 0) + asks.reduce(sum, 0)
const maxSize =
Math.max(
...asks.map(function (a) {
return a[1]
})
) +
Math.max(
...bids.map(function (b) {
return b[1]
})
)
const bidsToDisplay = defaultLayout
2021-09-06 06:44:32 -07:00
? getCumulativeOrderbookSide(bids, totalSize, maxSize, depth, false)
: getCumulativeOrderbookSide(bids, totalSize, maxSize, depth / 2, false)
2021-04-26 05:53:27 -07:00
const asksToDisplay = defaultLayout
2021-09-06 06:44:32 -07:00
? getCumulativeOrderbookSide(asks, totalSize, maxSize, depth, false)
: getCumulativeOrderbookSide(
asks,
totalSize,
maxSize,
(depth + 1) / 2,
true
)
currentOrderbookData.current = {
bids: orderbook?.bids,
asks: orderbook?.asks,
}
if (bidsToDisplay[0] || asksToDisplay[0]) {
const bid = bidsToDisplay[0]?.price
2021-04-26 05:53:27 -07:00
const ask = defaultLayout
? asksToDisplay[0]?.price
: asksToDisplay[asksToDisplay.length - 1]?.price
let spread = 0,
spreadPercentage = 0
if (bid && ask) {
spread = ask - bid
spreadPercentage = (spread / ask) * 100
}
2021-09-06 06:44:32 -07:00
2021-04-26 05:53:27 -07:00
setOrderbookData({
bids: bidsToDisplay,
2021-09-22 02:26:59 -07:00
asks: isMobile ? asksToDisplay.reverse() : asksToDisplay,
spread,
spreadPercentage,
2021-04-26 05:53:27 -07:00
})
2021-06-18 11:07:07 -07:00
} else {
setOrderbookData(null)
2021-04-26 05:53:27 -07:00
}
}
}, 500)
useEffect(() => {
nextOrderbookData.current = {
bids: orderbook?.bids,
asks: orderbook?.asks,
}
}, [orderbook])
2021-04-26 05:53:27 -07:00
const handleLayoutChange = () => {
setDefaultLayout(!defaultLayout)
setOrderbookData((prevState) => ({
...orderbookData,
asks: prevState.asks.reverse(),
}))
2021-04-26 05:53:27 -07:00
}
2021-09-04 21:42:37 -07:00
const onGroupSizeChange = (groupSize) => {
setGrouping(groupSize)
}
return !isMobile ? (
<FlipCard>
<FlipCardInner flip={defaultLayout}>
{defaultLayout ? (
<FlipCardFront>
<FloatingElement className="fadein-floating-element h-full">
<div className="flex items-center justify-between pb-2.5">
<div className="relative flex">
<Tooltip
content={
displayCumulativeSize
? t('tooltip-display-step')
: t('tooltip-display-cumulative')
}
className="py-1 text-xs"
>
<button
onClick={() => {
setDisplayCumulativeSize(!displayCumulativeSize)
}}
className="flex h-7 w-7 items-center justify-center rounded-full bg-th-bkg-4 hover:text-th-primary focus:outline-none"
>
{displayCumulativeSize ? (
<StepSizeIcon className="h-4 w-4" />
) : (
<CumulativeSizeIcon className="h-4 w-4" />
)}
</button>
</Tooltip>
2021-04-26 05:53:27 -07:00
</div>
2022-01-31 07:52:28 -08:00
<ElementTitle noMarginBottom>{t('orderbook')}</ElementTitle>
<div className="relative flex">
<Tooltip
content={t('tooltip-switch-layout')}
className="py-1 text-xs"
>
<button
onClick={handleLayoutChange}
className="flex h-7 w-7 items-center justify-center rounded-full bg-th-bkg-4 hover:text-th-primary focus:outline-none"
>
<SwitchHorizontalIcon className="h-4 w-4" />
</button>
</Tooltip>
2021-09-05 06:44:30 -07:00
</div>
</div>
<div className="mb-3 flex items-center justify-end">
<MarkPriceComponent markPrice={markPrice} />
<GroupSize
tickSize={market?.tickSize}
onChange={onGroupSizeChange}
value={grouping}
className="relative flex w-1/3 flex-col items-end"
/>
</div>
<div
className={`mb-2 flex justify-between text-xs text-th-fgd-4`}
>
<div className={`text-left`}>
{displayCumulativeSize ? 'Cumulative ' : ''}
{t('size')} ({marketConfig.baseSymbol})
</div>
<div className={`text-center`}>
{`${t('price')} (${groupConfig.quoteSymbol})`}
</div>
<div className={`text-right`}>
{displayCumulativeSize ? 'Cumulative ' : ''}
{t('size')} ({marketConfig.baseSymbol})
</div>
</div>
<div className="flex">
<div className="w-1/2">
{orderbookData?.bids.map(
({
price,
size,
cumulativeSize,
sizePercent,
maxSizePercent,
}) => (
<OrderbookRow
market={market}
hasOpenOrder={hasOpenOrderForPriceGroup(
openOrderPrices,
price,
grouping
)}
key={price + ''}
price={price}
size={displayCumulativeSize ? cumulativeSize : size}
side="buy"
sizePercent={
displayCumulativeSize ? maxSizePercent : sizePercent
}
grouping={grouping}
/>
)
)}
2021-04-26 05:53:27 -07:00
</div>
<div className="w-1/2">
{orderbookData?.asks.map(
({
price,
size,
cumulativeSize,
sizePercent,
maxSizePercent,
}) => (
<OrderbookRow
market={market}
hasOpenOrder={hasOpenOrderForPriceGroup(
openOrderPrices,
price,
grouping
)}
invert
key={price + ''}
price={price}
size={displayCumulativeSize ? cumulativeSize : size}
side="sell"
sizePercent={
displayCumulativeSize ? maxSizePercent : sizePercent
}
grouping={grouping}
/>
)
)}
2021-09-05 06:44:30 -07:00
</div>
</div>
2022-01-31 07:52:28 -08:00
<OrderbookSpread orderbookData={orderbookData} />
</FloatingElement>
</FlipCardFront>
) : (
<FlipCardBack>
<FloatingElement className="fadein-floating-element h-full">
<div className="flex items-center justify-between pb-2.5">
<div className="relative flex">
<Tooltip
content={
displayCumulativeSize
? t('tooltip-display-step')
: t('tooltip-display-cumulative')
}
className="py-1 text-xs"
>
<button
onClick={() => {
setDisplayCumulativeSize(!displayCumulativeSize)
}}
className="flex h-8 w-8 items-center justify-center rounded-full bg-th-bkg-3 hover:text-th-primary focus:outline-none"
>
{displayCumulativeSize ? (
<StepSizeIcon className="h-5 w-5" />
) : (
<CumulativeSizeIcon className="h-5 w-5" />
)}
</button>
</Tooltip>
</div>
2022-01-31 07:52:28 -08:00
<ElementTitle noMarginBottom>{t('orderbook')}</ElementTitle>
<div className="relative flex">
<Tooltip
content={t('tooltip-switch-layout')}
className="py-1 text-xs"
>
<button
onClick={handleLayoutChange}
className="flex h-8 w-8 items-center justify-center rounded-full bg-th-bkg-3 hover:text-th-primary focus:outline-none"
>
<SwitchHorizontalIcon className="h-5 w-5" />
</button>
</Tooltip>
</div>
</div>
2021-09-20 02:56:50 -07:00
<div className="flex flex-row items-center justify-end pb-2">
<MarkPriceComponent markPrice={markPrice} />
<GroupSize
tickSize={market?.tickSize}
onChange={onGroupSizeChange}
value={grouping}
className="relative flex w-1/3 flex-col items-end"
/>
</div>
<div className={`mb-2 flex justify-between text-th-fgd-4`}>
<div className={`text-left text-xs`}>
{displayCumulativeSize ? 'Cumulative ' : ''}
{t('size')} ({marketConfig.baseSymbol})
</div>
<div className={`text-right text-xs`}>
{`${t('price')} (${groupConfig.quoteSymbol})`}
</div>
</div>
{orderbookData?.asks.map(
({
price,
size,
cumulativeSize,
sizePercent,
maxSizePercent,
}) => (
<OrderbookRow
market={market}
hasOpenOrder={hasOpenOrderForPriceGroup(
openOrderPrices,
price,
grouping
)}
key={price + ''}
price={price}
size={displayCumulativeSize ? cumulativeSize : size}
side="sell"
sizePercent={
displayCumulativeSize ? maxSizePercent : sizePercent
}
grouping={grouping}
/>
)
)}
<div className="my-2 flex justify-between rounded-md bg-th-bkg-1 p-2 text-xs">
<div className="text-th-fgd-3">{t('spread')}</div>
<div className="text-th-fgd-1">
{orderbookData?.spread.toFixed(2)}
</div>
<div className="text-th-fgd-1">
{orderbookData?.spreadPercentage.toFixed(2)}%
</div>
</div>
{orderbookData?.bids.map(
({
price,
size,
cumulativeSize,
sizePercent,
maxSizePercent,
}) => (
<OrderbookRow
market={market}
hasOpenOrder={hasOpenOrderForPriceGroup(
openOrderPrices,
price,
grouping
)}
key={price + ''}
price={price}
size={displayCumulativeSize ? cumulativeSize : size}
side="buy"
sizePercent={
displayCumulativeSize ? maxSizePercent : sizePercent
}
grouping={grouping}
/>
)
)}
</FloatingElement>
</FlipCardBack>
)}
</FlipCardInner>
</FlipCard>
) : (
<div>
<div className="flex items-center justify-between pb-2.5">
<div className="relative flex">
<Tooltip
content={
displayCumulativeSize
? t('tooltip-display-step')
: t('tooltip-display-cumulative')
}
className="py-1 text-xs"
>
<button
onClick={() => {
setDisplayCumulativeSize(!displayCumulativeSize)
}}
className="flex h-8 w-8 items-center justify-center rounded-full bg-th-bkg-3 hover:text-th-primary focus:outline-none"
>
{displayCumulativeSize ? (
<StepSizeIcon className="h-5 w-5" />
) : (
<CumulativeSizeIcon className="h-5 w-5" />
)}
</button>
</Tooltip>
</div>
<GroupSize
tickSize={market?.tickSize}
onChange={onGroupSizeChange}
value={grouping}
className="relative mb-1 flex w-1/3 flex-col items-end"
/>
</div>
<div className={`flex justify-between text-th-fgd-4`}>
<div className={`text-left text-xs`}>
{displayCumulativeSize ? 'Cumulative ' : ''}
{t('size')}
</div>
<div className={`text-right text-xs`}>{t('price')}</div>
</div>
{orderbookData?.asks.map(
({ price, size, cumulativeSize, sizePercent, maxSizePercent }) => (
<OrderbookRow
market={market}
hasOpenOrder={hasOpenOrderForPriceGroup(
openOrderPrices,
price,
grouping
)}
key={price + ''}
price={price}
size={displayCumulativeSize ? cumulativeSize : size}
side="sell"
sizePercent={displayCumulativeSize ? maxSizePercent : sizePercent}
grouping={grouping}
/>
)
)}
2022-01-31 07:52:28 -08:00
<OrderbookSpread orderbookData={orderbookData} />
{orderbookData?.bids.map(
({ price, size, cumulativeSize, sizePercent, maxSizePercent }) => (
<OrderbookRow
market={market}
hasOpenOrder={hasOpenOrderForPriceGroup(
openOrderPrices,
price,
grouping
)}
key={price + ''}
price={price}
size={displayCumulativeSize ? cumulativeSize : size}
side="buy"
sizePercent={displayCumulativeSize ? maxSizePercent : sizePercent}
grouping={grouping}
/>
)
)}
</div>
2021-04-02 11:26:21 -07:00
)
}
2022-01-31 07:52:28 -08:00
const OrderbookSpread = ({ orderbookData }) => {
const { t } = useTranslation('common')
const selectedMarket = useMangoStore((s) => s.selectedMarket.current)
2022-03-30 10:10:15 -07:00
const decimals = useMemo(() => {
if (selectedMarket) {
getPrecisionDigits(selectedMarket?.tickSize)
}
}, [selectedMarket])
2022-01-31 07:52:28 -08:00
return (
<div className="mb-0 mt-3 flex justify-between rounded-md bg-th-bkg-1 p-2 text-xs">
<div className="hidden text-th-fgd-3 sm:block">{t('spread')}</div>
<div className="text-th-fgd-1">
{orderbookData?.spread.toFixed(decimals)}
</div>
2022-01-31 07:52:28 -08:00
<div className="text-th-fgd-1">
{orderbookData?.spreadPercentage.toFixed(2)}%
</div>
</div>
)
}
2021-04-02 11:26:21 -07:00
const OrderbookRow = React.memo<any>(
({
side,
price,
size,
sizePercent,
invert,
hasOpenOrder,
market,
grouping,
}: {
side: 'buy' | 'sell'
price: number
size: number
sizePercent: number
hasOpenOrder: boolean
invert: boolean
grouping: number
market: Market | PerpMarket
}) => {
2022-03-28 07:18:35 -07:00
const element = useRef<HTMLDivElement>(null)
2021-12-05 17:13:23 -08:00
const setMangoStore = useMangoStore(setStoreSelector)
2021-11-21 00:57:13 -08:00
const [showOrderbookFlash] = useLocalStorageState(ORDERBOOK_FLASH_KEY, true)
2022-01-31 07:52:28 -08:00
const flashClassName = side === 'sell' ? 'red-flash' : 'green-flash'
useEffect(() => {
2021-11-21 00:57:13 -08:00
showOrderbookFlash &&
2022-01-31 07:52:28 -08:00
!element.current?.classList.contains(flashClassName) &&
element.current?.classList.add(flashClassName)
const id = setTimeout(
() =>
2022-01-31 07:52:28 -08:00
element.current?.classList.contains(flashClassName) &&
element.current?.classList.remove(flashClassName),
250
)
return () => clearTimeout(id)
}, [price, size])
const formattedSize =
market?.minOrderSize && !isNaN(size)
? Number(size).toFixed(getDecimalCount(market.minOrderSize))
: size
const formattedPrice =
market?.tickSize && !isNaN(price)
? Number(price).toFixed(getDecimalCount(market.tickSize))
: price
const handlePriceClick = () => {
setMangoStore((state) => {
state.tradeForm.price = Number(formattedPrice)
})
}
const handleSizeClick = () => {
setMangoStore((state) => {
state.tradeForm.baseSize = Number(formattedSize)
})
}
2021-09-02 22:32:27 -07:00
if (!market) return null
const groupingDecimalCount = getDecimalCount(grouping)
const minOrderSizeDecimals = getDecimalCount(market.minOrderSize)
return (
<div
className={`relative flex cursor-pointer justify-between text-sm leading-6`}
ref={element}
>
{invert ? (
<>
2021-12-01 12:45:18 -08:00
<Line
invert
data-width={sizePercent + '%'}
className={`absolute left-0 ${
side === 'buy' ? `bg-th-green-muted` : `bg-th-red-muted`
}`}
/>
<div className="flex w-full items-center justify-between hover:font-semibold">
2021-04-26 05:53:27 -07:00
<div
onClick={handlePriceClick}
className={`z-10 text-xs leading-5 md:pl-5 md:leading-6 ${
2022-01-31 07:52:28 -08:00
side === 'buy'
? `text-th-green`
: `text-th-red brightness-125`
2021-09-02 22:32:27 -07:00
}`}
2021-04-26 05:53:27 -07:00
>
{usdFormatter(formattedPrice, groupingDecimalCount, false)}
2021-04-26 05:53:27 -07:00
</div>
2021-12-01 12:45:18 -08:00
<div
2022-01-31 07:52:28 -08:00
className={`z-10 text-xs ${
2022-01-31 21:06:13 -08:00
hasOpenOrder ? 'text-th-primary' : 'text-th-fgd-2'
2021-12-01 12:45:18 -08:00
}`}
onClick={handleSizeClick}
>
{usdFormatter(formattedSize, minOrderSizeDecimals, false)}
2021-12-01 12:45:18 -08:00
</div>
2021-04-15 14:36:55 -07:00
</div>
</>
) : (
<>
<div className="flex w-full items-center justify-between hover:font-semibold">
2021-12-01 12:45:18 -08:00
<div
2022-01-31 07:52:28 -08:00
className={`z-10 text-xs leading-5 md:leading-6 ${
2022-01-31 21:06:13 -08:00
hasOpenOrder ? 'text-th-primary' : 'text-th-fgd-2'
}`}
2021-12-01 12:45:18 -08:00
onClick={handleSizeClick}
>
{usdFormatter(formattedSize, minOrderSizeDecimals, false)}
2021-12-01 12:45:18 -08:00
</div>
<div
className={`z-10 text-xs leading-5 md:pr-4 md:leading-6 ${
2022-01-31 07:52:28 -08:00
side === 'buy'
? `text-th-green`
: `text-th-red brightness-125`
2021-09-02 22:32:27 -07:00
}`}
onClick={handlePriceClick}
>
{usdFormatter(formattedPrice, groupingDecimalCount, false)}
2021-04-05 12:03:20 -07:00
</div>
2021-04-02 11:26:21 -07:00
</div>
2021-12-01 12:45:18 -08:00
<Line
className={`absolute right-0 ${
side === 'buy' ? `bg-th-green-muted` : `bg-th-red-muted`
}`}
data-width={sizePercent + '%'}
/>
</>
)}
</div>
)
},
(prevProps, nextProps) =>
isEqual(prevProps, nextProps, [
'price',
'size',
'sizePercent',
'hasOpenOrder',
])
)
2021-04-02 11:26:21 -07:00
const MarkPriceComponent = React.memo<{ markPrice: number }>(
({ markPrice }) => {
2021-04-02 11:26:21 -07:00
const previousMarkPrice: number = usePrevious(markPrice)
return (
2021-04-02 11:26:21 -07:00
<div
className={`flex items-center justify-center font-bold md:w-1/3 md:text-base ${
2021-04-12 06:32:01 -07:00
markPrice > previousMarkPrice
? `text-th-green`
2021-04-12 06:32:01 -07:00
: markPrice < previousMarkPrice
? `text-th-red`
: `text-th-fgd-1`
}`}
2021-04-02 11:26:21 -07:00
>
{markPrice > previousMarkPrice && (
<ArrowUpIcon className={`mr-1 h-4 w-4 text-th-green`} />
2021-04-02 11:26:21 -07:00
)}
{markPrice < previousMarkPrice && (
<ArrowDownIcon className={`mr-1 h-4 w-4 text-th-red`} />
2021-04-02 11:26:21 -07:00
)}
{markPrice || '----'}
2021-04-02 11:26:21 -07:00
</div>
)
},
(prevProps, nextProps) => isEqual(prevProps, nextProps, ['markPrice'])
)