Contents

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

your servicesubmit · readsubmitvalidate · authorizeONE TRANSACTIONledgerappend-only · hash-chainedoutboxthe matching eventpostread — balances fold from the postingsworkeroff the request pathapplies inbounddrains the outbox, runs the sweepswebhooksverified inboundA verified provider callback lands in the inbox and applies through the same submit a direct caller hits.
One synchronous path and one deferred path. A submit commits its posting and its event in one transaction, reads fold from the postings, and everything that outlives a request — relaying events, payouts, renewals, checkpoints — runs on the worker, off the request path.

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

See also

Notes

  1. Conservation of value is a property of double-entry bookkeeping itself, first set down in print by Luca Pacioli in 1494. source