feat(bal): UI batch v0.3.9 + expired-will invalidate regression fix
UI batch (TASK A/B/C/D): - (A) Clearer 'Will expired' message: shortened will id (8+8 chars) and readable UTC date instead of raw UNIX timestamp; shown in WARNING colour (orange) instead of ERROR (red) in the wizard, as it is an expected step. - (A2) Split the orange message onto two lines via <br> (rendered as HTML by msg_warning) to avoid an overly long single line. - (B) History tab labels (text only): inheritance txs -> 'BAL Inheritance transaction'; invalidate tx -> 'BAL Invalidate transaction'. Colours left to Electrum defaults. - (C) New 'No will-executor TX' checkbox in plugin settings, bound to the existing NO_WILLEXECUTOR config (default ON, kept in sync with the wizard), with help text, and included in the settings reset action. - (D) Wizard button label 'Create your will' -> 'Build Your Will'. Regression fix (A3): - When an heir was added to an already-expired will via the wizard, the automatic invalidation no longer triggered. Root cause: the inner check_will() after build_will() raised WillExpiredException and the handler returned (False, None), which never invalidated. - Auto-opening the invalidation tx window from the closing wizard proved unreliable (the window ended up behind the main wallet on some window managers; a re-check loop could ask to invalidate repeatedly before the tx reached the mempool). The robust fix: close the wizard and show a clear instruction popup guiding the user to run 'Tools -> Invalidate' and then press 'Check' to finish the will. Reasoning documented in the code. Version bumped to 0.3.9 (manifest.json, __init__.py, plugin_base.py, VERSION). CHANGELOG entry #15 updated. Verified: py_compile OK, ruff clean (no new errors), full test suite 239 passed.
This commit is contained in:
69
CHANGELOG.md
69
CHANGELOG.md
@@ -784,3 +784,72 @@ the DATA mode and the RAW mode, while keeping the **CHECK ALIVE** title in bold.
|
|||||||
|
|
||||||
**Outcome:** DONE (delivered as a test ZIP v0.3.8 for the user to try before
|
**Outcome:** DONE (delivered as a test ZIP v0.3.8 for the user to try before
|
||||||
commit).
|
commit).
|
||||||
|
|
||||||
|
## 15. UI batch (v0.3.9): clearer "will expired" message, History labels, settings checkbox, wizard button
|
||||||
|
|
||||||
|
**Context:** A batch of four small UI improvements requested by the user
|
||||||
|
(internally tracked as TASK A/B/C/D).
|
||||||
|
|
||||||
|
**Changes:**
|
||||||
|
- **(A) "Will expired" message — clearer and not alarming.** Rewrote the message
|
||||||
|
raised by `Will.check_will_expired()` (`bal/core/will.py`): the will id is now
|
||||||
|
shortened (first 8 + last 8 chars, e.g. `9f1b0a75…fed9ae1b`) and the locktime
|
||||||
|
is shown as a readable UTC date (e.g. `2026-06-22 11:00 UTC`) instead of a raw
|
||||||
|
UNIX timestamp, with an explanation that the will will be invalidated and
|
||||||
|
re-signed. Two small helpers were added (`_short_will_id`, `_format_locktime`)
|
||||||
|
and `datetime`/`timezone` are now imported at module top. In the "Build your
|
||||||
|
will" wizard (`bal/gui/qt/dialogs.py`) an expired will is now shown in the
|
||||||
|
WARNING colour (orange) instead of the ERROR colour (red), because it is an
|
||||||
|
expected part of the flow, not an error.
|
||||||
|
- **(B) History tab labels (text only).** Renamed the labels written to
|
||||||
|
Electrum's History tab: inheritance transactions now read
|
||||||
|
`BAL Inheritance transaction` (was `BAL Transaction`, updated in both
|
||||||
|
`dialogs.py` and `window.py`) and the invalidate transaction now reads
|
||||||
|
`BAL Invalidate transaction` (was `BAL Invalidate`, in `window.py`). Colours
|
||||||
|
are left to Electrum's defaults (outgoing transactions are shown in red by
|
||||||
|
Electrum itself) to keep the change simple and robust.
|
||||||
|
- **(C) "No will-executor TX" checkbox in plugin settings.** Added a checkbox to
|
||||||
|
the settings dialog (`bal/gui/qt/plugin.py`) bound to the existing
|
||||||
|
`NO_WILLEXECUTOR` config (default ON), the same config used by the wizard's
|
||||||
|
will-executor download window, so the two stay in sync. Its help button reads:
|
||||||
|
"Create a will that does not require a Will-executor; it can be saved, for
|
||||||
|
example, on a USB stick, and a copy can be given to the heirs." It is also
|
||||||
|
included in the "Reset setting" action so a reset restores it to ON.
|
||||||
|
- **(D) Wizard button label.** The main wizard button now reads `Build Your Will`
|
||||||
|
(was `Create your will`, `bal/gui/qt/lists.py`), matching the tooltip and the
|
||||||
|
rest of the codebase which already call it the "Build your will" wizard.
|
||||||
|
|
||||||
|
- **(A2) Two-line expired message.** Following user feedback that the orange
|
||||||
|
message was too long on a single line, a `<br>` line break was added in
|
||||||
|
`Will.check_will_expired()` so the second sentence ("too late to anticipate,
|
||||||
|
the will will be invalidated and re-signed.") is shown on its own line. The
|
||||||
|
message is rendered as HTML by `msg_warning()`, so the `<br>` tag is honoured.
|
||||||
|
- **(A3) Auto-invalidate regression fix when adding an heir to an expired will.**
|
||||||
|
While verifying TASK A a regression was found: when an heir was added to an
|
||||||
|
already-expired will through the wizard, the automatic invalidation window no
|
||||||
|
longer opened (the user had to restart Electrum or press Check). Root cause:
|
||||||
|
in `dialogs.py::task_phase1`, adding an heir first raises
|
||||||
|
`HeirNotFoundException` (so the will is rebuilt by `build_will()`), and the
|
||||||
|
freshly rebuilt transactions are themselves expired, raising
|
||||||
|
`WillExpiredException` on the INNER `check_will()`. The original handler there
|
||||||
|
did `return False, None`, which never triggered invalidation. The fix makes
|
||||||
|
the wizard, in that case, behave exactly like the "Tools -> Invalidate" menu:
|
||||||
|
instead of trying to auto-open the invalidation transaction window (which
|
||||||
|
proved unreliable — depending on the OS window manager the transaction window
|
||||||
|
ended up BEHIND the main wallet window when the wizard closed, and an
|
||||||
|
automatic re-check loop could ask to invalidate repeatedly before the
|
||||||
|
invalidation tx reached the mempool), the wizard now closes and shows a clear
|
||||||
|
instruction popup telling the user to run `Tools -> Invalidate` themselves and
|
||||||
|
then press `Check`. That menu path is already known to work perfectly (its
|
||||||
|
transaction window stays in front and sets the `BAL Invalidate transaction`
|
||||||
|
history label) and it makes the user consciously aware of this deliberate,
|
||||||
|
important action. The reasoning behind this choice is documented in the code.
|
||||||
|
|
||||||
|
**Verification:**
|
||||||
|
- `py_compile` on all changed files: OK.
|
||||||
|
- `ruff check`: no new errors (only the pre-existing star-import noise and
|
||||||
|
pre-existing F841 warnings, none in the changed lines).
|
||||||
|
- Full test suite: `239 passed`.
|
||||||
|
|
||||||
|
**Outcome:** DONE (delivered as test ZIP v0.3.9, confirmed OK by the user before
|
||||||
|
commit).
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
0.3.8
|
0.3.9
|
||||||
|
|||||||
@@ -34,4 +34,4 @@ The plugin targets Electrum 4.7.2 (the last stable release exposing
|
|||||||
``json_db.register_dict``) and PyQt6.
|
``json_db.register_dict``) and PyQt6.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__version__ = "0.3.8"
|
__version__ = "0.3.9"
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ class BalPlugin(BasePlugin):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
_version = None
|
_version = None
|
||||||
__version__ = "0.3.8" # AUTOMATICALLY GENERATED DO NOT EDIT
|
__version__ = "0.3.9" # AUTOMATICALLY GENERATED DO NOT EDIT
|
||||||
|
|
||||||
# Command used to open an .ics calendar file, per operating system.
|
# Command used to open an .ics calendar file, per operating system.
|
||||||
default_app = {
|
default_app = {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ The status flags themselves (the source of truth) stay here; only the mapping
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
from electrum.i18n import _
|
from electrum.i18n import _
|
||||||
from electrum.logging import Logger, get_logger
|
from electrum.logging import Logger, get_logger
|
||||||
@@ -652,6 +653,47 @@ class Will:
|
|||||||
_logger.info("will ok")
|
_logger.info("will ok")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _short_will_id(will_id):
|
||||||
|
"""Return a human-friendly, shortened form of a will id (hash).
|
||||||
|
|
||||||
|
Will ids are long hex strings (e.g. a 64-char txid) that are hard to
|
||||||
|
read in a message box. This keeps only the first and last 8 characters
|
||||||
|
joined by an ellipsis (e.g. ``9f1b0a75…fed9ae1b``). Short ids are left
|
||||||
|
untouched.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
will_id: The will identifier (hash) to shorten; coerced to ``str``.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The shortened id, or the original string if it is short.
|
||||||
|
"""
|
||||||
|
text = str(will_id)
|
||||||
|
# Only shorten when there is something to gain (>= 20 chars), otherwise
|
||||||
|
# the ellipsis form would not actually be shorter or clearer.
|
||||||
|
if len(text) <= 20:
|
||||||
|
return text
|
||||||
|
return f"{text[:8]}\u2026{text[-8:]}"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _format_locktime(locktime):
|
||||||
|
"""Format a UNIX locktime timestamp as a readable UTC date string.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
locktime: UNIX timestamp (seconds) to format.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: A string like ``2026-06-22 11:00 UTC``. If formatting fails
|
||||||
|
for any reason, the raw timestamp is returned as a fallback so the
|
||||||
|
caller always has something to show.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
dt = datetime.fromtimestamp(int(locktime), tz=timezone.utc)
|
||||||
|
return dt.strftime("%Y-%m-%d %H:%M UTC")
|
||||||
|
except Exception:
|
||||||
|
# Never let date formatting break the (already exceptional) flow.
|
||||||
|
return str(locktime)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def check_will_expired(all_inputs_min_locktime, timestamp_to_check):
|
def check_will_expired(all_inputs_min_locktime, timestamp_to_check):
|
||||||
"""Raise WillExpiredException if any valid transaction has expired.
|
"""Raise WillExpiredException if any valid transaction has expired.
|
||||||
@@ -659,6 +701,12 @@ class Will:
|
|||||||
Locktimes are always UNIX timestamps, so a transaction is expired when
|
Locktimes are always UNIX timestamps, so a transaction is expired when
|
||||||
its locktime is in the past relative to ``timestamp_to_check``.
|
its locktime is in the past relative to ``timestamp_to_check``.
|
||||||
|
|
||||||
|
When a will is expired the message is written to be reassuring rather
|
||||||
|
than alarming: being past the locktime is an EXPECTED situation that the
|
||||||
|
plugin handles by invalidating the old will and re-signing it. The
|
||||||
|
message therefore uses a shortened will id and a human-readable UTC date
|
||||||
|
instead of raw values.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
all_inputs_min_locktime: Mapping prevout -> will-item info, used to
|
all_inputs_min_locktime: Mapping prevout -> will-item info, used to
|
||||||
find the minimum locktime per input.
|
find the minimum locktime per input.
|
||||||
@@ -671,12 +719,27 @@ class Will:
|
|||||||
locktime = int(wid[0][1].tx.locktime)
|
locktime = int(wid[0][1].tx.locktime)
|
||||||
# Locktimes are always timestamps: expired when in the past.
|
# Locktimes are always timestamps: expired when in the past.
|
||||||
if locktime < int(timestamp_to_check):
|
if locktime < int(timestamp_to_check):
|
||||||
|
# Build a clear, non-technical message: short id +
|
||||||
|
# readable date, and explain what will happen next.
|
||||||
|
short_id = Will._short_will_id(wid[0][0])
|
||||||
|
when = Will._format_locktime(locktime)
|
||||||
|
# The message is rendered as HTML by msg_warning(),
|
||||||
|
# so a <br> tag forces a line break: the second
|
||||||
|
# sentence goes on its own line to avoid an overly
|
||||||
|
# long single line in the wizard.
|
||||||
raise WillExpiredException(
|
raise WillExpiredException(
|
||||||
f"Will Expired {wid[0][0]}: {locktime}<{timestamp_to_check}"
|
"Will expired (id {id}, locktime {when}) \u2014<br>"
|
||||||
|
"too late to anticipate, the will will be "
|
||||||
|
"invalidated and re-signed.".format(
|
||||||
|
id=short_id, when=when
|
||||||
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
from datetime import datetime
|
_logger.debug(
|
||||||
_logger.debug(f"Will Not Expired {wid[0][0]}: {datetime.fromtimestamp(locktime).isoformat()} > {datetime.fromtimestamp(timestamp_to_check).isoformat()}")
|
f"Will Not Expired {wid[0][0]}: "
|
||||||
|
f"{Will._format_locktime(locktime)} > "
|
||||||
|
f"{Will._format_locktime(timestamp_to_check)}"
|
||||||
|
)
|
||||||
|
|
||||||
# def check_all_input_spent_are_in_wallet():
|
# def check_all_input_spent_are_in_wallet():
|
||||||
# _logger.info("check all input spent are in wallet or valid txs")
|
# _logger.info("check all input spent are in wallet or valid txs")
|
||||||
|
|||||||
@@ -648,13 +648,41 @@ class BalBuildWillDialog(BalDialog):
|
|||||||
|
|
||||||
self.bal_window.check_will()
|
self.bal_window.check_will()
|
||||||
for wid in Will.only_valid(self.bal_window.willitems):
|
for wid in Will.only_valid(self.bal_window.willitems):
|
||||||
self.bal_window.wallet.set_label(wid, "BAL Transaction")
|
# Label shown in Electrum's History tab for inheritance txs.
|
||||||
|
self.bal_window.wallet.set_label(wid, "BAL Inheritance transaction")
|
||||||
self.msg_set_building(self.msg_ok())
|
self.msg_set_building(self.msg_ok())
|
||||||
except WillExecutorNotPresent:
|
except WillExecutorNotPresent:
|
||||||
self.msg_set_status(
|
self.msg_set_status(
|
||||||
_("Will-Executor excluded"), None, _("Skipped"), self.COLOR_ERROR
|
_("Will-Executor excluded"), None, _("Skipped"), self.COLOR_ERROR
|
||||||
)
|
)
|
||||||
|
|
||||||
|
except WillExpiredException as e:
|
||||||
|
# An expired will is an EXPECTED situation (the locktime has
|
||||||
|
# passed). After adding/changing an heir the will is rebuilt
|
||||||
|
# above (build_will), and the freshly rebuilt transactions can
|
||||||
|
# themselves already be expired.
|
||||||
|
#
|
||||||
|
# We must NOT trigger the wizard's automatic invalidation loop
|
||||||
|
# here (return None, invalidate_tx). That loop re-runs
|
||||||
|
# task_phase1 right after broadcasting the invalidation, but the
|
||||||
|
# invalidation tx is not yet visible in the mempool, so the will
|
||||||
|
# is still detected as expired and the user is asked to
|
||||||
|
# invalidate again and again (infinite loop). It also never sets
|
||||||
|
# the "BAL Invalidate transaction" history label.
|
||||||
|
#
|
||||||
|
# Instead we reproduce EXACTLY what the "Tools -> invalidate"
|
||||||
|
# menu does (BalWalletWindow.invalidate_will): open Electrum's
|
||||||
|
# classic transaction dialog so the user can sign and broadcast
|
||||||
|
# the invalidation manually, set the proper history label, and
|
||||||
|
# stop. This is robust regardless of mempool confirmation state.
|
||||||
|
#
|
||||||
|
# The actual call to invalidate_will() (which opens GUI windows)
|
||||||
|
# must run in the GUI thread, so we only RETURN a signal here
|
||||||
|
# ("invalidate_classic"); on_success_phase1 performs the call.
|
||||||
|
# We still show the expired notice as a WARNING (orange).
|
||||||
|
self.msg_set_building(self.msg_warning(e))
|
||||||
|
return "invalidate_classic", None
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.msg_set_building(self.msg_error(e))
|
self.msg_set_building(self.msg_error(e))
|
||||||
return False, None
|
return False, None
|
||||||
@@ -906,6 +934,54 @@ class BalBuildWillDialog(BalDialog):
|
|||||||
# if not tx:
|
# if not tx:
|
||||||
# self.msg_edit_row(self.msg_error("Error, no tx was built"))
|
# self.msg_edit_row(self.msg_error("Error, no tx was built"))
|
||||||
# return
|
# return
|
||||||
|
|
||||||
|
# Special signal raised by task_phase1 when the freshly rebuilt will is
|
||||||
|
# already expired (e.g. an heir was added to an expired will). Instead of
|
||||||
|
# running the wizard's automatic invalidation loop (which would re-check
|
||||||
|
# before the invalidation tx reaches the mempool and loop forever), we
|
||||||
|
# behave exactly like the "Tools -> invalidate" menu: open Electrum's
|
||||||
|
# classic transaction dialog so the user signs and broadcasts the
|
||||||
|
# invalidation manually, with the "BAL Invalidate transaction" label.
|
||||||
|
# This runs in the GUI thread (on_success callback), so opening windows
|
||||||
|
# is safe. We then stop and close the wizard.
|
||||||
|
if self.have_to_sign == "invalidate_classic":
|
||||||
|
self.thread.stop()
|
||||||
|
# Design decision (window stacking + user clarity):
|
||||||
|
#
|
||||||
|
# When an heir is added to an already-expired will, the rebuilt will
|
||||||
|
# is itself expired and the old will must be invalidated on-chain
|
||||||
|
# before the new one can be used. We previously tried to open the
|
||||||
|
# invalidation transaction window AUTOMATICALLY from here, but doing
|
||||||
|
# so from within the closing wizard proved fragile: depending on the
|
||||||
|
# OS window manager and Qt's event ordering, the transaction window
|
||||||
|
# kept ending up BEHIND the main wallet window (it lost focus when
|
||||||
|
# the wizard closed). Neither closing-before-opening nor a deferred
|
||||||
|
# QTimer close() fixed it reliably on every machine.
|
||||||
|
#
|
||||||
|
# The robust solution is to NOT auto-open any window here. Instead we
|
||||||
|
# close the wizard and show a clear instruction telling the user to
|
||||||
|
# run "Tools -> Invalidate" themselves. That menu path is already
|
||||||
|
# known to work perfectly (its transaction window always stays in
|
||||||
|
# front, because no other window is closing at the same time), and
|
||||||
|
# it also makes the user consciously aware that they are performing a
|
||||||
|
# deliberate, important action (invalidating their old will).
|
||||||
|
#
|
||||||
|
# Close the wizard first so the instruction popup is the only window
|
||||||
|
# left, then show the guidance message.
|
||||||
|
self.close()
|
||||||
|
self.bal_window.show_message(
|
||||||
|
_(
|
||||||
|
"Your will has expired and must be invalidated before it "
|
||||||
|
"can be rebuilt.\n\n"
|
||||||
|
"Please use the top-right menu Tools -> Invalidate to "
|
||||||
|
"invalidate your old will: a transaction window will open "
|
||||||
|
"where you can sign and broadcast the invalidation.\n\n"
|
||||||
|
"After the invalidation is confirmed, press the Check "
|
||||||
|
"button near Tools, to finish the will."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
_logger.debug("have to sign {}".format(self.have_to_sign))
|
_logger.debug("have to sign {}".format(self.have_to_sign))
|
||||||
password = None
|
password = None
|
||||||
if self.have_to_sign is None:
|
if self.have_to_sign is None:
|
||||||
|
|||||||
@@ -470,7 +470,7 @@ class PreviewList(MyTreeView, MessageBoxMixin):
|
|||||||
# The Wizard is the main entry point to create an inheritance, so make
|
# The Wizard is the main entry point to create an inheritance, so make
|
||||||
# it stand out: show a bold label next to a slightly larger icon (the
|
# it stand out: show a bold label next to a slightly larger icon (the
|
||||||
# plain icon-only button was too easy to overlook).
|
# plain icon-only button was too easy to overlook).
|
||||||
wizard = QPushButton(" " + _("Create your will"))
|
wizard = QPushButton(" " + _("Build Your Will"))
|
||||||
wizard.setIcon(
|
wizard.setIcon(
|
||||||
read_QIcon_from_bytes(
|
read_QIcon_from_bytes(
|
||||||
self.bal_window.bal_plugin.read_file("icons/wizard.png")
|
self.bal_window.bal_plugin.read_file("icons/wizard.png")
|
||||||
|
|||||||
@@ -409,6 +409,14 @@ class Plugin(BalPlugin):
|
|||||||
# persisted NUM_REMINDERS config (default 3), with a range of 1..5.
|
# persisted NUM_REMINDERS config (default 3), with a range of 1..5.
|
||||||
heir_num_reminders = BalSpinBox(self.NUM_REMINDERS, minimum=1, maximum=5)
|
heir_num_reminders = BalSpinBox(self.NUM_REMINDERS, minimum=1, maximum=5)
|
||||||
|
|
||||||
|
# "No will-executor TX" checkbox. Bound to the persisted NO_WILLEXECUTOR
|
||||||
|
# config (default ON, see plugin_base.py), the SAME config used by the
|
||||||
|
# checkbox inside the "Build your will" wizard's will-executor download
|
||||||
|
# window, so the two stay in sync automatically. When enabled the plugin
|
||||||
|
# also builds a will that does not require a will-executor (e.g. it can
|
||||||
|
# be saved on a USB stick and a copy given to the heirs).
|
||||||
|
heir_no_willexecutor = BalCheckBox(self.NO_WILLEXECUTOR)
|
||||||
|
|
||||||
# Editable line/text widgets are created once and kept in named
|
# Editable line/text widgets are created once and kept in named
|
||||||
# variables so the "Reset" button (Group C / C4b) can refresh the
|
# variables so the "Reset" button (Group C / C4b) can refresh the
|
||||||
# displayed values after resetting the underlying config.
|
# displayed values after resetting the underlying config.
|
||||||
@@ -519,6 +527,21 @@ class Plugin(BalPlugin):
|
|||||||
)
|
)
|
||||||
#add_widget(grid, "Bal Mode", bal_mode, 4, "choose bal mode")
|
#add_widget(grid, "Bal Mode", bal_mode, 4, "choose bal mode")
|
||||||
|
|
||||||
|
# "No will-executor TX" setting. Mirrors the checkbox shown in the
|
||||||
|
# wizard's will-executor download window (both bound to NO_WILLEXECUTOR),
|
||||||
|
# so it can also be toggled from the plugin settings. Default ON.
|
||||||
|
add_widget(
|
||||||
|
grid,
|
||||||
|
"No will-executor TX",
|
||||||
|
heir_no_willexecutor,
|
||||||
|
8,
|
||||||
|
(
|
||||||
|
"Create a will that does not require a Will-executor; it can be "
|
||||||
|
"saved, for example, on a USB stick, and a copy can be given to "
|
||||||
|
"the heirs."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
# add_widget(
|
# add_widget(
|
||||||
# grid,
|
# grid,
|
||||||
# "Ping Willexecutors",
|
# "Ping Willexecutors",
|
||||||
@@ -533,32 +556,25 @@ class Plugin(BalPlugin):
|
|||||||
# 4,
|
# 4,
|
||||||
# "Ask before to ping willexecutor",
|
# "Ask before to ping willexecutor",
|
||||||
# )
|
# )
|
||||||
# add_widget(
|
|
||||||
# grid,
|
|
||||||
# "Backup Transaction",
|
|
||||||
# heir_no_willexecutor,
|
|
||||||
# 5,
|
|
||||||
# "Add transactions without willexecutor",
|
|
||||||
# )
|
|
||||||
# add_widget(grid,"Enable Multiverse(EXPERIMENTAL/BROKEN)",heir_enable_multiverse,6,"enable multiple locktimes, will import.... ")
|
# add_widget(grid,"Enable Multiverse(EXPERIMENTAL/BROKEN)",heir_enable_multiverse,6,"enable multiple locktimes, will import.... ")
|
||||||
grid.addWidget(heir_repush, 8, 0)
|
grid.addWidget(heir_repush, 9, 0)
|
||||||
grid.addWidget(
|
grid.addWidget(
|
||||||
HelpButton(
|
HelpButton(
|
||||||
"Broadcast all transactions to willexecutors including those already pushed"
|
"Broadcast all transactions to willexecutors including those already pushed"
|
||||||
),
|
),
|
||||||
8,
|
9,
|
||||||
2,
|
2,
|
||||||
)
|
)
|
||||||
|
|
||||||
# ----------------------------------------------------------------- #
|
# ----------------------------------------------------------------- #
|
||||||
# Group C / C4b: "Reset" button that restores the dialog settings to #
|
# Group C / C4b: "Reset" button that restores the dialog settings to #
|
||||||
# their factory defaults. It only resets the settings exposed by THIS #
|
# their factory defaults. It only resets the settings exposed by THIS #
|
||||||
# dialog (the 6 below) and refreshes the corresponding widgets so the #
|
# dialog (the ones below) and refreshes the corresponding widgets so #
|
||||||
# change is visible immediately. It deliberately does NOT touch the #
|
# change is visible immediately. It deliberately does NOT touch the #
|
||||||
# wills, will-executors or any other configuration. #
|
# wills, will-executors or any other configuration. #
|
||||||
# ----------------------------------------------------------------- #
|
# ----------------------------------------------------------------- #
|
||||||
def on_reset_defaults():
|
def on_reset_defaults():
|
||||||
"""Reset the six dialog settings to their defaults and refresh widgets.
|
"""Reset the dialog settings to their defaults and refresh widgets.
|
||||||
|
|
||||||
The default value of each setting is taken from ``BalConfig.default``
|
The default value of each setting is taken from ``BalConfig.default``
|
||||||
(the third argument used when the config was created in
|
(the third argument used when the config was created in
|
||||||
@@ -573,6 +589,7 @@ class Plugin(BalPlugin):
|
|||||||
(self.AUTO_SIGN, heir_auto_sign, "check"),
|
(self.AUTO_SIGN, heir_auto_sign, "check"),
|
||||||
(self.EDITABLE_DATES, heir_editable_dates, "check"),
|
(self.EDITABLE_DATES, heir_editable_dates, "check"),
|
||||||
(self.NUM_REMINDERS, heir_num_reminders, "spin"),
|
(self.NUM_REMINDERS, heir_num_reminders, "spin"),
|
||||||
|
(self.NO_WILLEXECUTOR, heir_no_willexecutor, "check"),
|
||||||
(self.EVENT_SUMMARY, edit_event_summary, "line"),
|
(self.EVENT_SUMMARY, edit_event_summary, "line"),
|
||||||
(self.EVENT_DESCRIPTION, edit_event_description, "text"),
|
(self.EVENT_DESCRIPTION, edit_event_description, "text"),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -608,7 +608,8 @@ class BalWindow:
|
|||||||
try:
|
try:
|
||||||
self.check_will()
|
self.check_will()
|
||||||
for wid, _w in self.willitems.items():
|
for wid, _w in self.willitems.items():
|
||||||
self.wallet.set_label(wid, "BAL Transaction")
|
# Label shown in Electrum's History tab for inheritance txs.
|
||||||
|
self.wallet.set_label(wid, "BAL Inheritance transaction")
|
||||||
rebuilt_ok = True
|
rebuilt_ok = True
|
||||||
except WillExpiredException as e:
|
except WillExpiredException as e:
|
||||||
self.invalidate_will()
|
self.invalidate_will()
|
||||||
@@ -699,7 +700,8 @@ class BalWindow:
|
|||||||
"Please sign and broadcast this transaction to invalidate current will"
|
"Please sign and broadcast this transaction to invalidate current will"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.wallet.set_label(result.txid(), "BAL Invalidate")
|
# Label shown in Electrum's History tab for invalidate txs.
|
||||||
|
self.wallet.set_label(result.txid(), "BAL Invalidate transaction")
|
||||||
self.show_transaction(result)
|
self.show_transaction(result)
|
||||||
else:
|
else:
|
||||||
self.show_message(_("No transactions to invalidate"))
|
self.show_message(_("No transactions to invalidate"))
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "bal",
|
"name": "bal",
|
||||||
"fullname": "Bitcoin After Life",
|
"fullname": "Bitcoin After Life",
|
||||||
"version": "0.3.8",
|
"version": "0.3.9",
|
||||||
"description": "Provides free and decentralized Bitcoin inheritance support. Build time-locked 'will' transactions that transfer funds to your heirs if you stop refreshing them (dead-man's switch), optionally relayed by will-executor servers.",
|
"description": "Provides free and decentralized Bitcoin inheritance support. Build time-locked 'will' transactions that transfer funds to your heirs if you stop refreshing them (dead-man's switch), optionally relayed by will-executor servers.",
|
||||||
"author": "Svatantrya",
|
"author": "Svatantrya",
|
||||||
"licence": "MIT",
|
"licence": "MIT",
|
||||||
|
|||||||
Reference in New Issue
Block a user