# money ## Purpose Boundary Zod schema for `MoneyLike` — `{ amount: bigint, currency: string }`. Payment APIs work in minor units (cents, pence, satoshi, lamports) and must never round-trip through IEEE-754 floats because rounding losses on `0.10 + 0.20` are exactly the kind of defect that ends up in a compliance audit. JSON cannot natively encode `bigint`, so the schema accepts either a real `bigint` literal, a finite JSON-number, or a numeric string and coerces via `BigInt()`. The currency code accepts 3-8 uppercase alphanumeric characters covering ISO 4217 (`USD`, `EUR`, `JPY`), crypto (`BTC`, `ETH`), stablecoins (`USDC`), and Solana micro-units (`LAMPORTS`). ## Features - `z.preprocess`-backed amount coercion handles three input shapes (`bigint` / `number` / numeric `string`) and refuses everything else (objects, floats expressed as strings, `NaN`). - Currency regex `^[A-Z0-9]+$` rejects lowercase, spaces, and mixed alphanumeric junk before any downstream lookup. - `nonnegative()` on the bigint prevents negative-amount intents which providers universally reject. - Inferred `Money` type drops in everywhere `MoneyLike` does because the structure is identical. ## Usage: Basic ```ts import { MoneySchema } from "@suaveplan/api-plugin-payment/schemas/money"; const parsed = MoneySchema.parse({ amount: 999n, currency: "USD" }); // { amount: 999n, currency: "USD" } ``` ## Usage: Advanced ```ts const result = MoneySchema.safeParse(await c.req.json()); if (!result.success) { return c.json({ error: "invalid_money", issues: result.error.issues }, 400); } const { amount, currency } = result.data; const intent = await provider.createIntent({ amount: { amount, currency } }); ``` ## API Reference - `MoneySchema` — `z.object({ amount: bigint (coerced), currency: string (3..8, [A-Z0-9]+) })`. - `Money` — `z.infer` — `{ amount: bigint; currency: string }`. ## Implementation Notes `z.preprocess` is used rather than `z.coerce.bigint()` because the latter happily produces `BigInt("12.5")` → `RangeError` and the error message is opaque to API consumers. The custom preprocessor inspects the input shape, only forwards values that BigInt can safely convert, and lets the downstream `z.bigint()` issue produce a clean failure message. Floating-point inputs are intentionally rejected — a fractional amount in minor units is a programming error, not a roundable value.