Revamp dashboard and persist pool stats across restarts

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.
This commit is contained in:
satoshi
2026-04-22 21:07:22 +03:00
parent 8de767646d
commit e881bc930d
10 changed files with 2180 additions and 14 deletions
+9
View File
@@ -88,6 +88,11 @@ export type BlockRecord = {
share_diff?: number;
};
export type HashratePoint = {
t: number; // unix seconds
v: number; // H/s
};
export type Snapshot = {
generated_at: string;
pool: PoolStats | null;
@@ -99,9 +104,13 @@ export type Snapshot = {
hashrate_hs_5m: number;
hashrate_hs_1h: number;
hashrate_hs_24h: number;
best_diff: number;
cumulative_shares: number;
next_block_reward_btc: number;
chain: BlockchainInfo | null;
network_hashrate_hs: number;
recent_blocks?: BlockRecord[];
hashrate_history?: HashratePoint[];
ckpool_ok: boolean;
bitcoin_ok: boolean;
last_error?: string;