perf(net): one balance scan per poll, filtered opstatus, a guarded merge scope

The Core poll ran z_gettotalbalance twice (minconf 0 and 1), each a whole-
wallet scan under dragonxd's cs_main. The spendable (minconf=1) call now
runs only after the display call succeeded, and only when something is
unconfirmed or pending or the exact total moved: about 95% of polls make
one scan instead of two. A forced post-send balance can no longer be lost
to a refused enqueue, and pending-send debits aren't re-applied each tick.

z_getoperationstatus is filtered to our opids with its real argument form
([[id,...]]; the old ["id"] was rejected), falling back to the unfiltered
call if a daemon refuses the filter. The Shield/Merge dialog's own polls
are filtered and session-guarded too, and finally reach Done; the dead
RPCClient wrappers are deleted.

The Merge/Consolidate scope scan becomes a tested state machine: one scan
at a time, failures latch behind a Retry button, only "node not ready"
retries by itself (10/30/60 s, at most 3), Lite never scans. Its 120 s
calls are maintenance calls: every main-thread disconnect aborts one in
flight first, so a lifecycle action no longer freezes the UI behind it.
An aborted merge that was already sent says it may still go through.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-09 11:06:34 -05:00
co-authored by Claude Opus 5.5
parent 4eed4283d6
commit 8b9a498eee
23 changed files with 1044 additions and 128 deletions
+5
View File
@@ -1178,10 +1178,12 @@
"merge_keep_each_status_failed": "%s — échec : %s",
"merge_keep_each_status_not_started": "%s — non démarré : %s",
"merge_keep_each_status_running": "%s — fusion de %d notes (%d lots sur %d terminés)…",
"merge_keep_each_status_unconfirmed": "%s — statut non confirmé",
"merge_keep_each_too_small": "Trop faible pour être consolidé : les frais absorberaient ces fonds.",
"merge_max_inputs": "Nombre max d'entrées par lot",
"merge_no_spendable": "Aucune entrée dépensable à consolider pour l'instant.",
"merge_progress": "Consolidation en cours… cela peut prendre quelques minutes. Vous pouvez fermer cette fenêtre.",
"merge_scope_failed_fmt": "Impossible de lire vos entrées : %s",
"merge_scope_fmt": "%d entrées transparentes + %d blindées · ~%s DRGX dépensables",
"merge_scope_loading": "Vérification de vos entrées…",
"merge_send_failed": "Échec de la fusion : ",
@@ -1190,7 +1192,10 @@
"merge_src_shielded": "Blindées",
"merge_src_transparent": "Transparentes",
"merge_started": "Opération de fusion démarrée",
"merge_submit_uncertain": "Le nœud n'a pas confirmé la fusion avant l'interruption de la connexion. Elle peut tout de même aboutir — vérifiez l'Historique après la reconnexion avant de fusionner à nouveau.",
"merge_title": "Fusionner vers une adresse",
"merge_wait_locked": "Le portefeuille est verrouillé. Déverrouillez-le pour continuer.",
"merge_waiting_node": "En attente du nœud…",
"merge_where": "Où doivent aller les fonds ?",
"mig_adopt": "Faire de ceci mon portefeuille",
"mig_adopt_now": "Adopter le portefeuille à phrase",