Skip to content

Commit 6ec0108

Browse files
committed
feat: make price formatting feed-exponent aware
1 parent b914d46 commit 6ec0108

File tree

3 files changed

+93
-16
lines changed

3 files changed

+93
-16
lines changed

apps/insights/src/components/LivePrices/index.tsx

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,17 @@ const LiveAggregatePrice = ({
4343
if (current === undefined) {
4444
return <Price />;
4545
} else if (current.status === PriceStatus.Trading) {
46-
return <Price current={current.price} prev={prev?.price} />;
46+
return (
47+
<Price
48+
current={current.price}
49+
prev={prev?.price}
50+
exponent={current.exponent}
51+
/>
52+
);
4753
} else {
48-
return <Price current={current.previousPrice} />;
54+
return (
55+
<Price current={current.previousPrice} exponent={current.exponent} />
56+
);
4957
}
5058
};
5159

@@ -63,15 +71,24 @@ const LiveComponentPrice = ({
6371
feedKey,
6472
publisherKey,
6573
);
66-
return <Price current={current?.latest.price} prev={prev?.latest.price} />;
74+
const { current: priceData } = useLivePriceData(cluster, feedKey);
75+
return (
76+
<Price
77+
current={current?.latest.price}
78+
prev={prev?.latest.price}
79+
exponent={priceData?.exponent}
80+
/>
81+
);
6782
};
6883

6984
const Price = ({
7085
prev,
7186
current,
87+
exponent,
7288
}: {
7389
prev?: number | undefined;
7490
current?: number | undefined;
91+
exponent?: number | undefined;
7592
}) =>
7693
current === undefined ? (
7794
<Skeleton width={SKELETON_WIDTH} />
@@ -80,7 +97,7 @@ const Price = ({
8097
className={styles.price}
8198
data-direction={prev ? getChangeDirection(prev, current) : "flat"}
8299
>
83-
<FormattedPriceValue n={current} />
100+
<FormattedPriceValue n={current} exponent={exponent} />
84101
</span>
85102
);
86103

@@ -114,6 +131,7 @@ const LiveAggregateConfidence = ({
114131
? current.confidence
115132
: current.previousConfidence)
116133
}
134+
exponent={current?.exponent}
117135
/>
118136
);
119137
};
@@ -128,24 +146,42 @@ const LiveComponentConfidence = ({
128146
cluster: Cluster;
129147
}) => {
130148
const { current } = useLivePriceComponent(cluster, feedKey, publisherKey);
131-
return <Confidence confidence={current?.latest.confidence} />;
149+
const { current: priceData } = useLivePriceData(cluster, feedKey);
150+
return (
151+
<Confidence
152+
confidence={current?.latest.confidence}
153+
exponent={priceData?.exponent}
154+
/>
155+
);
132156
};
133157

134-
const Confidence = ({ confidence }: { confidence?: number | undefined }) => (
158+
const Confidence = ({
159+
confidence,
160+
exponent,
161+
}: {
162+
confidence?: number | undefined;
163+
exponent?: number | undefined;
164+
}) => (
135165
<span className={styles.confidence}>
136166
<PlusMinus className={styles.plusMinus} />
137167
{confidence === undefined ? (
138168
<Skeleton width={SKELETON_WIDTH} />
139169
) : (
140170
<span>
141-
<FormattedPriceValue n={confidence} />
171+
<FormattedPriceValue n={confidence} exponent={exponent} />
142172
</span>
143173
)}
144174
</span>
145175
);
146176

147-
const FormattedPriceValue = ({ n }: { n: number }) => {
148-
const formatter = usePriceFormatter();
177+
const FormattedPriceValue = ({
178+
n,
179+
exponent,
180+
}: {
181+
n: number;
182+
exponent?: number | undefined;
183+
}) => {
184+
const formatter = usePriceFormatter(exponent);
149185

150186
return useMemo(() => formatter.format(n), [n, formatter]);
151187
};

apps/insights/src/components/PriceFeed/Chart/chart.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ const useChartElem = (symbol: string, feedId: string) => {
6969
const chartContainerRef = useRef<HTMLDivElement | null>(null);
7070
const chartRef = useRef<ChartRefContents | undefined>(undefined);
7171
const isBackfilling = useRef(false);
72-
const priceFormatter = usePriceFormatter();
7372
const abortControllerRef = useRef<AbortController | undefined>(undefined);
7473
// Lightweight charts has [a
7574
// bug](https://github.com/tradingview/lightweight-charts/issues/1649) where
@@ -79,6 +78,9 @@ const useChartElem = (symbol: string, feedId: string) => {
7978
const whitespaceData = useRef<Set<WhitespaceData>>(new Set());
8079

8180
const { current: livePriceData } = useLivePriceData(Cluster.Pythnet, feedId);
81+
const priceFormatter = usePriceFormatter(livePriceData?.exponent, {
82+
useSubscript: false,
83+
});
8284

8385
const didResetVisibleRange = useRef(false);
8486
const didLoadInitialData = useRef(false);
@@ -370,6 +372,17 @@ const useChartElem = (symbol: string, feedId: string) => {
370372
});
371373
}, [quickSelectWindow, resolution, fetchHistoricalData]);
372374

375+
// Update the chart's price formatter when the exponent becomes available
376+
useEffect(() => {
377+
if (chartRef.current && livePriceData?.exponent !== undefined) {
378+
chartRef.current.chart.applyOptions({
379+
localization: {
380+
priceFormatter: priceFormatter.format,
381+
},
382+
});
383+
}
384+
}, [livePriceData?.exponent, priceFormatter]);
385+
373386
return { chartRef, chartContainerRef };
374387
};
375388

apps/insights/src/hooks/use-price-formatter.ts

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,45 @@
11
import { useCallback, useMemo } from "react";
22
import { useNumberFormatter } from "react-aria";
33

4-
export const usePriceFormatter = () => {
4+
export const usePriceFormatter = (
5+
exponent?: number,
6+
options?: { useSubscript?: boolean },
7+
) => {
8+
// Calculate the number of decimal places based on the exponent
9+
// The exponent represents the power of 10, so -8 means 8 decimal places
10+
const decimals = exponent === undefined ? undefined : Math.abs(exponent);
11+
const useSubscript = options?.useSubscript ?? true;
12+
513
const bigNumberFormatter = useNumberFormatter({ maximumFractionDigits: 2 });
614
const smallNumberFormatter = useNumberFormatter({
715
maximumSignificantDigits: 6,
816
});
17+
const exponentBasedFormatter = useNumberFormatter({
18+
minimumFractionDigits: decimals,
19+
maximumFractionDigits: decimals,
20+
});
21+
922
const format = useCallback(
10-
(n: number) =>
11-
n >= 1000
12-
? bigNumberFormatter.format(n)
13-
: formatToSubscriptNumber(smallNumberFormatter.format(n)),
14-
[bigNumberFormatter, smallNumberFormatter],
23+
(n: number) => {
24+
// If we have an exponent, use exponent-based formatting
25+
if (decimals !== undefined) {
26+
const formatted = exponentBasedFormatter.format(n);
27+
return useSubscript ? formatToSubscriptNumber(formatted) : formatted;
28+
}
29+
// Otherwise, fall back to the old behavior
30+
if (n >= 1000) {
31+
return bigNumberFormatter.format(n);
32+
}
33+
const formatted = smallNumberFormatter.format(n);
34+
return useSubscript ? formatToSubscriptNumber(formatted) : formatted;
35+
},
36+
[
37+
bigNumberFormatter,
38+
smallNumberFormatter,
39+
exponentBasedFormatter,
40+
decimals,
41+
useSubscript,
42+
],
1543
);
1644
return useMemo(() => ({ format }), [format]);
1745
};

0 commit comments

Comments
 (0)