diff --git a/packages/ai-credits-widget/src/components/history/HistoryTab.tsx b/packages/ai-credits-widget/src/components/history/HistoryTab.tsx index d66841c0..e6092261 100644 --- a/packages/ai-credits-widget/src/components/history/HistoryTab.tsx +++ b/packages/ai-credits-widget/src/components/history/HistoryTab.tsx @@ -14,7 +14,7 @@ import { import type { IconName } from '@goodwidget/ui' import type { GdCreditEntry } from '../../backendTypes' import { formatUsdMicro } from '../../quoteMath' -import { formatGAmount, formatGWeiAmount, formatUsdMicroAmount } from '../../format' +import { formatExactGAmount, formatExactGWeiAmount, formatUsdMicroAmount } from '../../format' import { compactButtonProps } from '../shared/styles' import type { AiCreditsHistoryActions, @@ -69,7 +69,7 @@ function formatEntryGAmount(gdAmountWei: string): string | null { try { const amountWei = BigInt(gdAmountWei || '0') if (amountWei <= 0n) return null - return formatGWeiAmount(amountWei) + return formatExactGWeiAmount(amountWei) } catch { return null } @@ -185,7 +185,7 @@ function sumFilteredGdWei(entries: GdCreditEntry[]): bigint { } function formatAccumulatedG(amountWei: bigint): string { - return formatGAmount(Number(amountWei) / 1e18) + return formatExactGAmount(Number(amountWei) / 1e18) } function formatShortDate(dateValue: string): string { diff --git a/packages/ai-credits-widget/src/format.ts b/packages/ai-credits-widget/src/format.ts index 5b9f20ff..818273b3 100644 --- a/packages/ai-credits-widget/src/format.ts +++ b/packages/ai-credits-widget/src/format.ts @@ -6,15 +6,16 @@ * History cards. * * G$ — comma-grouped with up to 2 decimals and trailing zeros dropped - * (`10,000 G$`, `36,550.55 G$`); compact notation only from 1M up - * (`1.2M G$`) so whale balances cannot blow out a card. + * (`950.5 G$`); compact notation with 1 decimal from 1K up + * (`1.3K G$`, `21.2K G$`, `1.2M G$`) so large balances cannot blow out + * a card. Vault minimums and History stay exact (`21,190.79 G$`). * US$ — always 2 decimals behind a single `US$` symbol (`US$1.30`); a positive * amount that would round to zero renders as `= G_COMPACT_FROM } +/** Bare G$ number with no compacting, for minimums and history where every digit matters. */ +export function formatExactGValue(amount: string | number): string { + const value = toNumber(amount) + if (!Number.isFinite(value) || value <= 0) return '0' + if (value < 0.01) return '<0.01' + return gGrouped.format(value) +} + /** Full G$ amount with no compacting, for tooltips behind a compacted value. */ export function formatExactGAmount(amount: string | number): string { - const value = toNumber(amount) - if (!Number.isFinite(value) || value <= 0) return '0 G$' - return `${gGrouped.format(value)} G$` + return `${formatExactGValue(amount)} G$` +} + +export function formatExactGWeiAmount(amountWei: bigint | string): string { + return formatExactGAmount(weiToNumber(amountWei)) } export function formatGWeiValue(amountWei: bigint | string): string { diff --git a/packages/ai-credits-widget/src/vaultMinimums.ts b/packages/ai-credits-widget/src/vaultMinimums.ts index 3da6c935..6fd43cbc 100644 --- a/packages/ai-credits-widget/src/vaultMinimums.ts +++ b/packages/ai-credits-widget/src/vaultMinimums.ts @@ -1,5 +1,5 @@ import { gToWei, parseGAmount, formatUsdDisplay, quoteDepositPrincipalUsd, quoteStreamPrincipalUsd } from './quoteMath' -import { formatGValue } from './format' +import { formatExactGValue } from './format' import type { AiCreditsQuote } from './widgetRuntimeContract' import { parseAbi, type Address, type PublicClient } from 'viem' @@ -22,15 +22,15 @@ export function formatMinGDisplay(amountWei: bigint): string { if (!Number.isFinite(raw) || raw <= 0) return '0' // Minimums always round up, so the displayed figure is never below the // amount the vault actually accepts. - if (raw >= 1000) return formatGValue(Math.ceil(raw)) - if (raw >= 10) return formatGValue(Math.ceil(raw * 10) / 10) - return formatGValue(Math.ceil(raw * 100) / 100) + if (raw >= 1000) return formatExactGValue(Math.ceil(raw)) + if (raw >= 10) return formatExactGValue(Math.ceil(raw * 10) / 10) + return formatExactGValue(Math.ceil(raw * 100) / 100) } export function formatMinGDisplayLocale(amountG: string): string { const value = parseGAmount(amountG) if (value <= 0) return amountG - if (value >= 1000) return formatGValue(Math.ceil(value)) + if (value >= 1000) return formatExactGValue(Math.ceil(value)) return amountG }