Hanzo Ledger is a programmable double-entry financial ledger written in Go.
Category: Hanzo Ecosystem Related Skills: hanzo/hanzo-vault.md, hanzo/hanzo-commerce-api.md, hanzo/hanzo-commerce.md
Hanzo Ledger is a programmable double-entry financial ledger written in Go. It provides atomic multi-posting transactions, account-based modeling, and a scriptable DSL called Numscript for expressing complex money movements. Fork of Formance Ledger (Go module still github.com/formancehq/ledger).
big.Int)hanzo/commerce Storefront, catalog, orders
|
hanzo/payments Payment routing (50+ processors)
|
hanzo/treasury Ledger, reconciliation, wallets <-- this
|
lux/treasury On-chain treasury, MPC/KMS wallets
| Item | Value | |------|-------| | Language | Go | | Go Module | github.com/formancehq/ledger | | API | HTTP REST (chi router) | | Port | 3068 | | Database | PostgreSQL (via uptrace/bun ORM) | | API Versions | v1 (legacy), v2 (current), v3 (OpenAPI spec exists) | | CLI Commands | serve, worker, buckets upgrade, version, docs | | Event Bus | Watermill (NATS, Kafka, HTTP) | | Observability | OpenTelemetry (traces + metrics), Prometheus, Jaeger | | Repo | github.com/hanzoai/ledger | | License | MIT |
POST /v2/ledger/{name}/transactions
Content-Type: application/json
{
"postings": [{
"source": "world",
"destination": "users:001",
"amount": 10000,
"asset": "USD/2"
}]
}
POST /v2/ledger/{name}/transactions
Content-Type: application/json
{
"script": {
"plain": "send [USD/2 10000] (\n source = @users:001\n destination = {\n 90% to @merchants:042\n 10% to @platform:fees\n }\n)"
}
}
GET /v2/ledger/{name}/transactions
GET /v2/ledger/{name}/accounts/{address}
POST /v2/ledger/{name}/accounts/{address}/metadata
Content-Type: application/json
{
"role": "merchant",
"tier": "gold"
}
POST /v2/ledger/{name}/transactions/{id}/revert
POST /v2/ledger/{name}/bulk
Content-Type: application/json
[
{"action": "CREATE_TRANSACTION", "data": {"postings": [...]}},
{"action": "ADD_METADATA", "data": {"targetType": "ACCOUNT", "targetID": "users:001", "metadata": {...}}}
]
GET /_healthcheck
GET /_/info
GET /_/metrics
Numscript is a purpose-built language for expressing money movements.
// Simple transfer
send [USD/2 10000] (
source = @users:001
destination = @merchants:042
)
// Multi-party fee split
send [USD/2 10000] (
source = @users:001
destination = {
90% to @merchants:042
10% to {
50% to @platform:fees
50% to @platform:reserve
}
}
)
@world is a special unlimited source (money creation)CURRENCY/precision (e.g., USD/2 = cents)Hierarchical addresses separated by colons: users:001, merchants:042:fees. The special account world is an unlimited source.
Each posting moves an amount of an asset from source to destination:
type Posting struct {
Source string // source account address
Destination string // destination account address
Amount *big.Int // amount (arbitrary precision)
Asset string // asset identifier (e.g., "USD/2")
}
Every account tracks input/output volumes per asset. Balance = Input - Output.
Multiple ledgers can share a single database (bucket). Each ledger has independent accounts, transactions, and metadata. Bucket names and ledger names must match ^[0-9a-zA-Z_-]{1,63}$.
Optional schema enforcement. Define allowed account structures with fixed segments, variable segments ($variable), and regex patterns.
Per-ledger configurable features:
| Feature | Options | Default | |---------|---------|---------| | MOVES_HISTORY | ON, OFF | ON | | MOVES_HISTORY_POST_COMMIT_EFFECTIVE_VOLUMES | SYNC, DISABLED | SYNC | | HASH_LOGS | SYNC, ASYNC, DISABLED | SYNC | | ACCOUNT_METADATA_HISTORY | SYNC, DISABLED | SYNC | | TRANSACTION_METADATA_HISTORY | SYNC, DISABLED | SYNC |
go build ./...
go test ./...
# With integration tests
go test -tags it ./...
# Full test with coverage
just tests
docker compose up -d
# Ledger available at http://localhost:3068
Docker compose includes: PostgreSQL 16, Prometheus, Jaeger, OTEL collector, ledger server, and worker.
just # list available commands
just lint # golangci-lint
just tidy # go mod tidy
just generate # go generate
just tests # full test suite with coverage
just openapi # regenerate OpenAPI spec
just generate-client # regenerate Go client SDK (requires SPEAKEASY_API_KEY)
just pre-commit # tidy + generate + lint + openapi (run before commits)
ledger/
cmd/ CLI commands (serve, worker, buckets, docs, version)
internal/
api/ HTTP API (v1, v2 routers, bulking)
bus/ Event publishing (Watermill)
controller/ Business logic (ledger + system controllers)
machine/ Numscript execution engine
queries/ Query building
replication/ Data export pipelines (gRPC, drivers)
storage/ PostgreSQL storage layer (bun ORM)
tracing/ OpenTelemetry instrumentation
pkg/
accounts/ Account address validation
assets/ Asset format validation
client/ Generated Go client SDK (Speakeasy)
events/ Event type definitions
features/ Feature flag definitions
openapi/ OpenAPI specs (v1, v2, v3)
deployments/ Docker Compose + Pulumi configs
examples/ Example setups (standalone, publisher-http, publisher-kafka)
docs/ Generated documentation
tools/ Build tooling
| Variable | Description | Default | |----------|-------------|---------| | POSTGRES_URI | PostgreSQL connection string | required | | POSTGRES_MAX_OPEN_CONNS | Max open connections | -- | | POSTGRES_MAX_IDLE_CONNS | Max idle connections | -- | | POSTGRES_CONN_MAX_IDLE_TIME | Connection max idle time | -- | | AUTO_UPGRADE | Auto-upgrade schemas on start | false | | EXPERIMENTAL_FEATURES | Enable feature configurability | false | | BULK_PARALLEL | Bulk operation parallelism | 10 | | DEBUG | Enable debug mode | false |
| Flag | Description | Default | |------|-------------|---------| | --bind | API bind address | 0.0.0.0:3068 | | --auto-upgrade | Auto-upgrade schemas | false | | --numscript-cache-max-count | Numscript cache size | 1024 | | --bulk-max-size | Max bulk operation size | 100 | | --bulk-parallel | Bulk parallelism | 10 | | --default-page-size | Default pagination size | 15 | | --max-page-size | Max pagination size | 100 | | --worker | Enable embedded worker | false | | --schema-enforcement-mode | Schema enforcement (audit, strict) | audit |
| Package | Purpose | |---------|---------| | github.com/formancehq/numscript | Numscript DSL parser/interpreter | | github.com/formancehq/go-libs/v4 | Shared library (auth, ORM, health, OTLP, publishing) | | github.com/go-chi/chi/v5 | HTTP router | | github.com/uptrace/bun | PostgreSQL ORM | | github.com/jackc/pgx/v5 | PostgreSQL driver | | github.com/ThreeDotsLabs/watermill | Event bus (NATS, Kafka, HTTP) | | github.com/spf13/cobra | CLI framework | | go.uber.org/fx | Dependency injection | | go.opentelemetry.io/otel | Observability | | github.com/antlr/antlr4 | ANTLR parser runtime (Numscript grammar) |
| Issue | Cause | Solution | |-------|-------|----------| | Connection refused on 3068 | Server not running | docker compose up -d or go run main.go serve | | Schema not found | Ledger not created or not upgraded | Set AUTO_UPGRADE=true or run ledger buckets upgrade | | Insufficient funds | Source account balance too low | Use @world as source or fund the account first | | Invalid posting | Negative amount or invalid account address | Amounts must be >= 0, addresses match ^[a-zA-Z0-9_:]+$ | | Duplicate reference | Transaction reference already used | Use a unique reference field or omit it | | Numscript parse error | Invalid Numscript syntax | Check DSL syntax, ensure assets use ASSET/precision format |
hanzo/hanzo-vault.md - Card tokenization (PCI-compliant, used alongside ledger for payment flows)hanzo/hanzo-commerce-api.md - Commerce API (uses ledger for order accounting)hanzo/hanzo-commerce.md - Commerce storefront (drives transactions into ledger)hanzo/hanzo-database.md - PostgreSQL infrastructure (ledger's storage backend)Last Updated: 2026-03-13 Category: Hanzo Ecosystem Related: ledger, accounting, double-entry, numscript, financial, transactions, go Prerequisites: Double-entry accounting concepts, Go, PostgreSQL, Docker