Overview
What economy-lab is (and isn't): a double-entry credit economy, provably solvent and tamper-evident, built as a library rather than a product.
A “double-entry ledger” — the method economy-lab is built on — is the 500-year-old bookkeeping rule where every transaction is recorded twice: once as where the value came from, once as where it went, with the two entries always matching. You cannot add one side without the other, so money can never be silently created or destroyed; when the sides disagree, a record is wrong.[1]
Source src/economy.ts#L100createEconomysrc/index.ts#L50test/conformance/invariants.adversarial.test.tsREADME.md
API createEconomy
economy-lab is the application layer of a credits economy (wallets, a marketplace, payouts, subscriptions, and digital ownership) built as one library over a single double-entry ledger.
You drive it through one submit entry point and read its state through read. Every action is one Operation that posts a balanced transaction and returns an Outcome. The whole loop fits in a few lines:
import { createEconomy, memoryPorts, topUp, systemActor, toAmount, spendable } from '@pwngh/economy-lab';
const economy = createEconomy(memoryPorts({ signingKey: 'dev-signing-key' })); // in-memory, zero dependencies
const outcome = await economy.submit(
topUp({
idempotencyKey: 'ord_1001',
actor: systemActor('billing'),
userId: 'usr_a1',
amount: toAmount('CREDIT', 5000n),
source: 'stripe',
}),
);
const balance = await economy.read.balance(spendable('usr_a1'));
// outcome.status → "committed" · balance.minor → 5000n
Balances aren’t stored and mutated. Every action becomes a balanced posting in an append-only, hash-chained ledger, and balances are folded back from those postings.
The project enforces several invariants:
- value is conserved
- no account overdrafts
- every spendable credit is backed by real cash
- history can’t be silently rewritten
A prover re-checks all of them after every operation.
How it fits together
A submit is synchronous. It validates and authorizes the request first. Then it posts one balanced transaction to the ledger, writing a matching event to an outbox in the same transaction. The Economy API walks that request path step by step.
Anything that outlives a request happens off that path: a background worker drains the outbox and runs the recurring sweeps — payouts, subscriptions, promos, fees, and checkpoints, plus the history-lifecycle jobs that re-prove, archive, and expire old rows.
A lab, not a product
economy-lab is a runnable study of an application layer rather than a deployable money system. The ledger invariants are enforced to a production standard, while the operational edges (the payout Processor, the FX Rates source, the regulated plumbing a money transmitter provides) are stubbed or simplified.
By default it runs entirely in memory with zero runtime dependencies; swappable adapters run the same logic on Postgres, MySQL, Redis, and SQS, each held to the in-memory reference by a single conformance suite. What’s intentionally out of scope has its own page: scope and non-goals.
Where the ideas come from
economy-lab invents no cryptography and no accounting. It composes four well-established ideas into one ledger:
- Double-entry bookkeeping. The rule that every posting balances is the method Luca Pacioli first set down in print in 1494. It’s the foundation of accounts & double-entry.
- Hash-linked tamper-evidence. Hashing each record onto the one before it, so any later edit is detectable, comes from Haber and Stornetta’s How to Time-Stamp a Digital Document (1991), the construction Bitcoin would later cite. economy-lab applies it one hash chain per account.
- Merkle trees, Certificate Transparency, and Ed25519. The signed checkpoint folds every account’s head into a single Merkle root and signs it. The hash tree is Ralph Merkle’s, from his 1979 thesis and later patent; the leaf/node domain separation follows RFC 6962 (Certificate Transparency); and the signature is Ed25519 (Bernstein and colleagues).
- Sagas. A payout that reaches an outside rail is modeled as a long-lived transaction advanced one compensatable step at a time, the saga pattern from Garcia-Molina and Salem’s Sagas (SIGMOD 1987).
economy-lab binds them together (accounting conservation, cryptographic tamper-evidence, and compensatable long-lived transactions) under one prover that re-checks all of them after every operation.
Where to go next
- New to the model? Start with the money model and accounts & double-entry.
- Ready to call it? The Economy covers construction and the
submit/readloop; operations lists everything you can submit, and reads everything you can query. - Care about correctness? Solvency, integrity, and the proof.
- Curious how the sibling packages (money, @pwngh/taskq, economy-edge) plug in? The packages.
See also
Notes