diff --git a/CLAUDE.md b/CLAUDE.md index 1e3346e..c58fd9e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,10 +8,32 @@ The user communicates in Italian in chat — reply to them in Italian. Everythin ## Project status -This repository is at the **specification stage, not yet implemented**: it currently contains only [flowchart.mmd](flowchart.mmd), which is the source of truth for the project and describes the entire application flow. The tech stack is decided (see below) but no code, build system, or lint/test commands exist yet — once the project is scaffolded, this section must be updated with real commands (install, run, lint, test — including how to run a single test). +All 10 build-order stages from `/home/davide/.claude/plans/scalable-mixing-sloth.md` are code-complete and unit-tested (49 tests green): project skeleton, DB schema + Alembic migrations, auth, HD wallet derivation, Electrum client, deposit detection, bet flow, round/draw engine, payout, withdrawal, RBF fee-bump, admin config + audit log. + +Real-money verification on mainnet, done so far: registration + address derivation, deposit crediting (1-conf), a real 10 PLM bet (broadcast, confirmed, change credited back), and a full round cycle — close → draw (real block hash) → payout (70/30 split, exact sat math verified against the broadcast tx) → confirmation → round closed → next round auto-opened. Withdrawal and the RBF bump path are unit-tested but have never been exercised against a live broadcast. See "Known gaps" below before treating this as production-ready. Before writing code, always read [flowchart.mmd](flowchart.mmd) in full: every node in the diagram corresponds to a behavior that must be implemented exactly as described, including the labels on the edges (conditions, retries, loops). +## Commands + +```bash +source .venv/bin/activate # venv already created at .venv/ +pip install -e ".[dev]" # install/update deps + +alembic upgrade head # apply DB migrations +alembic revision --autogenerate -m "message" # generate a new migration after editing app/db/models.py + +PYTHONPATH=. python scripts/generate_master_key.py # one-time: create+encrypt the server's master xprv (requires XPRV_ENCRYPTION_KEY in .env) + +uvicorn app.main:app --reload --port 8123 # run the dev server + +python -m pytest # run all tests +python -m pytest tests/unit/test_hd.py # run one test file +python -m pytest tests/unit/test_hd.py::test_derivation_is_deterministic # run a single test +``` + +`.env` (gitignored) holds real secrets for local dev; `.env.example` documents the required keys and how to generate them. + ## Tech stack (MVP) - **Backend language**: Python. @@ -65,3 +87,17 @@ These choices were made explicitly during design (not derivable from reading a s - The user's personal deposit address always doubles as the winnings-receiving address: there is no separate "winner address". - 1 confirmation is the chosen threshold for all tx types (deposits, bets, payouts, withdrawals): don't introduce different thresholds (e.g. 3 or 6 confirmations) without an explicit decision. - The draw algorithm (node R) is deliberately simple and should be treated as a replaceable/pluggable component, not the final design — don't architect around its current implementation. + +## Known gaps / TODO + +Not blockers for reading the code, but must be addressed before this is production-ready: + +- **Scheduler doesn't resume mid-flight rounds after a restart.** `rounds/scheduler.py`'s `_tick()` only acts on rounds with `status == "open"`. If the process restarts while a round is `closing`/`drawing`/`paying_out`, it's permanently stuck — nothing re-enters `_wait_for_next_block` or retries `_trigger_payout`. Needs a startup routine that inspects in-progress rounds and resumes (or a periodic "unstick" check) before this can run unattended. +- **RBF bump only handles one case**: a single change output, paying back to the tx's own sender address, large enough to absorb the fee increase. No additional-input selection fallback — an exact-amount tx (no change) or a change output too small to absorb the bump raises `RbfError` and needs manual operator intervention. Documented in `tx/broadcast.py`. +- **Payout retry**: if `_trigger_payout` fails (e.g. insufficient pool UTXOs, Electrum disconnected), it just logs and returns — the round stays stuck in `paying_out` with no automatic retry. +- **Withdrawal and RBF bump have never been exercised against a live broadcast** — only deposit and bet flow are verified end-to-end with real PLM as of this commit. +- **No user-facing history endpoints** (list my bets / withdrawals / past rounds) — only `/users/me` (balance) exists. +- **No deployment setup**: no Dockerfile, process manager, or reconnect/supervision beyond the in-process asyncio tasks. Currently only run manually via `uvicorn` in a dev venv. +- **Admin auth is a single shared bearer token** (`ADMIN_TOKEN`, `X-Admin-Token` header) — no per-admin identity or audit trail of who changed config. +- **No rate limiting / abuse protection** on any endpoint (register, bet, withdrawal). +- No automated integration tests against a live Electrum connection — all live-network verification so far has been manual (ad hoc scripts + real mainnet transactions), not part of the `pytest` suite.