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 {
|
||||
decodeBook,
|
||||
decodeBookL2,
|
||||
getCumulativeOrderbookSide,
|
||||
formatOrderbookData,
|
||||
getMarket,
|
||||
groupBy,
|
||||
updatePerpMarketOnGroup,
|
||||
} from 'utils/orderbook'
|
||||
import { OrderbookData, OrderbookL2 } from 'types'
|
||||
|
@ -57,7 +56,6 @@ const Orderbook = () => {
|
|||
const [grouping, setGrouping] = useState(0.01)
|
||||
const [useOrderbookFeed, setUseOrderbookFeed] = useState(false)
|
||||
const orderbookElRef = useRef<HTMLDivElement>(null)
|
||||
const [isScrolled, setIsScrolled] = useState(false)
|
||||
const [sizeInBase, setSizeInBase] = useState(true)
|
||||
// const [useOrderbookFeed, setUseOrderbookFeed] = useState(
|
||||
// localStorage.getItem(USE_ORDERBOOK_FEED_KEY) !== null
|
||||
|
@ -104,15 +102,18 @@ const Orderbook = () => {
|
|||
element.scrollTop = (element.scrollHeight - element.offsetHeight) / 2
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
}, [orderbookElRef])
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('resize', verticallyCenterOrderbook)
|
||||
}, [verticallyCenterOrderbook])
|
||||
|
||||
const handleScroll = useCallback(() => {
|
||||
setIsScrolled(true)
|
||||
}, [])
|
||||
// center orderbook on market change
|
||||
useEffect(() => {
|
||||
if (orderbookElRef?.current) {
|
||||
verticallyCenterOrderbook()
|
||||
}
|
||||
}, [orderbookElRef, market])
|
||||
|
||||
const orderbookFeed = useRef<OrderbookFeed | null>(null)
|
||||
|
||||
|
@ -137,6 +138,33 @@ const Orderbook = () => {
|
|||
return asksPk.toString()
|
||||
}, [market])
|
||||
|
||||
const usersOpenOrderPrices = useMemo(() => {
|
||||
if (!market) return []
|
||||
const openOrders = mangoStore.getState().mangoAccount.openOrders
|
||||
const marketPk = market.publicKey.toString()
|
||||
const bids2 = mangoStore.getState().selectedMarket.bidsAccount
|
||||
const asks2 = mangoStore.getState().selectedMarket.asksAccount
|
||||
const mangoAccount = mangoStore.getState().mangoAccount.current
|
||||
let usersOpenOrderPrices: number[] = []
|
||||
if (
|
||||
mangoAccount &&
|
||||
bids2 &&
|
||||
asks2 &&
|
||||
bids2 instanceof BookSide &&
|
||||
asks2 instanceof BookSide
|
||||
) {
|
||||
usersOpenOrderPrices = [...bids2.items(), ...asks2.items()]
|
||||
.filter((order) => order.owner.equals(mangoAccount.publicKey))
|
||||
.map((order) => order.price)
|
||||
} else {
|
||||
usersOpenOrderPrices =
|
||||
marketPk && openOrders[marketPk]?.length
|
||||
? openOrders[marketPk]?.map((order) => order.price)
|
||||
: []
|
||||
}
|
||||
return usersOpenOrderPrices
|
||||
}, [market])
|
||||
|
||||
useEffect(
|
||||
() =>
|
||||
mangoStore.subscribe(
|
||||
|
@ -147,100 +175,21 @@ const Orderbook = () => {
|
|||
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 marketPk = market.publicKey.toString()
|
||||
const bids2 = mangoStore.getState().selectedMarket.bidsAccount
|
||||
const asks2 = mangoStore.getState().selectedMarket.asksAccount
|
||||
const mangoAccount = mangoStore.getState().mangoAccount.current
|
||||
let usersOpenOrderPrices: number[] = []
|
||||
if (
|
||||
mangoAccount &&
|
||||
bids2 &&
|
||||
asks2 &&
|
||||
bids2 instanceof BookSide &&
|
||||
asks2 instanceof BookSide
|
||||
) {
|
||||
usersOpenOrderPrices = [...bids2.items(), ...asks2.items()]
|
||||
.filter((order) => order.owner.equals(mangoAccount.publicKey))
|
||||
.map((order) => order.price)
|
||||
} else {
|
||||
usersOpenOrderPrices =
|
||||
marketPk && openOrders[marketPk]?.length
|
||||
? openOrders[marketPk]?.map((order) => order.price)
|
||||
: []
|
||||
}
|
||||
|
||||
// updated orderbook data
|
||||
const bids =
|
||||
groupBy(newOrderbook?.bids, market, grouping, true) || []
|
||||
const 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,
|
||||
const updatedOrderbook = formatOrderbookData(
|
||||
newOrderbook?.bids,
|
||||
newOrderbook?.asks,
|
||||
depth,
|
||||
usersOpenOrderPrices,
|
||||
market,
|
||||
grouping,
|
||||
isGrouped,
|
||||
)
|
||||
const asksToDisplay = getCumulativeOrderbookSide(
|
||||
asks,
|
||||
totalSize,
|
||||
maxSize,
|
||||
depth,
|
||||
usersOpenOrderPrices,
|
||||
grouping,
|
||||
isGrouped,
|
||||
)
|
||||
|
||||
currentOrderbookData.current = newOrderbook
|
||||
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
|
||||
}
|
||||
|
||||
setOrderbookData({
|
||||
bids: bidsToDisplay,
|
||||
asks: asksToDisplay.reverse(),
|
||||
spread,
|
||||
spreadPercentage,
|
||||
})
|
||||
if (!isScrolled) {
|
||||
verticallyCenterOrderbook()
|
||||
}
|
||||
} else {
|
||||
setOrderbookData(null)
|
||||
}
|
||||
setOrderbookData(updatedOrderbook)
|
||||
}
|
||||
},
|
||||
),
|
||||
[depth, grouping, market],
|
||||
[depth, grouping, market, usersOpenOrderPrices],
|
||||
)
|
||||
|
||||
// subscribe to the bids and asks orderbook accounts
|
||||
|
@ -469,9 +418,23 @@ const Orderbook = () => {
|
|||
})
|
||||
}, [bidAccountAddress])
|
||||
|
||||
const onGroupSizeChange = useCallback((groupSize: number) => {
|
||||
setGrouping(groupSize)
|
||||
}, [])
|
||||
const onGroupSizeChange = useCallback(
|
||||
(groupSize: number) => {
|
||||
setGrouping(groupSize)
|
||||
if (market) {
|
||||
const updatedOrderbook = formatOrderbookData(
|
||||
currentOrderbookData?.current?.bids,
|
||||
currentOrderbookData?.current?.asks,
|
||||
depth,
|
||||
market,
|
||||
groupSize,
|
||||
usersOpenOrderPrices,
|
||||
)
|
||||
setOrderbookData(updatedOrderbook)
|
||||
}
|
||||
},
|
||||
[currentOrderbookData, depth, market, usersOpenOrderPrices],
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="flex h-full flex-col">
|
||||
|
@ -544,7 +507,6 @@ const Orderbook = () => {
|
|||
<div
|
||||
className="hide-scroll relative h-full overflow-y-scroll"
|
||||
ref={orderbookElRef}
|
||||
onScroll={handleScroll}
|
||||
>
|
||||
{depthArray.map((_x, idx) => {
|
||||
let index = idx
|
||||
|
|
|
@ -118,7 +118,7 @@ export const getCumulativeOrderbookSide = (
|
|||
}
|
||||
|
||||
export const groupBy = (
|
||||
ordersArray: number[][],
|
||||
ordersArray: number[][] | undefined,
|
||||
market: PerpMarket | Market,
|
||||
grouping: number,
|
||||
isBids: boolean,
|
||||
|
@ -166,3 +166,70 @@ export const groupBy = (
|
|||
})
|
||||
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