Files
donkey-ai dc166d04ff feat(bal): Group A (timestamps + statuses + anticipate docs) and Group B (auto-sign) v0.3.4
Bump plugin version to 0.3.4 (manifest, __init__, plugin_base, VERSION).

GROUP A
- A1: remove block-height locktimes; the plugin now uses UNIX timestamps
  only. The NLOCKTIME_BLOCKHEIGHT_MAX guard is kept on purpose (it forces
  every locktime to be a timestamp). chk_locktime is now 2-arg; int_locktime
  and anticipate_locktime no longer accept blocks; RAW input only accepts d/y.
  Two now-dormant configs (LOCKTIME_BLOCKS, LOCKTIMEDELTA_BLOCKS) are kept with
  comments to avoid touching persisted keys.
- A2: rename PENDING -> MEMPOOL everywhere (label 'Mempool', yellow #ffce30);
  add new UPDATED status; ANTICIPATED & UPDATED keep VALID; documented
  set_status rules; backward-compat migration (old PENDING -> MEMPOOL).
- A3: clarify that anticipating to a future date only rebuilds (never
  invalidates), while only a past locktime invalidates (WillExpired). Code was
  already correct; only the comment and docs were fixed.

Colour follow-up: UPDATED lightened from #800080 to #b266b2 (more readable),
updated in theme.py, docs and the theme test.

GROUP B
- B1: verified the 'Create your will' button already opens the guided wizard
  (no code change needed).
- B2: new persisted AUTO_SIGN setting (default ON) with an 'Auto-sign on Check'
  checkbox in the settings dialog. When enabled, Check signs and broadcasts
  automatically; the wallet password is requested only for encrypted wallets.

B2 follow-up (fixes reported after testing):
- Remove the duplicate sign/broadcast cycle in lists.check(); build_will_task()
  already signs and broadcasts.
- Suppress the manual 'press Sign/Broadcast' hint and its popup when AUTO_SIGN
  is ON (kept when OFF).
- Make broadcast one-shot: removed the retry flag and the Exception('retry');
  failed will-executors stay PUSH_FAIL and are skipped (no endless retry).
  PUSHED transactions are already excluded from re-collection.

Docs: inheritance-options.md/.html and inheritance-flow.svg updated to v0.3.4.
Tests: 206 passing (new test_anticipate_manual_locktime, test_anticipate_past_locktime,
test_group_b_auto_sign; updated core/util, core/will_extra, gui/theme, gui/widgets).
CHANGELOG.md added with one numbered entry per task.
2026-06-28 23:00:23 -04:00

99 lines
3.9 KiB
Python

"""
bal.gui.qt.theme
================
Pure presentation helpers for the Qt layer.
This is where colours and other look-and-feel decisions live, kept apart from
the core inheritance logic. In particular it hosts :func:`status_color`, which
used to be ``WillItem.get_color()`` inside ``will.py``.
The status flags themselves are computed by the core layer
(:class:`bal.core.will.WillItem`); this module only translates a will item's
status into a colour for the transaction list / detail views.
"""
# Status -> hex colour. The first matching status (checked in priority order)
# wins. These are exactly the colours the original ``WillItem.get_color`` used,
# so the GUI looks identical after the refactor.
#
# The order matters: e.g. an INVALIDATED tx must show orange even if it also
# carries other flags, so INVALIDATED is checked before everything else.
_STATUS_COLOR_PRIORITY = (
("INVALIDATED", "#f87838"), # orange - tx can no longer be mined
("REPLACED", "#ff97e9"), # pink - superseded by another tx
("UPDATED", "#b266b2"), # light violet - replaced keeping same locktime+heirs
("CONFIRMED", "#bfbfbf"), # grey - already mined
("MEMPOOL", "#ffce30"), # yellow - seen in the Electrum mempool
)
# Default colour used when no status in the priority list matches.
_DEFAULT_COLOR = "#ffffff"
def status_color(will_item) -> str:
"""Return the display colour (``"#rrggbb"``) for a :class:`WillItem`.
This is a faithful, behaviour-preserving port of the old
``WillItem.get_color()`` method. The slightly irregular handling of the
push/check states (which is not a simple priority list) is reproduced
exactly as in the original code.
"""
# First, the simple priority-ordered statuses.
for status, color in _STATUS_COLOR_PRIORITY:
if will_item.get_status(status):
return color
# The remaining states need the original branching because of the
# CHECK_FAIL / CHECKED interaction.
if will_item.get_status("CHECK_FAIL") and not will_item.get_status("CHECKED"):
return "#e83845" # red - server check failed
elif will_item.get_status("CHECKED"):
return "#8afa6c" # green - server confirmed it stored the tx
elif will_item.get_status("PUSH_FAIL"):
return "#e83845" # red - failed to push to will-executor
elif will_item.get_status("PUSHED"):
return "#73f3c8" # teal - pushed to will-executor
elif will_item.get_status("COMPLETE"):
return "#2bc8ed" # blue - signed
else:
return _DEFAULT_COLOR
def server_status_text(will_item) -> str:
"""Return a short, human-readable label describing the state of a will
item on the will-executor servers (the online inheritance backup).
This is shown in the dedicated "Server" column of the transaction list so
the user always knows whether each inheritance transaction is actually
stored on the will-executor servers, regardless of the row colour.
"""
from electrum.i18n import _
if will_item.get_status("CHECK_FAIL") and not will_item.get_status("CHECKED"):
return _("Not on server")
if will_item.get_status("CHECKED"):
return _("Confirmed on server")
if will_item.get_status("PUSH_FAIL"):
return _("Send failed")
if will_item.get_status("PUSHED"):
return _("Sent (not checked)")
if will_item.get_status("COMPLETE"):
return _("Signed (not sent)")
return _("Not sent")
def server_status_tooltip(will_item) -> str:
"""Return a detailed tooltip for the "Server" column, including the
will-executor URL (if any) and the current server state."""
from electrum.i18n import _
url = None
we = getattr(will_item, "we", None)
if we:
url = we.get("url")
state = server_status_text(will_item)
if url:
return "{}: {}\n{}".format(_("Will-Executor"), url, state)
return "{}\n{}".format(_("No will-executor"), state)