remove loading state and add .flash class to visualize book updates
This commit is contained in:
parent
dbf6e7087f
commit
51e6d4c1cc
|
@ -90,7 +90,7 @@ export default function MarginBalances() {
|
||||||
Borrows
|
Borrows
|
||||||
</th>
|
</th>
|
||||||
<th scope="col" className={`flex-auto font-normal text-right`}>
|
<th scope="col" className={`flex-auto font-normal text-right`}>
|
||||||
Interest (APY)
|
APY / APR
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
|
@ -68,18 +68,40 @@ const StyledFloatingElement = styled(FloatingElement)`
|
||||||
`};
|
`};
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const getCumulativeOrderbookSide = (
|
||||||
|
orders,
|
||||||
|
totalSize,
|
||||||
|
depth,
|
||||||
|
backwards = false
|
||||||
|
) => {
|
||||||
|
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),
|
||||||
|
})
|
||||||
|
return cumulative
|
||||||
|
}, [])
|
||||||
|
if (backwards) {
|
||||||
|
cumulative = cumulative.reverse()
|
||||||
|
}
|
||||||
|
return cumulative
|
||||||
|
}
|
||||||
|
|
||||||
export default function Orderbook({ depth = 8 }) {
|
export default function Orderbook({ depth = 8 }) {
|
||||||
const markPrice = useMarkPrice()
|
const markPrice = useMarkPrice()
|
||||||
const [orderbook] = useOrderbook()
|
const [orderbook] = useOrderbook()
|
||||||
const { baseCurrency, quoteCurrency } = useMarket()
|
const { baseCurrency, quoteCurrency } = useMarket()
|
||||||
const setMangoStore = useMangoStore((s) => s.set)
|
|
||||||
|
|
||||||
const currentOrderbookData = useRef(null)
|
const currentOrderbookData = useRef(null)
|
||||||
const lastOrderbookData = useRef(null)
|
const lastOrderbookData = useRef(null)
|
||||||
|
|
||||||
const [orderbookData, setOrderbookData] = useState(null)
|
const [orderbookData, setOrderbookData] = useState(null)
|
||||||
const [defaultLayout, setDefaultLayout] = useState(true)
|
const [defaultLayout, setDefaultLayout] = useState(true)
|
||||||
const [loading, setLoading] = useState(true)
|
|
||||||
|
|
||||||
useInterval(() => {
|
useInterval(() => {
|
||||||
if (
|
if (
|
||||||
|
@ -122,7 +144,6 @@ export default function Orderbook({ depth = 8 }) {
|
||||||
spread: spread,
|
spread: spread,
|
||||||
spreadPercentage: spreadPercentage,
|
spreadPercentage: spreadPercentage,
|
||||||
})
|
})
|
||||||
setLoading(false)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, 250)
|
}, 250)
|
||||||
|
@ -134,49 +155,12 @@ export default function Orderbook({ depth = 8 }) {
|
||||||
}
|
}
|
||||||
}, [orderbook])
|
}, [orderbook])
|
||||||
|
|
||||||
const getCumulativeOrderbookSide = (
|
|
||||||
orders,
|
|
||||||
totalSize,
|
|
||||||
depth,
|
|
||||||
backwards = false
|
|
||||||
) => {
|
|
||||||
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),
|
|
||||||
})
|
|
||||||
return cumulative
|
|
||||||
}, [])
|
|
||||||
if (backwards) {
|
|
||||||
cumulative = cumulative.reverse()
|
|
||||||
}
|
|
||||||
return cumulative
|
|
||||||
}
|
|
||||||
|
|
||||||
const handlePriceClick = (price) => {
|
|
||||||
console.log('price click')
|
|
||||||
|
|
||||||
setMangoStore((state) => {
|
|
||||||
state.tradeForm.price = price
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleSizeClick = (size) => {
|
|
||||||
console.log('size click')
|
|
||||||
|
|
||||||
setMangoStore((state) => {
|
|
||||||
state.tradeForm.baseSize = size
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleLayoutChange = () => {
|
const handleLayoutChange = () => {
|
||||||
setLoading(true)
|
|
||||||
setDefaultLayout(!defaultLayout)
|
setDefaultLayout(!defaultLayout)
|
||||||
|
setOrderbookData((prevState) => ({
|
||||||
|
...orderbookData,
|
||||||
|
asks: prevState.asks.reverse(),
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -192,7 +176,7 @@ export default function Orderbook({ depth = 8 }) {
|
||||||
<div className="flex relative">
|
<div className="flex relative">
|
||||||
<Tooltip content={'Switch Layout'} className="text-xs py-1">
|
<Tooltip content={'Switch Layout'} className="text-xs py-1">
|
||||||
<button
|
<button
|
||||||
onClick={() => handleLayoutChange()}
|
onClick={handleLayoutChange}
|
||||||
className="flex items-center justify-center rounded-full bg-th-bkg-3 w-8 h-8 hover:text-th-primary focus:outline-none"
|
className="flex items-center justify-center rounded-full bg-th-bkg-3 w-8 h-8 hover:text-th-primary focus:outline-none"
|
||||||
>
|
>
|
||||||
<SwitchHorizontalIcon className="w-5 h-5" />
|
<SwitchHorizontalIcon className="w-5 h-5" />
|
||||||
|
@ -201,58 +185,37 @@ export default function Orderbook({ depth = 8 }) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MarkPriceComponent markPrice={markPrice} />
|
<MarkPriceComponent markPrice={markPrice} />
|
||||||
{!loading ? (
|
|
||||||
<>
|
|
||||||
<div
|
<div
|
||||||
className={`text-th-fgd-4 flex justify-between mb-2 text-xs`}
|
className={`text-th-fgd-4 flex justify-between mb-2 text-xs`}
|
||||||
>
|
>
|
||||||
<div className={`text-left`}>Size ({baseCurrency})</div>
|
<div className={`text-left`}>Size ({baseCurrency})</div>
|
||||||
<div className={`text-center`}>
|
<div className={`text-center`}>Price ({quoteCurrency})</div>
|
||||||
Price ({quoteCurrency})
|
|
||||||
</div>
|
|
||||||
<div className={`text-right`}>Size ({baseCurrency})</div>
|
<div className={`text-right`}>Size ({baseCurrency})</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<div className="w-1/2">
|
<div className="w-1/2">
|
||||||
{orderbookData?.bids.map(
|
{orderbookData?.bids.map(({ price, size, sizePercent }) => (
|
||||||
({ price, size, sizePercent }) => (
|
|
||||||
<OrderbookRow
|
<OrderbookRow
|
||||||
key={price + ''}
|
key={price + ''}
|
||||||
price={price}
|
price={price}
|
||||||
size={size}
|
size={size}
|
||||||
side={'buy'}
|
side="buy"
|
||||||
sizePercent={sizePercent}
|
sizePercent={sizePercent}
|
||||||
onPriceClick={() => handlePriceClick(price)}
|
|
||||||
onSizeClick={() => handleSizeClick(size)}
|
|
||||||
/>
|
/>
|
||||||
)
|
))}
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="w-1/2">
|
<div className="w-1/2">
|
||||||
{/* <div
|
{orderbookData?.asks.map(({ price, size, sizePercent }) => (
|
||||||
className={`text-th-fgd-4 flex justify-between mb-2`}
|
|
||||||
>
|
|
||||||
<div className={`text-left text-xs px-1`}>
|
|
||||||
Ask ({quoteCurrency})
|
|
||||||
</div>
|
|
||||||
<div className={`text-right text-xs`}>
|
|
||||||
Size ({baseCurrency})
|
|
||||||
</div>
|
|
||||||
</div> */}
|
|
||||||
{orderbookData?.asks.map(
|
|
||||||
({ price, size, sizePercent }) => (
|
|
||||||
<OrderbookRow
|
<OrderbookRow
|
||||||
invert
|
invert
|
||||||
key={price + ''}
|
key={price + ''}
|
||||||
price={price}
|
price={price}
|
||||||
size={size}
|
size={size}
|
||||||
side={'sell'}
|
side="sell"
|
||||||
sizePercent={sizePercent}
|
sizePercent={sizePercent}
|
||||||
onPriceClick={() => handlePriceClick(price)}
|
|
||||||
onSizeClick={() => handleSizeClick(size)}
|
|
||||||
/>
|
/>
|
||||||
)
|
))}
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between bg-th-bkg-1 p-2 mt-4 rounded-md text-xs">
|
<div className="flex justify-between bg-th-bkg-1 p-2 mt-4 rounded-md text-xs">
|
||||||
|
@ -264,19 +227,6 @@ export default function Orderbook({ depth = 8 }) {
|
||||||
{orderbookData?.spreadPercentage.toFixed(2)}%
|
{orderbookData?.spreadPercentage.toFixed(2)}%
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<div className="animate-pulse space-y-3 w-full">
|
|
||||||
<div className="h-5 w-full bg-th-bkg-3 rounded" />
|
|
||||||
<div className="h-5 w-full bg-th-bkg-3 rounded" />
|
|
||||||
<div className="h-5 w-full bg-th-bkg-3 rounded" />
|
|
||||||
<div className="h-5 w-full bg-th-bkg-3 rounded" />
|
|
||||||
<div className="h-5 w-full bg-th-bkg-3 rounded" />
|
|
||||||
<div className="h-5 w-full bg-th-bkg-3 rounded" />
|
|
||||||
<div className="h-5 w-full bg-th-bkg-3 rounded" />
|
|
||||||
<div className="h-5 w-full bg-th-bkg-3 rounded" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</StyledFloatingElement>
|
</StyledFloatingElement>
|
||||||
</FlipCardFront>
|
</FlipCardFront>
|
||||||
) : (
|
) : (
|
||||||
|
@ -288,7 +238,7 @@ export default function Orderbook({ depth = 8 }) {
|
||||||
<div className="flex relative">
|
<div className="flex relative">
|
||||||
<Tooltip content={'Switch Layout'} className="text-xs py-1">
|
<Tooltip content={'Switch Layout'} className="text-xs py-1">
|
||||||
<button
|
<button
|
||||||
onClick={() => handleLayoutChange()}
|
onClick={handleLayoutChange}
|
||||||
className="flex items-center justify-center rounded-full bg-th-bkg-3 w-8 h-8 hover:text-th-primary focus:outline-none"
|
className="flex items-center justify-center rounded-full bg-th-bkg-3 w-8 h-8 hover:text-th-primary focus:outline-none"
|
||||||
>
|
>
|
||||||
<SwitchHorizontalIcon className="w-5 h-5" />
|
<SwitchHorizontalIcon className="w-5 h-5" />
|
||||||
|
@ -297,8 +247,6 @@ export default function Orderbook({ depth = 8 }) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<MarkPriceComponent markPrice={markPrice} />
|
<MarkPriceComponent markPrice={markPrice} />
|
||||||
{!loading ? (
|
|
||||||
<>
|
|
||||||
<div className={`text-th-fgd-4 flex justify-between mb-2`}>
|
<div className={`text-th-fgd-4 flex justify-between mb-2`}>
|
||||||
<div className={`text-left text-xs`}>
|
<div className={`text-left text-xs`}>
|
||||||
Size ({baseCurrency})
|
Size ({baseCurrency})
|
||||||
|
@ -312,10 +260,8 @@ export default function Orderbook({ depth = 8 }) {
|
||||||
key={price + ''}
|
key={price + ''}
|
||||||
price={price}
|
price={price}
|
||||||
size={size}
|
size={size}
|
||||||
side={'sell'}
|
side="sell"
|
||||||
sizePercent={sizePercent}
|
sizePercent={sizePercent}
|
||||||
onPriceClick={() => handlePriceClick(price)}
|
|
||||||
onSizeClick={() => handleSizeClick(size)}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
<div className="flex justify-between bg-th-bkg-1 p-2 my-2 rounded-md text-xs">
|
<div className="flex justify-between bg-th-bkg-1 p-2 my-2 rounded-md text-xs">
|
||||||
|
@ -332,25 +278,10 @@ export default function Orderbook({ depth = 8 }) {
|
||||||
key={price + ''}
|
key={price + ''}
|
||||||
price={price}
|
price={price}
|
||||||
size={size}
|
size={size}
|
||||||
side={'buy'}
|
side="buy"
|
||||||
sizePercent={sizePercent}
|
sizePercent={sizePercent}
|
||||||
onPriceClick={() => handlePriceClick(price)}
|
|
||||||
onSizeClick={() => handleSizeClick(size)}
|
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</>
|
|
||||||
) : (
|
|
||||||
<div className="animate-pulse space-y-3 w-full">
|
|
||||||
<div className="h-5 w-full bg-th-bkg-3 rounded" />
|
|
||||||
<div className="h-5 w-full bg-th-bkg-3 rounded" />
|
|
||||||
<div className="h-5 w-full bg-th-bkg-3 rounded" />
|
|
||||||
<div className="h-5 w-full bg-th-bkg-3 rounded" />
|
|
||||||
<div className="h-5 w-full bg-th-bkg-3 rounded" />
|
|
||||||
<div className="h-5 w-full bg-th-bkg-3 rounded" />
|
|
||||||
<div className="h-5 w-full bg-th-bkg-3 rounded" />
|
|
||||||
<div className="h-5 w-full bg-th-bkg-3 rounded" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</StyledFloatingElement>
|
</StyledFloatingElement>
|
||||||
</FlipCardBack>
|
</FlipCardBack>
|
||||||
)}
|
)}
|
||||||
|
@ -361,9 +292,10 @@ export default function Orderbook({ depth = 8 }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const OrderbookRow = React.memo<any>(
|
const OrderbookRow = React.memo<any>(
|
||||||
({ side, price, size, sizePercent, onSizeClick, onPriceClick, invert }) => {
|
({ side, price, size, sizePercent, invert }) => {
|
||||||
const element = useRef(null)
|
const element = useRef(null)
|
||||||
const { market } = useMarket()
|
const { market } = useMarket()
|
||||||
|
const setMangoStore = useMangoStore((s) => s.set)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
!element.current?.classList.contains('flash') &&
|
!element.current?.classList.contains('flash') &&
|
||||||
|
@ -387,6 +319,18 @@ const OrderbookRow = React.memo<any>(
|
||||||
? Number(price).toFixed(getDecimalCount(market.tickSize) + 1)
|
? Number(price).toFixed(getDecimalCount(market.tickSize) + 1)
|
||||||
: price
|
: price
|
||||||
|
|
||||||
|
const handlePriceClick = () => {
|
||||||
|
setMangoStore((state) => {
|
||||||
|
state.tradeForm.price = price
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSizeClick = () => {
|
||||||
|
setMangoStore((state) => {
|
||||||
|
state.tradeForm.baseSize = size
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`flex text-sm leading-7 justify-between`} ref={element}>
|
<div className={`flex text-sm leading-7 justify-between`} ref={element}>
|
||||||
{invert ? (
|
{invert ? (
|
||||||
|
@ -401,13 +345,13 @@ const OrderbookRow = React.memo<any>(
|
||||||
}`}
|
}`}
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
onClick={onPriceClick}
|
onClick={handlePriceClick}
|
||||||
className="z-30 relative text-th-fgd-1 px-1"
|
className="z-30 relative text-th-fgd-1 px-1"
|
||||||
>
|
>
|
||||||
{formattedPrice}
|
{formattedPrice}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={`text-right`} onClick={onSizeClick}>
|
<div className={`text-right`} onClick={handleSizeClick}>
|
||||||
{formattedSize}
|
{formattedSize}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
@ -415,7 +359,7 @@ const OrderbookRow = React.memo<any>(
|
||||||
<>
|
<>
|
||||||
<div
|
<div
|
||||||
className={`text-left flex-1 text-th-fgd-1`}
|
className={`text-left flex-1 text-th-fgd-1`}
|
||||||
onClick={onSizeClick}
|
onClick={handleSizeClick}
|
||||||
>
|
>
|
||||||
{formattedSize}
|
{formattedSize}
|
||||||
</div>
|
</div>
|
||||||
|
@ -429,7 +373,7 @@ const OrderbookRow = React.memo<any>(
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
className={`z-30 relative text-th-fgd-1 px-1`}
|
className={`z-30 relative text-th-fgd-1 px-1`}
|
||||||
onClick={onPriceClick}
|
onClick={handlePriceClick}
|
||||||
>
|
>
|
||||||
{formattedPrice}
|
{formattedPrice}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -144,8 +144,8 @@ input[type='number'] {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Responsive table */
|
/* Responsive table */
|
||||||
|
|
||||||
/* inspired by: https://css-tricks.com/responsive-data-tables/ */
|
/* inspired by: https://css-tricks.com/responsive-data-tables/ */
|
||||||
|
|
||||||
.responsiveTable {
|
.responsiveTable {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
@ -231,3 +231,37 @@ input[type='number'] {
|
||||||
.react-tel-input .country-list .highlight {
|
.react-tel-input .country-list .highlight {
|
||||||
background-color: var(--bkg-1) !important;
|
background-color: var(--bkg-1) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* orderbook flash */
|
||||||
|
|
||||||
|
@keyframes highlight {
|
||||||
|
from {
|
||||||
|
background-color: var(--primary);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@-webkit-keyframes highlight {
|
||||||
|
from {
|
||||||
|
background-color: var(--primary);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@-moz-keyframes highlight {
|
||||||
|
from {
|
||||||
|
background-color: var(--primary);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.flash {
|
||||||
|
-moz-animation: highlight 0.5s ease 0s 1 alternate;
|
||||||
|
-webkit-animation: highlight 0.5s ease 0s 1 alternate;
|
||||||
|
animation: highlight 0.5s ease 0s 1 alternate;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue