e881bc930d6492c20e832c9fbf3557351687bd45
Dashboard now renders 10 tiles in a 5x2 overview: hashrate, best share, miners, network hashrate, and expected block on the top row; difficulty, block height, block reward, total work, and the difficulty-adjustment countdown on the bottom row. Difficulty is rendered with T/P suffixes instead of scientific notation, the main hashrate card shows the 1-minute value, and the block-height tile pulses orange when the network tip advances. Added a 24-hour hashrate area chart below the overview, sampled once per minute. Samples are persisted to a new hashrate_samples SQLite table and restored on startup so the chart doesn't reset every time kamado-api is restarted. Cumulative pool work (sum of accepted diff-1-normalized shares) is now tracked across ckpool restarts. The aggregator integrates only positive deltas on pool.Shares — a regression means ckpool's counter reset to zero and the baseline is refreshed without losing the running total. A hasPoolSharesBaseline flag prevents double- counting on the first refresh after a kamado-api restart. The value is persisted to a new kv table once per minute. Next-block reward (subsidy + fees) is fetched from bitcoind getblocktemplate at most once per minute and surfaced as a tile. Header's block-height badge now reads prevHeight via untrack() so the effect doesn't form a dependency cycle with its own write.
Kamado Pool
A modern, feature-complete solo Bitcoin mining pool built on a patched fork of CKPool, with a real-time web dashboard and a Go-based API middleware that surfaces everything CKPool knows.
Why Kamado?
Existing CKPool-based solutions (like Bassin for Umbrel) read only a handful of periodic stats files and miss most of CKPool's rich data. Kamado talks directly to CKPool's Unix socket API to expose:
- Real-time per-client data: hashrate, difficulty, user agent, hardware detection
- Full block-found history with height, hash, reward, and solving worker
- Per-worker and per-client best share tracking (current + all-time)
- Network difficulty, pool efficiency, expected time to block
- Live dashboard updates via WebSocket (no 60-second file polls)
Architecture
┌────────────────────────────────────────────────────┐
│ ckpool-solo (C) ──Unix socket──► kamado-api (Go) │
│ ports: 3333 ports: 80 │
│ │
│ ▲ stratum ▲ HTTP/WS │
│ │ │ │
│ Miners Browser │
│ │
│ bitcoind ◄──── RPC + ZMQ ────── ckpool + kamado-api│
└────────────────────────────────────────────────────┘
Three main components:
| Component | Language | Purpose |
|---|---|---|
ckpool/ |
C | Stratum server, share validation, block submission |
api/ |
Go | Socket client, REST/WebSocket API, persistence |
ui/ |
Svelte | Real-time dashboard |
Phases
- Phase 1 — Fork & fix CKPool, build infrastructure
- [~] Phase 2 — Go API middleware
- Phase 2a: CKPool socket client, bitcoind RPC, state aggregator, REST API
- Phase 2b: CKPool log tailer, block history, stdlib WebSocket push
- Phase 2b.5: ZMQ block notifier, SQLite persistence (deferred until s9pk repo exists — need real Go build env for new deps)
- ckpool patch 0001: expose
besteverin runtime socket JSON so the UI can show "this round" and "all-time" best share side by side - [~] Phase 3 — Svelte UI dashboard (skeleton: header, pool overview, miners table, blocks, best shares leaderboard; live WS updates)
- Phase 4 — Monorepo Docker build:
kamado-apiembedsui/distvia//go:embedand serves it at/. The api Dockerfile has a node stage that builds the UI before the Go stage embeds and builds the binary; docker-compose uses the repo root as build context so bothapi/andui/are visible. - Phase 5 — Testing (regtest, testnet4), polish
Quick start (dev)
cp .env.example .env # set POOL_BTCADDRESS and bitcoind creds
make up # build + start ckpool + api
curl localhost:8080/api/health
curl localhost:8080/api/pool
REST endpoints:
| Route | Returns |
|---|---|
GET /api/health |
CKPool + bitcoind health |
GET /api/pool |
Pool stats + derived hashrate windows + chain info |
GET /api/users |
All users from users socket command |
GET /api/workers |
All workers from workers socket command |
GET /api/clients |
All connected stratum sessions (useragent, IP, diff) |
GET /api/blocks |
Recent solved blocks (in-memory ring, SQLite in Phase 2b.5) |
GET /api/snapshot |
Full merged snapshot (everything) |
GET /api/ws |
WebSocket push: full snapshot on every refresh + on solve |
StartOS packaging lives in a separate repository.
Upstream
CKPool by Con Kolivas: https://bitbucket.org/ckolivas/ckpool
Pinned commit: see ckpool/CKPOOL_COMMIT
License
GPL-3.0. CKPool itself is distributed under GPL-3.
Languages
Go
46.7%
Svelte
36.4%
Shell
9.2%
TypeScript
4.7%
Dockerfile
1.4%
Other
1.5%