feat(ui): treat transparent addresses as mining-only addresses

DragonX is a private chain (-ac_private=1): consensus rejects any
non-coinbase output to a transparent address, so a t-address can only
ever receive mining rewards, and its coins can only move to a shielded
address. The wallet treated them like ordinary recipients.

Block paying one:
- Send: a transparent recipient shows "Mining address - can't be paid"
  and disables Review Send (tooltip explains; ask for a zs... address).
  Typing, paste, contacts and payment URIs all go through this field.
- Overview drag-to-transfer: a mining-address row is never a transfer
  target (it only reorders).
- Pool payout must be shielded (pools pay with ordinary transactions):
  field tooltip, disabled Start button and the start check say why.
- isValidRecipientAddress() is now shielded-only; new isDragonXAddress()
  and classifyRecipient() (Shielded / MiningOnly / Invalid).

Call them mining addresses:
- Overview: "Mining rewards" card (amber "Not yet shielded" when there
  is a balance; hover explains; click opens the Shield dialog), "New
  mining address" button with a tooltip, rows typed "Mining".
- QR / label dialogs, portfolio filter, contact badge ("Mining only"),
  Receive notifications.

i18n: 17 new keys in all 8 languages, 12 dead keys removed, CJK subset
rebuilt. Tests: recipient classification, translation completeness.
UI sweep: new "send-mining-recipient" target.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-02 20:08:14 -05:00
co-authored by Claude Opus 5.5
parent a3361020d1
commit 5246898968
26 changed files with 468 additions and 162 deletions
+4 -2
View File
@@ -2689,10 +2689,12 @@ void App::startPoolMining(int threads)
// Validate the payout address at EVERY start entry point (manual Start button, idle auto-start, thread
// scaling) — not just the UI gate — since a stale/hand-edited/wrong-chain address here silently loses
// mining rewards. (M-01) worker_name IS the pool login the rewards are credited to (see below).
// A pool pays with ordinary transactions, so only a shielded address can be paid (private chain).
if (!cfg.worker_name.empty() && cfg.worker_name != "x" &&
!util::isValidRecipientAddress(cfg.worker_name)) {
ui::Notifications::instance().error(
"Pool payout address is not a valid DragonX address — mining not started.");
ui::Notifications::instance().error(util::isTransparentAddress(cfg.worker_name)
? TR("mining_payout_needs_shielded")
: "Pool payout address is not a valid DragonX address — mining not started.");
return;
}
// The algo follows the pool: official pools use their own algo (pool.dragonx.cc