fix grouping and vertical center book
This commit is contained in:
parent
d7f01687bb
commit
3330583f3e
|
@ -29,9 +29,8 @@ import { OrderbookFeed } from '@blockworks-foundation/mango-feeds'
|
||||||
import {
|
import {
|
||||||
decodeBook,
|
decodeBook,
|
||||||
decodeBookL2,
|
decodeBookL2,
|
||||||
getCumulativeOrderbookSide,
|
formatOrderbookData,
|
||||||
getMarket,
|
getMarket,
|
||||||
groupBy,
|
|
||||||
updatePerpMarketOnGroup,
|
updatePerpMarketOnGroup,
|
||||||
} from 'utils/orderbook'
|
} from 'utils/orderbook'
|
||||||
import { OrderbookData, OrderbookL2 } from 'types'
|
import { OrderbookData, OrderbookL2 } from 'types'
|
||||||
|
@ -57,7 +56,6 @@ const Orderbook = () => {
|
||||||
const [grouping, setGrouping] = useState(0.01)
|
const [grouping, setGrouping] = useState(0.01)
|
||||||
const [useOrderbookFeed, setUseOrderbookFeed] = useState(false)
|
const [useOrderbookFeed, setUseOrderbookFeed] = useState(false)
|
||||||
const orderbookElRef = useRef<HTMLDivElement>(null)
|
const orderbookElRef = useRef<HTMLDivElement>(null)
|
||||||
const [isScrolled, setIsScrolled] = useState(false)
|
|
||||||
const [sizeInBase, setSizeInBase] = useState(true)
|
const [sizeInBase, setSizeInBase] = useState(true)
|
||||||
// const [useOrderbookFeed, setUseOrderbookFeed] = useState(
|
// const [useOrderbookFeed, setUseOrderbookFeed] = useState(
|
||||||
// localStorage.getItem(USE_ORDERBOOK_FEED_KEY) !== null
|
// localStorage.getItem(USE_ORDERBOOK_FEED_KEY) !== null
|
||||||
|
@ -104,15 +102,18 @@ const Orderbook = () => {
|
||||||
element.scrollTop = (element.scrollHeight - element.offsetHeight) / 2
|
element.scrollTop = (element.scrollHeight - element.offsetHeight) / 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [])
|
}, [orderbookElRef])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
window.addEventListener('resize', verticallyCenterOrderbook)
|
window.addEventListener('resize', verticallyCenterOrderbook)
|
||||||
}, [verticallyCenterOrderbook])
|
}, [verticallyCenterOrderbook])
|
||||||
|
|
||||||
const handleScroll = useCallback(() => {
|
// center orderbook on market change
|
||||||
setIsScrolled(true)
|
useEffect(() => {
|
||||||
}, [])
|
if (orderbookElRef?.current) {
|
||||||
|
verticallyCenterOrderbook()
|
||||||
|
}
|
||||||
|
}, [orderbookElRef, market])
|
||||||
|
|
||||||
const orderbookFeed = useRef<OrderbookFeed | null>(null)
|
const orderbookFeed = useRef<OrderbookFeed | null>(null)
|
||||||
|
|
||||||
|
@ -137,17 +138,8 @@ const Orderbook = () => {
|
||||||
return asksPk.toString()
|
return asksPk.toString()
|
||||||
}, [market])
|
}, [market])
|
||||||
|
|
||||||
useEffect(
|
const usersOpenOrderPrices = useMemo(() => {
|
||||||
() =>
|
if (!market) return []
|
||||||
mangoStore.subscribe(
|
|
||||||
(state) => state.selectedMarket.orderbook,
|
|
||||||
(newOrderbook) => {
|
|
||||||
if (
|
|
||||||
newOrderbook &&
|
|
||||||
market &&
|
|
||||||
!isEqual(currentOrderbookData.current, newOrderbook)
|
|
||||||
) {
|
|
||||||
// check if user has open orders so we can highlight them on orderbook
|
|
||||||
const openOrders = mangoStore.getState().mangoAccount.openOrders
|
const openOrders = mangoStore.getState().mangoAccount.openOrders
|
||||||
const marketPk = market.publicKey.toString()
|
const marketPk = market.publicKey.toString()
|
||||||
const bids2 = mangoStore.getState().selectedMarket.bidsAccount
|
const bids2 = mangoStore.getState().selectedMarket.bidsAccount
|
||||||
|
@ -170,77 +162,34 @@ const Orderbook = () => {
|
||||||
? openOrders[marketPk]?.map((order) => order.price)
|
? openOrders[marketPk]?.map((order) => order.price)
|
||||||
: []
|
: []
|
||||||
}
|
}
|
||||||
|
return usersOpenOrderPrices
|
||||||
|
}, [market])
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
() =>
|
||||||
|
mangoStore.subscribe(
|
||||||
|
(state) => state.selectedMarket.orderbook,
|
||||||
|
(newOrderbook) => {
|
||||||
|
if (
|
||||||
|
newOrderbook &&
|
||||||
|
market &&
|
||||||
|
!isEqual(currentOrderbookData.current, newOrderbook)
|
||||||
|
) {
|
||||||
// updated orderbook data
|
// updated orderbook data
|
||||||
const bids =
|
const updatedOrderbook = formatOrderbookData(
|
||||||
groupBy(newOrderbook?.bids, market, grouping, true) || []
|
newOrderbook?.bids,
|
||||||
const asks =
|
newOrderbook?.asks,
|
||||||
groupBy(newOrderbook?.asks, market, grouping, false) || []
|
|
||||||
|
|
||||||
const sum = (total: number, [, size]: number[], index: number) =>
|
|
||||||
index < depth ? total + size : total
|
|
||||||
const totalSize = bids.reduce(sum, 0) + asks.reduce(sum, 0)
|
|
||||||
|
|
||||||
const maxSize =
|
|
||||||
Math.max(
|
|
||||||
...bids.map((b: number[]) => {
|
|
||||||
return b[1]
|
|
||||||
}),
|
|
||||||
) +
|
|
||||||
Math.max(
|
|
||||||
...asks.map((a: number[]) => {
|
|
||||||
return a[1]
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
const isGrouped = grouping !== market.tickSize
|
|
||||||
const bidsToDisplay = getCumulativeOrderbookSide(
|
|
||||||
bids,
|
|
||||||
totalSize,
|
|
||||||
maxSize,
|
|
||||||
depth,
|
depth,
|
||||||
usersOpenOrderPrices,
|
market,
|
||||||
grouping,
|
grouping,
|
||||||
isGrouped,
|
|
||||||
)
|
|
||||||
const asksToDisplay = getCumulativeOrderbookSide(
|
|
||||||
asks,
|
|
||||||
totalSize,
|
|
||||||
maxSize,
|
|
||||||
depth,
|
|
||||||
usersOpenOrderPrices,
|
usersOpenOrderPrices,
|
||||||
grouping,
|
|
||||||
isGrouped,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
currentOrderbookData.current = newOrderbook
|
currentOrderbookData.current = newOrderbook
|
||||||
if (bidsToDisplay[0] || asksToDisplay[0]) {
|
setOrderbookData(updatedOrderbook)
|
||||||
const bid = bidsToDisplay[0]?.price
|
|
||||||
const ask = asksToDisplay[0]?.price
|
|
||||||
let spread = 0,
|
|
||||||
spreadPercentage = 0
|
|
||||||
if (bid && ask) {
|
|
||||||
spread = parseFloat(
|
|
||||||
(ask - bid).toFixed(getDecimalCount(market.tickSize)),
|
|
||||||
)
|
|
||||||
spreadPercentage = (spread / ask) * 100
|
|
||||||
}
|
|
||||||
|
|
||||||
setOrderbookData({
|
|
||||||
bids: bidsToDisplay,
|
|
||||||
asks: asksToDisplay.reverse(),
|
|
||||||
spread,
|
|
||||||
spreadPercentage,
|
|
||||||
})
|
|
||||||
if (!isScrolled) {
|
|
||||||
verticallyCenterOrderbook()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
setOrderbookData(null)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
[depth, grouping, market],
|
[depth, grouping, market, usersOpenOrderPrices],
|
||||||
)
|
)
|
||||||
|
|
||||||
// subscribe to the bids and asks orderbook accounts
|
// subscribe to the bids and asks orderbook accounts
|
||||||
|
@ -469,9 +418,23 @@ const Orderbook = () => {
|
||||||
})
|
})
|
||||||
}, [bidAccountAddress])
|
}, [bidAccountAddress])
|
||||||
|
|
||||||
const onGroupSizeChange = useCallback((groupSize: number) => {
|
const onGroupSizeChange = useCallback(
|
||||||
|
(groupSize: number) => {
|
||||||
setGrouping(groupSize)
|
setGrouping(groupSize)
|
||||||
}, [])
|
if (market) {
|
||||||
|
const updatedOrderbook = formatOrderbookData(
|
||||||
|
currentOrderbookData?.current?.bids,
|
||||||
|
currentOrderbookData?.current?.asks,
|
||||||
|
depth,
|
||||||
|
market,
|
||||||
|
groupSize,
|
||||||
|
usersOpenOrderPrices,
|
||||||
|
)
|
||||||
|
setOrderbookData(updatedOrderbook)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[currentOrderbookData, depth, market, usersOpenOrderPrices],
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full flex-col">
|
<div className="flex h-full flex-col">
|
||||||
|
@ -544,7 +507,6 @@ const Orderbook = () => {
|
||||||
<div
|
<div
|
||||||
className="hide-scroll relative h-full overflow-y-scroll"
|
className="hide-scroll relative h-full overflow-y-scroll"
|
||||||
ref={orderbookElRef}
|
ref={orderbookElRef}
|
||||||
onScroll={handleScroll}
|
|
||||||
>
|
>
|
||||||
{depthArray.map((_x, idx) => {
|
{depthArray.map((_x, idx) => {
|
||||||
let index = idx
|
let index = idx
|
||||||
|
|
|
@ -118,7 +118,7 @@ export const getCumulativeOrderbookSide = (
|
||||||
}
|
}
|
||||||
|
|
||||||
export const groupBy = (
|
export const groupBy = (
|
||||||
ordersArray: number[][],
|
ordersArray: number[][] | undefined,
|
||||||
market: PerpMarket | Market,
|
market: PerpMarket | Market,
|
||||||
grouping: number,
|
grouping: number,
|
||||||
isBids: boolean,
|
isBids: boolean,
|
||||||
|
@ -166,3 +166,70 @@ export const groupBy = (
|
||||||
})
|
})
|
||||||
return sortedGroups
|
return sortedGroups
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const formatOrderbookData = (
|
||||||
|
rawBids: number[][] | undefined,
|
||||||
|
rawAsks: number[][] | undefined,
|
||||||
|
depth: 12 | 30,
|
||||||
|
market: PerpMarket | Market,
|
||||||
|
grouping: number,
|
||||||
|
usersOpenOrderPrices: number[],
|
||||||
|
) => {
|
||||||
|
const bids = groupBy(rawBids, market, grouping, true) || []
|
||||||
|
const asks = groupBy(rawAsks, market, grouping, false) || []
|
||||||
|
|
||||||
|
const sum = (total: number, [, size]: number[], index: number) =>
|
||||||
|
index < depth ? total + size : total
|
||||||
|
const totalSize = bids.reduce(sum, 0) + asks.reduce(sum, 0)
|
||||||
|
|
||||||
|
const maxSize =
|
||||||
|
Math.max(
|
||||||
|
...bids.map((b: number[]) => {
|
||||||
|
return b[1]
|
||||||
|
}),
|
||||||
|
) +
|
||||||
|
Math.max(
|
||||||
|
...asks.map((a: number[]) => {
|
||||||
|
return a[1]
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
const isGrouped = grouping !== market.tickSize
|
||||||
|
const bidsToDisplay = getCumulativeOrderbookSide(
|
||||||
|
bids,
|
||||||
|
totalSize,
|
||||||
|
maxSize,
|
||||||
|
depth,
|
||||||
|
usersOpenOrderPrices,
|
||||||
|
grouping,
|
||||||
|
isGrouped,
|
||||||
|
)
|
||||||
|
const asksToDisplay = getCumulativeOrderbookSide(
|
||||||
|
asks,
|
||||||
|
totalSize,
|
||||||
|
maxSize,
|
||||||
|
depth,
|
||||||
|
usersOpenOrderPrices,
|
||||||
|
grouping,
|
||||||
|
isGrouped,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (bidsToDisplay[0] || asksToDisplay[0]) {
|
||||||
|
const bid = bidsToDisplay[0]?.price
|
||||||
|
const ask = asksToDisplay[0]?.price
|
||||||
|
let spread = 0,
|
||||||
|
spreadPercentage = 0
|
||||||
|
if (bid && ask) {
|
||||||
|
spread = parseFloat((ask - bid).toFixed(getDecimalCount(market.tickSize)))
|
||||||
|
spreadPercentage = (spread / ask) * 100
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
bids: bidsToDisplay,
|
||||||
|
asks: asksToDisplay.reverse(),
|
||||||
|
spread,
|
||||||
|
spreadPercentage,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue