The audit (docs/plans/wallet-ui-3-audit.md, 24 before-captures), the design (docs/plans/wallet-ui-3.md) and the
build: five sections in the miner's rail (Home, Send, Receive, History, Settings), the balance first with the money
line ("no market price on devnet: coins have no value" until price_gbp_per_ign exists), one node line with Details,
Send confirmed in place with the fee behind Details and the pending row after, Receive with the address box and the
QR, History with the node's ONE state word per row (pending, included, executed, proven, finalised; the wallet's own
verified final wins; failed from the receipt) and a reason line, Settings as plain rows (Security, Backup, This
machine with Appearance, the Igneum Wallet update card, Node with the endpoint, Advanced with the remove ask), no
dialogs, dark and light, a bottom tab bar under 720 px. The Rust engine is untouched: the node words come from the
existing GET /api/tx/<hash>. One Swift line removed so the window follows the Mac's appearance.
view.test.mjs (11) with lock-screen (5) and update-card (4): 20 pass. tools/ui-mock/wallet.mjs and shoot-wallet.mjs
(one niced headless chromium, closed after the batch). Result captures n00 to n24 beside the audit's, and the real
Mac window m00 to m06 from this worktree's engine on a scratch data dir with a throwaway wallet (deleted after).
Site: wallet.html and the wallet section of index.html on the shipped design; wallet-home.webp and wallet-final.webp
from the mock with example addresses.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The one long page becomes a rail with six sections, a thin top bar and the status strip under it; the setup
screens and the key sheet stay. Mine: one big start/stop, the numbers, one row per GPU with its switch, hash
rate, temperature and power. Prove: the switch with plain words, the counts, the verifier, the pinned ids.
Rewards: the address with one Copy, the key backup card, another address. Node: the plain lines, the consensus
digest, the next switch. Updates: the version, the jobs. Settings: one switch or slider per setting with one line
of help. Every function that existed is placed, none removed.
Engine (three small additions, each with a unit test): node.consensus_digest from the node's own line,
node.consensus_switches from the override file, proving.program_id and aggregator_id from the host's --mode id.
Hosts: the window minimum is 900 x 600 on both. UI tests: view.test.mjs (10) joins notices and update-card in CI.
Proof: docs/plans/miner-ui-2.md and the 19 screenshots under docs/plans/miner-ui-2/, taken from a build of this
tree running on its own port against the devnet.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The window host owns the prompt and the secret (app/mac/Biometric.swift): LAPolicy.deviceOwnerAuthenticationWithBiometrics
with "Use password" as the fallback button (never the device password), the wallet's password sealed to a Secure
Enclave key made with .biometryCurrentSet (the Keychain refuses biometric access controls under the ad hoc signature,
-34018, measured) in <data>/wallet/biometric.json; a fingerprint change invalidates it. The engine owns the gate
(igneum-common/src/biometric.rs): a nonce per action, read by the host with its token (the HOST line on stdout,
X-Igneum-Host on host-only calls), confirmed after the prompt, taken once within 30 s and bound to the exact quote;
/api/send refuses without it while enrolled; /api/reveal with a nonce reads the unlocked key in memory; the password
never goes through the page (enrolment parks it under a one-time token the host takes). Idle lock after 5 minutes
without window activity (setting, default on). A password change or a wallet removal deletes the sealed file.
Reason lines in our voice ("Unlock your wallet", "Send 1.5 IGN to 0x7E5F…5Bdf", "Show your recovery words"); the page
shows its own ember line after every prompt. Windows: app/windows/biometric.h (UserConsentVerifier through
IUserConsentVerifierInterop, DPAPI), wired into wallet-host.cpp and BUILD-WALLET-APP.bat, not yet compiled on a PC.
Hosts gain a @main entry so Biometric.swift compiles alongside; build-wallet-dmg.sh links LocalAuthentication.
Balance card: the coin at 56 px, "0" (or the balance) as soon as the node answers, "reading the chain, N of M blocks"
under it while the history scans. Version: v0.1.2 in the brand band, "Igneum Wallet 0.1.2 · up to date" in Settings.
Unit tests: the gate (7, igneum-common), the wallet's 17 still green. README: the flows, the threat model, what was
verified on this Mac (enrol and unlock through the real prompt) and what was not.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
app/igneum-common (new library crate): the platform helpers with the app identity as a parameter, the payout key
code, the signed OTA manifest (byte-identical to the miner's), the manifest fetch and download check, the 127.0.0.1
server primitives and a JSON client, run_timeout, the packaged config and machine id. Nothing in app/igneum-app
changed; `cargo check -p igneum-app` still passes.
app/igneum-wallet (new): create (24 words, three typed back) or import (words, raw key, the miner's wallet.json),
sealed with Argon2id + XChaCha20-Poly1305 under the user's password; balance, send (EIP-1559, signed in Rust, zero
address refused, fee shown as base fee + tip), receive with a QR drawn locally, history (transfers, block rewards from
the execution records, shard payouts when they exist); finality per transaction verified by the wallet itself with the
node's own finality code (certificate from the blocks after the checkpoint, canonical voter list, aggregate BLS
signature, 2/3 of active and of total weight), shown as pending / in a block / final with the checkpoint index; export
to MetaMask (key with a warning, network parameters, add-network link); node source order: the miner app's node,
the environment's node, the bundled igneumd, the packaged public RPC. 13 unit tests.
Hosts and packaging: app/mac/IgneumWallet.swift, app/windows/wallet-host.* (untested), packaging/mac/build-wallet-dmg.sh,
packaging/windows/Igneum-Wallet.iss, publish-manifest.sh --product wallet (miner path unchanged).
tools/wallet-testnet/run.mjs and the bench-log entry: on igneum-devnet-958 a transfer went pending, in a block and
final under checkpoint 5, 170.6 s after sending, the certificate verified by the wallet.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>