diff --git a/apps/insights/src/components/LivePrices/index.tsx b/apps/insights/src/components/LivePrices/index.tsx
index db45c120d0..0bf30b37e7 100644
--- a/apps/insights/src/components/LivePrices/index.tsx
+++ b/apps/insights/src/components/LivePrices/index.tsx
@@ -5,13 +5,14 @@ import type { PriceData, PriceComponent } from "@pythnetwork/client";
import { Skeleton } from "@pythnetwork/component-library/Skeleton";
import type { ReactNode } from "react";
import { useMemo } from "react";
-import { useNumberFormatter, useDateFormatter } from "react-aria";
+import { useDateFormatter } from "react-aria";
import styles from "./index.module.scss";
import {
useLivePriceComponent,
useLivePriceData,
} from "../../hooks/use-live-price-data";
+import { usePriceFormatter } from "../../hooks/use-price-formatter";
import type { Cluster } from "../../services/pyth";
export const SKELETON_WIDTH = 20;
@@ -66,20 +67,17 @@ const Price = ({
}: {
prev?: number | undefined;
current?: number | undefined;
-}) => {
- const numberFormatter = useNumberFormatter({ maximumFractionDigits: 5 });
-
- return current === undefined ? (
+}) =>
+ current === undefined ? (
) : (
- {numberFormatter.format(current)}
+
);
-};
export const LiveConfidence = ({
publisherKey,
@@ -119,19 +117,23 @@ const LiveComponentConfidence = ({
return ;
};
-const Confidence = ({ confidence }: { confidence?: number | undefined }) => {
- const numberFormatter = useNumberFormatter({ maximumFractionDigits: 5 });
-
- return (
-
-
- {confidence === undefined ? (
-
- ) : (
- {numberFormatter.format(confidence)}
- )}
-
- );
+const Confidence = ({ confidence }: { confidence?: number | undefined }) => (
+
+
+ {confidence === undefined ? (
+
+ ) : (
+
+
+
+ )}
+
+);
+
+const FormattedPriceValue = ({ n }: { n: number }) => {
+ const formatter = usePriceFormatter();
+
+ return useMemo(() => formatter.format(n), [n, formatter]);
};
export const LiveLastUpdated = ({
diff --git a/apps/insights/src/components/PriceFeed/chart.tsx b/apps/insights/src/components/PriceFeed/chart.tsx
index 96d6d72026..d5ee596505 100644
--- a/apps/insights/src/components/PriceFeed/chart.tsx
+++ b/apps/insights/src/components/PriceFeed/chart.tsx
@@ -11,6 +11,7 @@ import { z } from "zod";
import styles from "./chart.module.scss";
import { useLivePriceData } from "../../hooks/use-live-price-data";
+import { usePriceFormatter } from "../../hooks/use-price-formatter";
import { Cluster } from "../../services/pyth";
type Props = {
@@ -44,6 +45,7 @@ const useChartElem = (symbol: string, feedId: string) => {
const chartRef = useRef(undefined);
const earliestDateRef = useRef(undefined);
const isBackfilling = useRef(false);
+ const priceFormatter = usePriceFormatter();
const backfillData = useCallback(() => {
if (!isBackfilling.current && earliestDateRef.current) {
@@ -113,6 +115,9 @@ const useChartElem = (symbol: string, feedId: string) => {
timeVisible: true,
secondsVisible: true,
},
+ localization: {
+ priceFormatter: priceFormatter.format,
+ },
});
const price = chart.addSeries(LineSeries, { priceFormat });
@@ -141,7 +146,7 @@ const useChartElem = (symbol: string, feedId: string) => {
chart.remove();
};
}
- }, [backfillData]);
+ }, [backfillData, priceFormatter]);
useEffect(() => {
if (current && chartRef.current) {
diff --git a/apps/insights/src/hooks/use-price-formatter.ts b/apps/insights/src/hooks/use-price-formatter.ts
new file mode 100644
index 0000000000..db578a279d
--- /dev/null
+++ b/apps/insights/src/hooks/use-price-formatter.ts
@@ -0,0 +1,40 @@
+import { useCallback, useMemo } from "react";
+import { useNumberFormatter } from "react-aria";
+
+export const usePriceFormatter = () => {
+ const bigNumberFormatter = useNumberFormatter({ maximumFractionDigits: 2 });
+ const smallNumberFormatter = useNumberFormatter({
+ maximumSignificantDigits: 5,
+ });
+ const format = useCallback(
+ (n: number) =>
+ n >= 1000
+ ? bigNumberFormatter.format(n)
+ : formatToSubscriptNumber(smallNumberFormatter.format(n)),
+ [bigNumberFormatter, smallNumberFormatter],
+ );
+ return useMemo(() => ({ format }), [format]);
+};
+
+const formatToSubscriptNumber = (numString: string) => {
+ const parts = numString.split(".");
+
+ const [integerPart, decimalPart] = parts;
+ if (integerPart && decimalPart) {
+ const zerosCount =
+ decimalPart.length - decimalPart.replace(/^0+/, "").length;
+
+ return zerosCount < 5
+ ? numString
+ : integerPart +
+ "." +
+ "0" +
+ (zerosCount > 9
+ ? String.fromCodePoint(0x20_80 + Math.floor(zerosCount / 10))
+ : "") +
+ String.fromCodePoint(0x20_80 + (zerosCount % 10)) +
+ decimalPart.replace(/^0+/, "");
+ } else {
+ return numString;
+ }
+};