Proposal: Multi-wallet viewer screen + Quantus brand theme for miner-app
Working prototype is running locally as a watch-only Python web dashboard at localhost:7878 while this proposal is reviewed. It queries the local node's RPC directly for any number of tracked SS58 addresses and renders a gray + orange UI matching the proposed Quantus design direction.
This doc proposes folding the same feature into miner-app/ as a first-class screen, and applying the gray + orange palette across the existing dashboard.
Motivation
Today the miner app has a single MinerBalanceCard tied to the wormhole preimage configured in setup. That's the right primary view for "what am I earning?" — but it leaves three real gaps:
- Mining rewards land in the standard Balances pallet, not as wormhole UTXOs (see
pallets/mining-rewards/src/lib.rs:220: T::Currency::mint_into(miner, reward)). The current WormholeUtxoService.getUnspentBalance view does not surface them. A miner who has won blocks sees "0 QUAN" in the GUI while System.Account(addr).data.free shows a non-zero balance. Reported live on this account: qzjtdBwdhUVKtJVi2hatJ3H6XCuEmNxkYCKem5k8se64mz3mE → 0.7739 QUAN on chain, 0 in current GUI.
- No multi-wallet view. A user with a CLI-generated wallet and a phone wallet has to context-switch between two UIs to reconcile balances.
- Default Material 3 theme ships out of the box. The dashboard reads as a generic Flutter app, not as Quantus.
Feature A — Wallet viewer screen (watch-only)
User-facing behaviour
A new route at /wallets reachable from the dashboard's hamburger menu, alongside Logout (Full Reset) and Settings.
- Auto-imports the active miner's wormhole address with the label "Mining wallet".
- Adds arbitrary addresses via a
+ button → modal with an SS58 input field (paste-only; no key material).
- Shows for each row: label, full SS58 (truncated with copy button), free balance from
System.Account(addr).data.free, status pill (Active / No account / Error).
- Total at the bottom.
- Auto-refresh every 10 s; mining-event-driven refresh hook reusing the existing
MinerConfig.blockSubmittedLogMarker pattern from miner_balance_card.dart.
- Persists wallet list to local app storage (Hive or
shared_preferences — whatever the project's existing convention is).
Why standard System.Account, not wormhole UTXO
Mining rewards mint into the standard Balances pallet at the wormhole address. To make those balances visible to the user without a wormhole withdrawal proof, we need a direct state_getStorage(System.Account(addr)) query. The reference Python prototype shows this works against the local node with no node-side changes.
The wormhole UTXO view stays the right primary view for "spendable, privacy-protected balance" and should not be removed — this is an additive secondary view.
Suggested Dart structure
miner-app/lib/features/wallets/
wallets_screen.dart // ListView of WalletTile
wallet_tile.dart // label, address, balance, status
add_wallet_dialog.dart // paste SS58, validate, save
wallet_repository.dart // load/save list, in-memory cache
wallet_balance_service.dart // state_getStorage queries via RPC
miner-app/lib/main.dart // add `/wallets` GoRoute
The balance service should reuse the existing quantus_sdk RPC client. Storage-key computation is twox128("System") || twox128("Account") || blake2_128_concat(account_id); the SDK already has these primitives (qp-poseidon-core and friends).
Reference implementation
The Python prototype at scripts/balance-viewer.py in adamtpang/quantus-windows-miner (or wherever this contrib lands) implements the SS58 decode, storage-key derivation, RPC call, and AccountInfo decode in ~50 lines using only xxhash, base58, and hashlib. The HTML dashboard demonstrates the gray + orange aesthetic targeted in Feature B below.
Feature B — Quantus gray + orange theme
The dashboard today inherits ThemeData.dark(useMaterial3: true), which is why buttons read as Material default blue and sliders as Material default purple.
Proposed palette (Flutter constants)
// miner-app/lib/src/theme/quantus_theme.dart
class QuantusColors {
// Neutral scale (background → foreground)
static const bg0 = Color(0xFF0C0C0D);
static const bg1 = Color(0xFF161618);
static const bg2 = Color(0xFF1F1F23);
static const bg3 = Color(0xFF2A2A2F);
static const border = Color(0x12FFFFFF); // rgba(255,255,255,0.07)
static const fg = Color(0xFFF4F4F5);
static const fgMuted = Color(0xFFA1A1AA);
static const fgDim = Color(0xFF71717A);
// Quantus orange
static const orange = Color(0xFFF97316);
static const orangeHover = Color(0xFFFB923C);
static const orangeSoft = Color(0x1FF97316); // rgba(249,115,22,0.12)
// Status
static const err = Color(0xFFEF4444);
}
ThemeData quantusTheme() => ThemeData(
useMaterial3: true,
brightness: Brightness.dark,
scaffoldBackgroundColor: QuantusColors.bg0,
colorScheme: const ColorScheme.dark(
primary: QuantusColors.orange,
secondary: QuantusColors.orange,
surface: QuantusColors.bg1,
error: QuantusColors.err,
),
// ... typography, card theme, button theme matching the HTML prototype
);
Apply in main.dart:
MaterialApp.router(
title: 'Quantus Miner',
theme: quantusTheme(),
routerConfig: _router,
);
What this changes visibly
- "Start Node" button: blue → orange
- Sliders (CPU Workers, GPU Devices): purple → orange
- Idle/Mining pill: maintains shape, picks up orange accent for active states
- Backgrounds shift from default dark to a tighter, more brand-aligned gray scale
- Update banner: keeps blue for "info" or shifts to orange for emphasis (design call)
Acceptance criteria
Out of scope (defer to follow-ups)
- Sending / withdrawing from this screen (read-only intentionally)
- Wormhole withdrawal proof generation
- Per-wallet transaction history
- Theme switching / light mode
Happy to PR
If a maintainer can confirm the route placement and any naming preferences (/wallets vs /balances vs /portfolio), I'm happy to put up a draft PR with the new screen + theme. The Python prototype is a 1:1 reference for the visible behaviour.
Closes the dashboard mystery in adamtpang's stuck-dashboard issue by giving users a working balance view independent of the wormhole-UTXO sync state.
Proposal: Multi-wallet viewer screen + Quantus brand theme for miner-app
Working prototype is running locally as a watch-only Python web dashboard at
localhost:7878while this proposal is reviewed. It queries the local node's RPC directly for any number of tracked SS58 addresses and renders a gray + orange UI matching the proposed Quantus design direction.This doc proposes folding the same feature into
miner-app/as a first-class screen, and applying the gray + orange palette across the existing dashboard.Motivation
Today the miner app has a single
MinerBalanceCardtied to the wormhole preimage configured in setup. That's the right primary view for "what am I earning?" — but it leaves three real gaps:pallets/mining-rewards/src/lib.rs:220:T::Currency::mint_into(miner, reward)). The currentWormholeUtxoService.getUnspentBalanceview does not surface them. A miner who has won blocks sees "0 QUAN" in the GUI whileSystem.Account(addr).data.freeshows a non-zero balance. Reported live on this account:qzjtdBwdhUVKtJVi2hatJ3H6XCuEmNxkYCKem5k8se64mz3mE→ 0.7739 QUAN on chain, 0 in current GUI.Feature A — Wallet viewer screen (watch-only)
User-facing behaviour
A new route at
/walletsreachable from the dashboard's hamburger menu, alongsideLogout (Full Reset)andSettings.+button → modal with an SS58 input field (paste-only; no key material).System.Account(addr).data.free, status pill (Active / No account / Error).MinerConfig.blockSubmittedLogMarkerpattern fromminer_balance_card.dart.shared_preferences— whatever the project's existing convention is).Why standard
System.Account, not wormhole UTXOMining rewards mint into the standard Balances pallet at the wormhole address. To make those balances visible to the user without a wormhole withdrawal proof, we need a direct
state_getStorage(System.Account(addr))query. The reference Python prototype shows this works against the local node with no node-side changes.The wormhole UTXO view stays the right primary view for "spendable, privacy-protected balance" and should not be removed — this is an additive secondary view.
Suggested Dart structure
The balance service should reuse the existing
quantus_sdkRPC client. Storage-key computation istwox128("System") || twox128("Account") || blake2_128_concat(account_id); the SDK already has these primitives (qp-poseidon-coreand friends).Reference implementation
The Python prototype at
scripts/balance-viewer.pyin adamtpang/quantus-windows-miner (or wherever this contrib lands) implements the SS58 decode, storage-key derivation, RPC call, and AccountInfo decode in ~50 lines using onlyxxhash,base58, andhashlib. The HTML dashboard demonstrates the gray + orange aesthetic targeted in Feature B below.Feature B — Quantus gray + orange theme
The dashboard today inherits
ThemeData.dark(useMaterial3: true), which is why buttons read as Material default blue and sliders as Material default purple.Proposed palette (Flutter constants)
Apply in
main.dart:What this changes visibly
Acceptance criteria
/walletsroute exists and is reachable from the existing menustate_getStorage(System.Account(addr))and refreshes every 10 squantus_sdkalready exposesQuantusColors+quantusTheme()applied app-wide; existing screens visually pass through unchanged in layoutOut of scope (defer to follow-ups)
Happy to PR
If a maintainer can confirm the route placement and any naming preferences (
/walletsvs/balancesvs/portfolio), I'm happy to put up a draft PR with the new screen + theme. The Python prototype is a 1:1 reference for the visible behaviour.Closes the dashboard mystery in adamtpang's stuck-dashboard issue by giving users a working balance view independent of the wormhole-UTXO sync state.