Files
observer/web/vite.config.ts
rob thijssen 110fbc3631 feat: blackbeard.observer — live Quantus mining leaderboard
Cargo workspace plus a Vite frontend, following ~/git/architecture/generic.md.

Every block header carries its author's wormhole reward preimage in a `pow_`
PreRuntime digest, so authorship for the whole network is derivable from headers
alone — no indexer, no registration, no way for a miner to be left out. That
decoding, the hashrate maths and the telemetry name attribution live in
blackbeard-core with no I/O at all, so the parts that are easy to get subtly
wrong are exercised by unit tests rather than only against a live chain.

The browser holds one WebSocket: snapshot on subscribe, deltas thereafter. The
head stream is itself a push (chain_subscribeNewHeads), so a block reaches the
page the moment the node imports it. Messages are serialised once per broadcast,
and leaderboards are recomputed only for windows a socket is actually watching.
No RxJS — useSyncExternalStore is React's own contract for this.

Verified against the live Planck testnet: 12/12 headers decoded, telemetry names
attributed (quanpool-planck, baba-gorchitsa, …), warm start restoring 84 blocks
and 5 held names across a restart.

Three findings worth recording, all in CLAUDE.md:

- substrate-telemetry sends its JSON in *binary* frames. A text-only client
  connects, subscribes, reports healthy and receives nothing at all — and a
  Python probe hides it, because json.loads accepts bytes.
- Difficulty is a little-endian U512; decoding it big-endian gives a number
  wrong by ~10^150 that still renders fine.
- Planck's real block interval is ~13-15s against a 6s target with enormous
  variance, so a measured interval needs 20 tip samples before it is publishable.

Deploy assets, the Gitea Actions workflow and script/infra-setup.sh are included;
port 25864 is registered in architecture/port-allocations.md.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MSDYiibCtELsrjQq6KXnoi
2026-09-04 12:33:54 +03:00

27 lines
834 B
TypeScript

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'
// The built output is static and served by nginx from /var/www/blackbeard.observer;
// there is no Node.js in production (architecture/generic.md §4).
export default defineConfig({
plugins: [react()],
build: {
// Source maps ship: the bundle is public, the code is GPL, and a stack
// trace from a miner's browser is worth far more than the bytes.
sourcemap: true,
},
server: {
port: 5173,
// `pnpm dev` talks to a locally-run blackbeard-api so the browser sees one
// origin and the WebSocket upgrade needs no CORS dance — the same shape
// nginx presents in production.
proxy: {
'/v1': {
target: 'http://127.0.0.1:25864',
changeOrigin: true,
ws: true,
},
},
},
})