From d306155120335cc76949294e497d4d5f4337b930 Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Fri, 24 Apr 2026 07:09:20 +0900 Subject: [PATCH 1/2] [#960] Replace scientific notation with subscript-zero format for small USD prices Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/format.ts | 18 ++++++++++++++++++ lib/usd-price.ts | 5 ++--- package-lock.json | 4 ++-- package.json | 2 +- src/components/PriceChart.tsx | 6 +++--- 5 files changed, 26 insertions(+), 9 deletions(-) diff --git a/lib/format.ts b/lib/format.ts index c41eb1e6..57d2e50a 100644 --- a/lib/format.ts +++ b/lib/format.ts @@ -33,6 +33,24 @@ export function formatTokenAmount(value: bigint, decimals: number): string { return num.toExponential(2); } +/** + * Format a small decimal using subscript-zero notation: $0.0₄6262 + * Counts leading zeros after the decimal and renders the count as a + * Unicode subscript digit, followed by 4 significant digits. + */ +export function formatSubscriptPrice(v: number, prefix = "$"): string { + const str = v.toFixed(20); + const afterDot = str.split(".")[1]; + let leadingZeros = 0; + for (const c of afterDot) { + if (c === "0") leadingZeros++; + else break; + } + const significant = afterDot.slice(leadingZeros, leadingZeros + 4); + const subscriptDigit = String.fromCharCode(0x2080 + leadingZeros); + return `${prefix}0.0${subscriptDigit}${significant}`; +} + /** Format a token supply or balance for display. Accepts a string or number. */ export function formatSupply(value: string | number): string { const v = typeof value === "string" ? parseFloat(value) : value; diff --git a/lib/usd-price.ts b/lib/usd-price.ts index 3784b058..0a60f71d 100644 --- a/lib/usd-price.ts +++ b/lib/usd-price.ts @@ -12,6 +12,7 @@ import { PLOT_TOKEN } from "./contracts/constants"; import { createServiceRoleClient } from "./supabase"; +import { formatSubscriptPrice } from "./format"; // In-memory cache let cachedPrice: number | null = null; @@ -212,7 +213,5 @@ export function formatUsdTokenPrice(value: number | null): string { if (value === null) return "—"; if (value === 0) return "$0"; if (value >= 0.01) return formatUsdValue(value); - // For very small values, show 2 significant digits - const digits = Math.max(2, -Math.floor(Math.log10(value)) + 1); - return `$${value.toFixed(digits)}`; + return formatSubscriptPrice(value); } diff --git a/package-lock.json b/package-lock.json index b4883bc7..9a15534c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "plotlink", - "version": "0.1.27", + "version": "0.1.47", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "plotlink", - "version": "0.1.27", + "version": "0.1.47", "workspaces": [ "packages/*" ], diff --git a/package.json b/package.json index 1e277dfb..b01272bc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "plotlink", - "version": "0.1.46", + "version": "0.1.47", "private": true, "workspaces": [ "packages/*" diff --git a/src/components/PriceChart.tsx b/src/components/PriceChart.tsx index 883c217b..c76a3534 100644 --- a/src/components/PriceChart.tsx +++ b/src/components/PriceChart.tsx @@ -6,6 +6,7 @@ import { type Address, formatUnits } from "viem"; import { supabase } from "../../lib/supabase"; import { RESERVE_LABEL } from "../../lib/contracts/constants"; import { usePlotUsdPrice } from "../hooks/usePlotUsdPrice"; +import { formatSubscriptPrice } from "../../lib/format"; const CHART_W = 320; const CHART_H = 140; @@ -41,7 +42,7 @@ function formatTime(iso: string): string { function formatReservePrice(v: number): string { if (v === 0) return "0"; - if (v < 0.001) return v.toExponential(0); + if (v < 0.001) return formatSubscriptPrice(v, ""); if (v < 1) return v.toFixed(4); return v.toFixed(2); } @@ -50,8 +51,7 @@ function formatUsdPrice(v: number): string { if (v === 0) return "$0"; if (v >= 1) return `$${v.toFixed(2)}`; if (v >= 0.01) return `$${v.toFixed(4)}`; - if (v >= 0.0001) return `$${v.toFixed(6)}`; - return `$${v.toExponential(2)}`; + return formatSubscriptPrice(v); } /** From bef1a6eeb8df027420e2c2b8eeaea29b593288bf Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Fri, 24 Apr 2026 07:11:41 +0900 Subject: [PATCH 2/2] [#960] Use digit-by-digit subscript mapping for leading zero counts >= 10 Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/format.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/format.ts b/lib/format.ts index 57d2e50a..621e39ca 100644 --- a/lib/format.ts +++ b/lib/format.ts @@ -47,8 +47,13 @@ export function formatSubscriptPrice(v: number, prefix = "$"): string { else break; } const significant = afterDot.slice(leadingZeros, leadingZeros + 4); - const subscriptDigit = String.fromCharCode(0x2080 + leadingZeros); - return `${prefix}0.0${subscriptDigit}${significant}`; + const subscriptMap: Record = { + "0": "\u2080", "1": "\u2081", "2": "\u2082", "3": "\u2083", + "4": "\u2084", "5": "\u2085", "6": "\u2086", "7": "\u2087", + "8": "\u2088", "9": "\u2089", + }; + const subscriptZeros = leadingZeros.toString().split("").map((d) => subscriptMap[d]).join(""); + return `${prefix}0.0${subscriptZeros}${significant}`; } /** Format a token supply or balance for display. Accepts a string or number. */