Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions lib/format.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
/**
* Shared number formatting utilities for readable display.
*
* formatPrice — token prices (small decimals, 4 sig digits)
* formatSupply — token supply / balances (large numbers, commas)
* formatPrice — token prices (small decimals, 4 sig digits)
* formatSupply — token supply / balances (large numbers, commas)
* formatTokenAmount — bigint token amounts with tiered precision
*/

import { formatUnits } from "viem";

/** 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;
Expand All @@ -14,6 +17,22 @@ export function formatPrice(value: string | number): string {
return v.toFixed(2);
}

/** Format a raw bigint token amount for display with appropriate precision. */
export function formatTokenAmount(value: bigint, decimals: number): string {
const num = Number(formatUnits(value, decimals));
if (num === 0) return "0";
if (num >= 1) {
return num.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}
if (num >= 0.001) {
return num.toFixed(4);
}
if (num >= 0.000001) {
return num.toFixed(6);
}
return num.toExponential(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;
Expand Down
5 changes: 3 additions & 2 deletions src/components/DonateWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useQuery } from "@tanstack/react-query";
import { parseUnits, formatUnits } from "viem";
import { browserClient as publicClient } from "../../lib/rpc";
import { erc20Abi } from "../../lib/price";
import { formatTokenAmount } from "../../lib/format";
import { storyFactoryAbi } from "../../lib/contracts/abi";
import { STORY_FACTORY, PLOT_TOKEN, RESERVE_LABEL, EXPLORER_URL } from "../../lib/contracts/constants";
import { indexFetch } from "../../lib/index-fetch";
Expand Down Expand Up @@ -149,7 +150,7 @@ export function DonateWidget({ storylineId, writerAddress }: DonateWidgetProps)
</div>
{balance !== undefined && (
<p className="text-muted mt-1 text-[10px]">
Balance: {formatUnits(balance, 18)} {RESERVE_LABEL}
Balance: {formatTokenAmount(balance, 18)} {RESERVE_LABEL}
</p>
)}
{insufficientBalance && (
Expand All @@ -161,7 +162,7 @@ export function DonateWidget({ storylineId, writerAddress }: DonateWidgetProps)
<p className="text-muted mt-2 text-xs">
Donating{" "}
<span className="font-semibold text-accent">
{formatUnits(parsedAmount, 18)} {RESERVE_LABEL}
{formatTokenAmount(parsedAmount, 18)} {RESERVE_LABEL}
</span>{" "}
to {writerAddress ? <FarcasterAvatar address={writerAddress} size={12} /> : `story #${storylineId}`}
</p>
Expand Down
16 changes: 1 addition & 15 deletions src/components/TradingWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useQuery } from "@tanstack/react-query";
import { parseUnits, formatUnits, type Address } from "viem";
import { browserClient as publicClient } from "../../lib/rpc";
import { mcv2BondAbi, erc20Abi } from "../../lib/price";
import { formatTokenAmount } from "../../lib/format";
import {
MCV2_BOND, PLOT_TOKEN, RESERVE_LABEL, EXPLORER_URL,
ZAP_PLOTLINK, SUPPORTED_ZAP_TOKENS, ETH_ADDRESS,
Expand All @@ -28,21 +29,6 @@ function applySlippage(amount: bigint, isBuy: boolean): bigint {

const isZapAvailable = ZAP_PLOTLINK !== "0x0000000000000000000000000000000000000000";

/** Format a raw bigint token amount for display with appropriate precision. */
function formatTokenAmount(value: bigint, decimals: number): string {
const num = Number(formatUnits(value, decimals));
if (num === 0) return "0";
if (num >= 1) {
return num.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });
}
if (num >= 0.001) {
return num.toFixed(4);
}
if (num >= 0.000001) {
return num.toFixed(6);
}
return num.toExponential(2);
}

/** Retry a writeContractAsync call once if it fails with a nonce error. */
async function retryOnNonceError<T>(fn: () => Promise<T>): Promise<T> {
Expand Down
Loading