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 — ошибка: %s",
"merge_keep_each_status_not_started": "%s — не запущено: %s",
"merge_keep_each_status_running": "%s — объединение %d заметок (готово партий: %d из %d)…",
"merge_keep_each_status_unconfirmed": "%s — статус не удалось подтвердить",
"merge_keep_each_too_small": "Слишком мало для объединения: комиссия съест эти средства.",
"merge_max_inputs": "Макс. входов за партию",
"merge_no_spendable": "Пока нет доступных для расходования входов для объединения.",
"merge_progress": "Объединение… это может занять несколько минут. Вы можете закрыть это окно.",
"merge_scope_failed_fmt": "Не удалось прочитать ваши входы: %s",
"merge_scope_fmt": "%d прозрачных + %d защищённых входов · ~%s DRGX доступно",
"merge_scope_loading": "Проверка ваших входов…",
"merge_send_failed": "Ошибка объединения: ",
@@ -1190,7 +1192,10 @@
"merge_src_shielded": "Защищённые",
"merge_src_transparent": "Прозрачные",
"merge_started": "Операция объединения начата",
"merge_submit_uncertain": "Узел не подтвердил объединение до разрыва соединения. Оно всё ещё может выполниться — после переподключения проверьте Историю, прежде чем объединять снова.",
"merge_title": "Объединить на адрес",
"merge_wait_locked": "Кошелёк заблокирован. Разблокируйте его, чтобы продолжить.",
"merge_waiting_node": "Ожидание узла…",
"merge_where": "Куда направить средства?",
"mig_adopt": "Сделать это моим кошельком",
"mig_adopt_now": "Принять сид-кошелёк",