Skip to main content

Local development

Bachelier is a pnpm + turbo monorepo (Node 20+, 22 recommended).

Setup

corepack enable && corepack prepare pnpm@10.33.0 --activate
pnpm install
pnpm test # all tests: contracts + services + web

Quickstart (local devnet)

# 1. start the chain (terminal A) — requires Docker
cd contracts && clarinet devnet start
# the deployment plan publishes all contracts and wires bcshare-token.set-vault

# 2. postgres + indexer + api (terminal B)
docker compose up postgres indexer api
# or natively:
# docker compose up postgres -d
# pnpm --filter @bachelier/db migrate && pnpm --filter @bachelier/db seed
# pnpm --filter @bachelier/indexer dev # :4001
# pnpm --filter @bachelier/api dev # :4000

# 3. keeper (terminal C) — drives rounds, uses the devnet deployer key
cp .env.example .env # uncomment KEEPER_PRIVATE_KEY (devnet deployer)
pnpm --filter @bachelier/keeper dev # :4002

# 4. web (terminal D)
pnpm --filter @bachelier/web dev # :5173

The web app shows a devnet Faucet button (mock sBTC/USDC mints). Every package reads .env / environment — see .env.example for the full matrix.

Tests

pnpm test # everything (turbo)
pnpm --filter @bachelier/contracts test # 78 Clarity tests incl. BS parity + cost gate
pnpm --filter @bachelier/shared test # TS Black–Scholes mirror
cd contracts && clarinet check # static analysis

Highlights enforced by the suite: the BS reference vector table, a 216-point TS↔Clarity parity grid, full round lifecycle for both settlement branches, and an execution-cost gate on buy-call.

Demo-user scripts

Two scripts under contracts/scripts/ reproduce the on-chain demo:

# deploy everything to testnet (idempotent)
NODE_OPTIONS="--dns-result-order=ipv4first" pnpm tsx scripts/deploy-testnet.ts

# create N funded demo users that each deposit (default 60)
DEMO_USERS=60 NODE_OPTIONS="--dns-result-order=ipv4first" pnpm tsx scripts/demo-users.ts

demo-users.ts is rate-limit aware (global throttle + backoff against the Hiro public API) and resumable by on-chain nonce, so an interrupted run continues cleanly. Results land in contracts/deployments/demo-users-tx.json; wallet keys in contracts/deployments/demo-users.json (gitignored). See Test Users.

Security checklist (enforced)

  • Post-conditions on every user-facing token transfer; canonical-token asserts (u112); try!-guarded SIP-010 calls.
  • Oracle staleness + positivity guards; settlement price must postdate expiry.
  • Pausable in a user-protective way (withdrawals/claims/settlement/exercise stay open).
  • Owner/keeper RBAC with events on every change; keeper key isolated and rotatable.
  • Fixed-point overflow review with 128-bit headroom per operation; fp-exp clamped.
  • First-depositor inflation attack mitigated by MIN_DEPOSIT + internal accounting.
  • Indexer idempotent by (tx_id, event_index); reorg rollback; API rate-limited; no key custody.