diff --git a/lib/format.ts b/lib/format.ts new file mode 100644 index 00000000..19d22af7 --- /dev/null +++ b/lib/format.ts @@ -0,0 +1,25 @@ +/** + * Shared number formatting utilities for readable display. + * + * formatPrice — token prices (small decimals, 4 sig digits) + * formatSupply — token supply / balances (large numbers, commas) + */ + +/** Format a token price for display. Accepts a string or number. */ +export function formatPrice(value: string | number): string { + const v = typeof value === "string" ? parseFloat(value) : value; + if (v === 0 || isNaN(v)) return "0"; + if (v < 0.001) return v.toExponential(0); + if (v < 1) return v.toFixed(4); + return v.toFixed(2); +} + +/** 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; + if (v === 0 || isNaN(v)) return "0"; + if (v < 1) return v.toFixed(4); + if (v >= 1_000_000) return `${(v / 1_000_000).toFixed(1)}M`; + if (v >= 1_000) return Math.round(v).toLocaleString("en-US"); + return v.toFixed(2); +} diff --git a/src/app/story/[storylineId]/page.tsx b/src/app/story/[storylineId]/page.tsx index 07e41c25..0f26067a 100644 --- a/src/app/story/[storylineId]/page.tsx +++ b/src/app/story/[storylineId]/page.tsx @@ -11,6 +11,7 @@ import { RatingSummary } from "../../../components/RatingSummary"; import { ShareToFarcaster } from "../../../components/ShareToFarcaster"; import { getTokenPrice, type TokenPriceInfo } from "../../../../lib/price"; import { RESERVE_LABEL, STORY_FACTORY } from "../../../../lib/contracts/constants"; +import { formatPrice, formatSupply } from "../../../../lib/format"; import { type Address } from "viem"; import { truncateAddress } from "../../../../lib/utils"; import Link from "next/link"; @@ -56,7 +57,7 @@ export async function generateMetadata({ : null; const reserveLabel = RESERVE_LABEL; const priceSuffix = priceInfo - ? ` — Price: ${priceInfo.pricePerToken} ${reserveLabel}` + ? ` — Price: ${formatPrice(priceInfo.pricePerToken)} ${reserveLabel}` : ""; const description = `An on-chain story by ${truncateAddress(sl.writer_address)} — ${sl.plot_count} ${sl.plot_count === 1 ? "plot" : "plots"}${priceSuffix}`; @@ -260,7 +261,7 @@ function StoryHeader({ Token Price - {priceInfo.pricePerToken} {reserveLabel} + {formatPrice(priceInfo.pricePerToken)} {reserveLabel}