Skip to content

dashboard: add a "Pool at a glance" card to the overview - #99

Merged
rsantacroce merged 2 commits into
mainfrom
feat/dashboard-at-a-glance
Oct 12, 2026
Merged

rsantacroce merged 2 commits into
mainfrom
feat/dashboard-at-a-glance

Conversation

@rsantacroce

@rsantacroce rsantacroce commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Adds a headline stats card at the top of the overview page, laid out as two rows of five tiles:

Tile Value Subtitle
Network hashrate measured from block arrivals 24h · from N block times
Pool share (24h) pool 24h ÷ network 24h pool and network over 24h
Network difficulty from the current template as of …
Block height tip last block … ago
Next retarget next multiple of 2016 N blocks away (hidden on regtest)
Pool hashrate (1h) 1h 24h average
Blocks mined (24h) confirmed confirmed, all time
Coins mined confirmed reward_sats (after fee), in COIN_SYMBOL confirmed only, after fee
Active users distinct payout addresses, 24h workers hashing (a share in the last 15 min)
Fee fee_bps "verifiable in each coinbase" only when the fee is its own coinbase output

Network hashrate

The dashboard has no bitcoind RPC, so stats.networkHashrate() takes block times from the templates table: the first template at a new height marks a block arrival. Hashrate is the work of those blocks (difficulty × 2^32) divided by the time span the rows cover.

  • Heights are compared against the running max, so a reorg that steps back and forward is not counted twice.
  • A jump of several heights (proxy down, missed poll) counts every skipped block.
  • With fewer than 6 arrivals the tile falls back to the difficulty-implied figure (D × 2^32 / 600) and says so. Pool share shows "—" in that case.

These are arrival times as the pool saw them, not header timestamps.

Other changes

  • fmtHashrate no longer renders sub-1 H/s values as 0.00 H/s (a forknet's implied hashrate is about 0.003 H/s).
  • New COIN_SYMBOL env var (default BTC) sets the unit for reward amounts on the overview and /blocks, e.g. COIN_SYMBOL=pECX on a forknet. Documented in the dashboard README and .env.example.
  • nodeStatus() / /api/node now carry network_hashrate, the figure implied by difficulty.

Test plan

  • npm test in dashboard/: 204 pass, 0 fail
  • New test/headline-stats.test.js covers: arrivals and span math, reorg and gap handling, the minimum-blocks fallback, the retarget boundary and regtest, active users and coins mined, and rendering both a populated and an empty pool
  • Rendered against a seeded DB and checked the layout in a browser
  • Started with COIN_SYMBOL=pECX; the overview and /blocks show pECX

Ten headline tiles at the top of the overview: network hashrate, pool
share, network difficulty, block height, next retarget, pool hashrate,
blocks mined, coins mined, active users and fee.

Network hashrate is measured from block arrivals in the templates table
(the dashboard has no bitcoind RPC): each first template at a new height
is a block arrival, and the work of those blocks is divided by the span
the rows cover. Heights are compared to the running max so a reorg is not
counted twice, and a gap counts every skipped height. With fewer than six
arrivals it falls back to the difficulty-implied figure and says so, and
pool share is only computed against a measured figure.

fmtHashrate no longer renders sub-1 H/s values as "0.00 H/s", which a
forknet's implied network hashrate would otherwise read as.
Block rewards were always labelled BTC, which on a forknet claims mainnet
value the coins don't have. fmtBtc takes the symbol, and server.js binds
it from COIN_SYMBOL (default BTC) for every public view that shows a
reward: the overview and /blocks.

"Workers hashing" on the at-a-glance card counted every worker with a
share in the last 24h, the same as active workers, so a rig switched off
this morning still read as hashing. It now counts workers with a share in
the last 15 minutes (HASHING_WINDOW_SEC).
@rsantacroce
rsantacroce merged commit a60ecec into main Oct 12, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant