Wallet & Ledger
An integer-cent, double-entry wallet with idempotency, overdraft, refunds, and pluggable fees.
lib/wallet.ts (class Wallet) implements an integer-cent, double-entry wallet system with idempotency, overdraft, refunds, and pluggable fees. Wallets are per { tenant, currency }. All ledger entries are written in debit + credit pairs inside a MongoDB transaction.
There is no HTTP route for wallets - it's a library you call from your own routes.
Usage
import { Wallet } from "@/plugins/Huruf-Tech/thunder-core/lib/wallet.ts";
// Transfer 1000 cents between two tenants' wallets in a currency.
await Wallet.transfer({
fromTenant, toTenant, // ObjectId
currency: "usd",
amount: 1000, // positive integer, in cents
idempotencyKey, // optional; auto-derived if omitted
reference, // optional; auto-generated via References
allowOverdraft, overdraftLimit,
foreignRefType, foreignRef, // link to an external object
purpose, description, metadata,
databaseSession, // optional existing Mongo session
});
// Refund an existing transaction by its reference.
await Wallet.refund({ refToRefund, /* ...subset of transfer opts */ });Read lib/wallet.ts, schemas/wallet.ts, and schemas/walletLedger.ts for the full option and field set.
Rules
amountmust be a positive, non-zero integer (cents). Self-transfers are rejected.- Idempotency is enforced by a unique index; the auto key incorporates currency / amount / minute / from / to / description / foreignRef.
- Overdraft is off by default; when enabled, balance may go down to
-overdraftLimit.
Extension Points
| Hook | Purpose |
|---|---|
Wallet.beforeTransferApproval? | Optional static hook; return false to reject a transfer. |
Wallet.onCalculateFee? | Optional static hook returning a fee breakdown. |
Wallet.resolve() | Finds or lazily creates a wallet for a tenant + currency. |
References (sequential counters)
lib/references.ts (class References): References.inc(label, prefix) atomically increments a named counter in the references collection and returns prefix + count (e.g. TX1, TX2). It is used to generate human-readable wallet transfer references.