Block found celebration + smarter ZMQ stale detection

Replace the subtle petal animation with a full block-found party:
confetti rain, sakura petals, ember burst, and a dismissible banner
showing block height and reward. Triggers on pool block finds (not
every network block). Animations loop until the user clicks dismiss.

Fix ZMQ stale banner false-positiving during long block intervals by
comparing ZMQ age against tip-change age instead of a fixed 30-min
threshold. Add tip_changed_age to the snapshot so the UI can tell
"no blocks on the network" from "ZMQ is broken". Use solid background
colors on health banners instead of transparent rgba.
This commit is contained in:
satoshi
2026-05-12 01:36:33 +03:00
parent 5e7be22e8e
commit 467fe5e2ef
4 changed files with 352 additions and 91 deletions
+15
View File
@@ -87,6 +87,7 @@ type Snapshot struct {
ZMQEnabled bool `json:"zmq_enabled"`
LastZMQEventAge float64 `json:"last_zmq_event_age,omitempty"` // seconds; >=0
HasLastZMQEvent bool `json:"has_last_zmq_event"`
TipChangedAge float64 `json:"tip_changed_age"` // seconds since tip height last changed
// Share counters: raw counts (1 submission = 1 share regardless of diff).
// Session = since ckpool started; AllTime = persisted across restarts.
@@ -214,6 +215,12 @@ type Aggregator struct {
zmqEnabled bool
lastZMQEventTime time.Time
// Tip-change tracking: the height and time when we last saw the
// chain tip advance. Used to distinguish "ZMQ stale" from "no
// blocks on the network".
lastTipHeight int64
lastTipChangedAt time.Time
// All-time share counters (raw, not diff-weighted). Accumulated
// using the same delta-integration pattern as cumulative_shares.
allTimeAccepted int64
@@ -337,6 +344,14 @@ func (a *Aggregator) refresh(ctx context.Context) {
if bi, err := a.RPC.GetBlockchainInfo(ctx); err == nil {
next.Chain = bi
next.BitcoinOK = true
// Track when the tip height last changed.
if bi.Blocks != a.lastTipHeight {
a.lastTipHeight = bi.Blocks
a.lastTipChangedAt = time.Now()
}
if !a.lastTipChangedAt.IsZero() {
next.TipChangedAge = time.Since(a.lastTipChangedAt).Seconds()
}
if nh, err := a.RPC.GetNetworkHashPS(ctx, -1, int(bi.Blocks)); err == nil {
next.NetworkHashrateHs = nh
}