diff --git a/components/trade/Orderbook.tsx b/components/trade/Orderbook.tsx
index f45e4a77..8f84097b 100644
--- a/components/trade/Orderbook.tsx
+++ b/components/trade/Orderbook.tsx
@@ -469,6 +469,9 @@ const Orderbook = () => {
size={orderbookData?.asks[index].size}
side="sell"
sizePercent={orderbookData?.asks[index].sizePercent}
+ averagePrice={orderbookData?.asks[index].averagePrice}
+ cumulativeValue={orderbookData?.asks[index].cumulativeValue}
+ cumulativeSize={orderbookData?.asks[index].cumulativeSize}
cumulativeSizePercent={
orderbookData?.asks[index].cumulativeSizePercent
}
@@ -510,6 +513,9 @@ const Orderbook = () => {
size={orderbookData?.bids[index].size}
side="buy"
sizePercent={orderbookData?.bids[index].sizePercent}
+ averagePrice={orderbookData?.bids[index].averagePrice}
+ cumulativeValue={orderbookData?.bids[index].cumulativeValue}
+ cumulativeSize={orderbookData?.bids[index].cumulativeSize}
cumulativeSizePercent={
orderbookData?.bids[index].cumulativeSizePercent
}
@@ -531,6 +537,9 @@ const OrderbookRow = ({
// invert,
hasOpenOrder,
minOrderSize,
+ averagePrice,
+ cumulativeValue,
+ cumulativeSize,
cumulativeSizePercent,
tickSize,
grouping,
@@ -539,6 +548,9 @@ const OrderbookRow = ({
price: number
size: number
sizePercent: number
+ averagePrice: number
+ cumulativeValue: number
+ cumulativeSize: number
cumulativeSizePercent: number
hasOpenOrder: boolean
// invert: boolean
@@ -616,12 +628,35 @@ const OrderbookRow = ({
[minOrderSize],
)
+ const handleMouseOver = useCallback(() => {
+ const { set } = mangoStore.getState()
+ if (averagePrice && cumulativeSize && cumulativeValue) {
+ set((state) => {
+ state.orderbookTooltip = {
+ averagePrice,
+ cumulativeSize,
+ cumulativeValue,
+ side,
+ }
+ })
+ }
+ }, [averagePrice, cumulativeSize, cumulativeValue])
+
+ const handleMouseLeave = useCallback(() => {
+ const { set } = mangoStore.getState()
+ set((state) => {
+ state.orderbookTooltip = undefined
+ })
+ }, [])
+
if (!minOrderSize) return null
return (
<>
diff --git a/components/trade/OrderbookTooltip.tsx b/components/trade/OrderbookTooltip.tsx
new file mode 100644
index 00000000..8fefe4e4
--- /dev/null
+++ b/components/trade/OrderbookTooltip.tsx
@@ -0,0 +1,50 @@
+import { PerpMarket } from '@blockworks-foundation/mango-v4'
+import mangoStore from '@store/mangoStore'
+import useSelectedMarket from 'hooks/useSelectedMarket'
+import { useMemo } from 'react'
+import { useTranslation } from 'react-i18next'
+import { formatNumericValue, getDecimalCount } from 'utils/numbers'
+
+const OrderbookTooltip = () => {
+ const { t } = useTranslation(['common', 'trade'])
+ const orderbookTooltip = mangoStore((s) => s.orderbookTooltip)
+ const { serumOrPerpMarket, baseSymbol, quoteSymbol } = useSelectedMarket()
+
+ const [minOrderDecimals, tickDecimals] = useMemo(() => {
+ if (!serumOrPerpMarket) return [0, 0]
+ return [
+ getDecimalCount(serumOrPerpMarket.minOrderSize),
+ getDecimalCount(serumOrPerpMarket.tickSize),
+ ]
+ }, [serumOrPerpMarket])
+
+ if (!orderbookTooltip) return null
+
+ const { averagePrice, cumulativeSize, cumulativeValue, side } =
+ orderbookTooltip
+ const isBid = side === 'buy'
+ const isPerp = serumOrPerpMarket instanceof PerpMarket
+ return (
+
+
+ {t(side)}
+ {` ${formatNumericValue(cumulativeSize, minOrderDecimals)} ${
+ isPerp ? '' : baseSymbol
+ } ${t('trade:for')} ${isPerp ? '$' : ''}${formatNumericValue(
+ cumulativeValue,
+ tickDecimals,
+ )} ${isPerp ? '' : quoteSymbol} ${t('trade:average-price-of')} ${
+ isPerp ? '$' : ''
+ }${formatNumericValue(averagePrice, tickDecimals)} ${
+ isPerp ? '' : quoteSymbol
+ }`}
+
+
+ )
+}
+
+export default OrderbookTooltip
diff --git a/components/trade/TradeAdvancedPage.tsx b/components/trade/TradeAdvancedPage.tsx
index 28ebc4fd..dd6b2d4d 100644
--- a/components/trade/TradeAdvancedPage.tsx
+++ b/components/trade/TradeAdvancedPage.tsx
@@ -22,6 +22,7 @@ import FavoriteMarketsBar from './FavoriteMarketsBar'
import useLocalStorageState from 'hooks/useLocalStorageState'
import { SIDEBAR_COLLAPSE_KEY, TRADE_LAYOUT_KEY } from 'utils/constants'
import TradeHotKeys from './TradeHotKeys'
+import OrderbookTooltip from './OrderbookTooltip'
export type TradeLayout =
| 'chartLeft'
@@ -304,6 +305,7 @@ const TradeAdvancedPage = () => {
className="h-full border border-x-0 border-th-bkg-3"
>
+
diff --git a/public/locales/en/trade.json b/public/locales/en/trade.json
index 9cafc2fb..29ffef05 100644
--- a/public/locales/en/trade.json
+++ b/public/locales/en/trade.json
@@ -3,6 +3,7 @@
"activate-volume-alert": "Activate Volume Alert",
"amount": "Amount",
"average-funding": "Average {{interval}} Funding",
+ "average-price-of": "at an average price of",
"base": "Base",
"book": "Book",
"buys": "Buys",
@@ -20,6 +21,7 @@
"est-liq-price": "Est. Liq. Price",
"avg-entry-price": "Avg. Entry Price",
"est-slippage": "Est. Slippage",
+ "for": "for",
"funding-limits": "Funding Limits",
"funding-rate": "1h Avg Funding Rate",
"grouping": "Grouping",
diff --git a/public/locales/es/trade.json b/public/locales/es/trade.json
index 9cafc2fb..29ffef05 100644
--- a/public/locales/es/trade.json
+++ b/public/locales/es/trade.json
@@ -3,6 +3,7 @@
"activate-volume-alert": "Activate Volume Alert",
"amount": "Amount",
"average-funding": "Average {{interval}} Funding",
+ "average-price-of": "at an average price of",
"base": "Base",
"book": "Book",
"buys": "Buys",
@@ -20,6 +21,7 @@
"est-liq-price": "Est. Liq. Price",
"avg-entry-price": "Avg. Entry Price",
"est-slippage": "Est. Slippage",
+ "for": "for",
"funding-limits": "Funding Limits",
"funding-rate": "1h Avg Funding Rate",
"grouping": "Grouping",
diff --git a/public/locales/ru/trade.json b/public/locales/ru/trade.json
index 9cafc2fb..29ffef05 100644
--- a/public/locales/ru/trade.json
+++ b/public/locales/ru/trade.json
@@ -3,6 +3,7 @@
"activate-volume-alert": "Activate Volume Alert",
"amount": "Amount",
"average-funding": "Average {{interval}} Funding",
+ "average-price-of": "at an average price of",
"base": "Base",
"book": "Book",
"buys": "Buys",
@@ -20,6 +21,7 @@
"est-liq-price": "Est. Liq. Price",
"avg-entry-price": "Avg. Entry Price",
"est-slippage": "Est. Slippage",
+ "for": "for",
"funding-limits": "Funding Limits",
"funding-rate": "1h Avg Funding Rate",
"grouping": "Grouping",
diff --git a/public/locales/zh/trade.json b/public/locales/zh/trade.json
index 729b4a04..322ae6d4 100644
--- a/public/locales/zh/trade.json
+++ b/public/locales/zh/trade.json
@@ -3,6 +3,7 @@
"activate-volume-alert": "Activate Volume Alert",
"amount": "Amount",
"average-funding": "Average {{interval}} Funding",
+ "average-price-of": "at an average price of",
"base": "Base",
"book": "Book",
"buys": "Buys",
@@ -20,6 +21,7 @@
"est-liq-price": "Est. Liq. Price",
"avg-entry-price": "Avg. Entry Price",
"est-slippage": "Est. Slippage",
+ "for": "for",
"funding-limits": "Funding Limits",
"funding-rate": "1h Avg Funding Rate",
"grouping": "Grouping",
diff --git a/public/locales/zh_tw/trade.json b/public/locales/zh_tw/trade.json
index 013b540f..712236a3 100644
--- a/public/locales/zh_tw/trade.json
+++ b/public/locales/zh_tw/trade.json
@@ -4,6 +4,7 @@
"amount": "數量",
"average-funding": "平均 {{interval}} 資金費",
"avg-entry-price": "平均開倉價格",
+ "average-price-of": "at an average price of",
"base": "基礎",
"book": "單薄",
"buys": "買",
@@ -20,6 +21,7 @@
"edit-order": "編輯訂單",
"est-liq-price": "預計清算價格",
"est-slippage": "預計下滑",
+ "for": "for",
"funding-limits": "資金費限制",
"funding-rate": "1小時平均資金費",
"grouping": "分組",
diff --git a/store/mangoStore.ts b/store/mangoStore.ts
index fda8ea0b..df7a6eac 100644
--- a/store/mangoStore.ts
+++ b/store/mangoStore.ts
@@ -59,6 +59,7 @@ import {
ProfileDetails,
MangoTokenStatsItem,
PositionStat,
+ OrderbookTooltip,
} from 'types'
import spotBalancesUpdater from './spotBalancesUpdater'
import { PerpMarket } from '@blockworks-foundation/mango-v4/'
@@ -174,6 +175,7 @@ export type MangoStore = {
closestToLiq: PositionStat[]
}
}
+ orderbookTooltip: OrderbookTooltip | undefined
profile: {
details: ProfileDetails | null
loadDetails: boolean
@@ -323,6 +325,7 @@ const mangoStore = create
()(
closestToLiq: [],
},
},
+ orderbookTooltip: undefined,
profile: {
loadDetails: false,
details: { profile_name: '', trader_category: '', wallet_pk: '' },
diff --git a/types/index.ts b/types/index.ts
index 217c1b05..fac9b7a0 100644
--- a/types/index.ts
+++ b/types/index.ts
@@ -425,7 +425,9 @@ export type MarketsDataItem = {
export type cumOrderbookSide = {
price: number
size: number
+ averagePrice: number
cumulativeSize: number
+ cumulativeValue: number
sizePercent: number
maxSizePercent: number
cumulativeSizePercent: number
@@ -439,6 +441,13 @@ export type OrderbookData = {
spreadPercentage: number
}
+export type OrderbookTooltip = {
+ averagePrice: number
+ cumulativeSize: number
+ cumulativeValue: number
+ side: 'buy' | 'sell'
+}
+
export interface HealthContribution {
asset: string
contribution: number
diff --git a/utils/orderbook.ts b/utils/orderbook.ts
index 5d93cf93..60c8a1f7 100644
--- a/utils/orderbook.ts
+++ b/utils/orderbook.ts
@@ -94,11 +94,15 @@ export const getCumulativeOrderbookSide = (
isGrouped: boolean,
): cumOrderbookSide[] => {
let cumulativeSize = 0
+ let cumulativeValue = 0
return orders.slice(0, depth).map(([price, size]) => {
cumulativeSize += size
+ cumulativeValue += price * size
return {
price: Number(price),
size,
+ averagePrice: cumulativeValue / cumulativeSize,
+ cumulativeValue: cumulativeValue,
cumulativeSize,
sizePercent: Math.round((cumulativeSize / (totalSize || 1)) * 100),
cumulativeSizePercent: Math.round((size / (cumulativeSize || 1)) * 100),