Zaraba is a cryptocurrency exchange backend written in Go, built around an in-memory orderbook, an internal gRPC service layer, and a server-rendered UI.
- In-memory matching engine for limit and market orders
- Integer-based price and quantity handling for financial precision
- HTTP app (Chi) with session auth and CSRF protection
- Internal gRPC exchange service in the same process
- Real-time market, orderbook, and trade streams via SSE
- PostgreSQL persistence for users, wallets, orders, and sessions
- Templ-based server-rendered frontend
- Single process starts both HTTP (
:8080by default) and gRPC (:50051by default) - HTTP handlers call the in-process exchange server
- Matching happens in memory (
internal/engine) - SSE brokers push updates to connected browser clients
- PostgreSQL stores user, wallet, order, and session data
- Go 1.25+
- Chi router
- gRPC + Protocol Buffers
- PostgreSQL (
lib/pq) - SCS sessions (Postgres store)
- Templ for HTML rendering
cmd/exchange HTTP server, routes, middleware, handlers
cmd/simulator Optional market-maker bot
internal/engine Matching engine + precision helpers
internal/models Database access (users, wallets, orders)
internal/service gRPC server, SSE brokers, liquidity manager
proto/ Protobuf definitions
pb/ Generated protobuf Go code
ui/ Templ pages, partials, static assets
schema.sql Wallet and order tables
- Go 1.25+
- PostgreSQL
Required in normal use:
DATABASE_URL(PostgreSQL DSN)API_KEY(CoinGecko API key)
Common local defaults:
CSRF_SECURE_COOKIE=falseDISABLE_CSRF=trueAPP_ENV=development
Create these tables:
userstablewalletsandorderstables fromschema.sqlsessionstable for SCS session storage
The full SQL is documented in mydocs/DEPLOYMENT.md.
go build -o bin/exchange ./cmd/exchange/
go run ./cmd/exchange/ -addr :8080 -dsn "$DATABASE_URL"Run tests:
go test -v ./...Optional simulator:
go build -o bin/simulator ./cmd/simulator/
SIM_BASE_URL=http://localhost:8080 go run ./cmd/simulator/Core routes:
GET /pingGET /marketsGET /trade/{symbol}POST /trade/{symbol}/placemarketorderPOST /trade/{symbol}/placelimitorderGET /user/wallet
SSE routes:
GET /sse/marketsGET /sse/orderbookGET /sse/trades
gRPC service methods (proto/exchange.proto):
PlaceMarketOrderPlaceLimitOrderStreamOrderBook
- Price scale:
1 USDT = 1,000,000micro-units (int64) - Quantity scale:
1 unit = 100,000,000base units (int64)
All matching and notional calculations are integer-based in the engine.
- Edit
.templfiles, then runtempl generate - Edit
proto/*.proto, then runmake proto
