Architecture
How the web app, API, shared packages, settlement contract and verifier fit together.
Overview
architecture
Browser ──── sama-frontend (Next.js 16, React 19)
│ │ fetch, cookie session
│ ▼
│ sama-backend (Elysia on Bun) ── Postgres / PGlite
│ │ @sama/* packages: assets · oracle · portfolio · matcher
│ │ settlement · verifier · residual · pancakeswap
│ ├── BNB Chain RPC (executor) balances, snapshot, simulation
│ ├── BNB Chain RPC (verifier) a different provider
│ └── Binance Web3 API stock prices
│
└── Privy wallet ── EIP-712 signatures, approve, settle() ──▶ SamaSettlement (BSC 56)Repositories
| Folder | What lives there |
|---|---|
sama-frontend | Next.js app: landing, docs, onboarding, portfolio, Circles, rounds, activity. Talks to the API or runs fully in the browser in mock mode |
sama-backend | Elysia API on Bun: sessions, targets, Circles, the round state machine, leftovers, proof |
sama-packages | Domain logic as @sama/* packages, imported by the backend without a build step |
sama-contract | SamaSettlement.sol, Foundry tests and the deploy script |
Packages
| Package | Responsibility |
|---|---|
@sama/shared | Chain config, fixed-point math, canonical JSON, logging, deployments |
@sama/assets | Allowlist, on-chain checks, BEP-8056 multipliers, market calendar, TWAP reads |
@sama/binance, @sama/oracle | Stock prices and the per-round snapshot with cross-checks |
@sama/portfolio | Holdings, targets, rebalance deltas, intent limits |
@sama/matcher | The production solver (sama-mmcc-1) |
@sama/reference-matcher | Independent solvers that check the matcher in tests |
@sama/circles | Membership, assets and round scheduling |
@sama/settlement | EIP-712 types, canonical plans, preflight, generated contract bindings |
@sama/verifier | Settlement verification from chain data only |
@sama/residual, @sama/pancakeswap | Leftover recommendations and PancakeSwap quotes and swaps |
@sama/agent | Optional natural-language target interpreter; code resolves every number |
@sama/api-types | Wire types shared by the API and the frontend |
A round, end to end
- 1
POST /api/circles/:id/roundopens a round with a price snapshot pinned to one block. - 2Each member fetches
GET /api/rounds/:id/intent, signs the EIP-712 payload, and posts it back. - 3At the freeze time the background loop runs the matcher and builds a canonical plan.
- 4Participants fetch
GET /api/rounds/:id/approval, sign the plan and send exactapprovetransactions. - 5Any participant fetches
GET /api/rounds/:id/settle, sendssettle(), and reports the hash withPOST. - 6The API checks the hash against the plan, waits for the receipt, runs the verifier on a second RPC and records the result.
Data
Postgres holds offchain state only: users, targets, Circles, memberships, invites, rounds and their history, intents, approvals, leftover decisions and activity. Balances, prices and settlements are always re-read from BNB Chain. Local development uses PGlite with the same schema.