gui+cli+core: anticipated-delivery warning, task #67 amount checks, CLI tools
GUI - "Building your will" row (owner request):
- when a rebuild anticipates the delivery date by one day, show
"Anticipated - new delivery date: <date>" on the "Building your will" row
instead of a plain "Ok";
- the detection compares the will's minimum locktime BEFORE and AFTER the
rebuild, so it also covers relative recipes ("1y"/"30d") that the previous
stored-vs-built comparison missed;
- the sign explanation stays on its own "Signing your will" row so it no
longer overwrites the anticipation warning.
Task #67 - "Checking variables" stuck on "Wait":
- core: Will.check_amounts only requires a fixed amount to be funded when it
is > 0, and only requires percentages to total 100% when the will actually
has percentage heirs; fixed-only / empty-wallet wills no longer raise;
- gui: the amount warning is written on the "Checking variables" row itself
(COLOR_WARNING) instead of being overwritten by the next row; the redundant
"adjustment of the amounts" sentence was dropped.
CLI - will-executor helpers:
- willexecutors_update accepts promo_code;
- willexecutors_select supports bulk apply with only_valid;
- willexecutors_export supports selected/valid subsets;
- import overwrites existing records with sane defaults;
- raise NoServersForChainError with a clear user-facing message; map
NotCompleteWill / HeirChange / WillexecutorChange in _user_facing.
Tests and docs:
- tests for the anticipation row, the CLI helpers and the amount checks;
- i18n catalogs refreshed; CHANGELOG section 67; agent task memory updated.
This commit is contained in:
@@ -238,24 +238,26 @@ async def willexecutors_update(
|
||||
wallet,
|
||||
"willexecutors_update",
|
||||
url,
|
||||
address,
|
||||
base_fee,
|
||||
info,
|
||||
promo_code,
|
||||
rename_to,
|
||||
address=address,
|
||||
base_fee=base_fee,
|
||||
info=info,
|
||||
promo_code=promo_code,
|
||||
rename_to=rename_to,
|
||||
)
|
||||
|
||||
|
||||
@plugin_command("nw", plugin_name)
|
||||
async def willexecutors_select(
|
||||
self, url, value=True, wallet=None, plugin=None
|
||||
self, url=None, value=True, only_valid=False, wallet=None, plugin=None
|
||||
):
|
||||
"""Select (or deselect) a will-executor.
|
||||
"""Select (or deselect) a will-executor, or bulk-apply a selection.
|
||||
|
||||
arg:str:url:The will-executor URL.
|
||||
arg:str:url:The will-executor URL; omit to act on every executor.
|
||||
arg:bool:value:True to select, False to deselect.
|
||||
arg:bool:only_valid:When selecting/deselecting all, only change the valid executors (the invalid ones are deselected/left alone).
|
||||
"""
|
||||
return _call(plugin, wallet, "willexecutors_select", [url], value)
|
||||
urls = [url] if url is not None else None
|
||||
return _call(plugin, wallet, "willexecutors_select", urls, value, only_valid)
|
||||
|
||||
|
||||
@plugin_command("nw", plugin_name)
|
||||
@@ -298,12 +300,13 @@ async def willexecutors_import(self, path, wallet=None, plugin=None):
|
||||
|
||||
|
||||
@plugin_command("nw", plugin_name)
|
||||
async def willexecutors_export(self, path, wallet=None, plugin=None):
|
||||
async def willexecutors_export(self, path, subset=None, wallet=None, plugin=None):
|
||||
"""Export the will-executors to a JSON file.
|
||||
|
||||
arg:str:path:Destination file path.
|
||||
arg:str:subset:Optional filter: ``selected`` (only selected executors) or ``valid`` (only valid ones); omit to export all.
|
||||
"""
|
||||
return _call(plugin, wallet, "willexecutors_export", path)
|
||||
return _call(plugin, wallet, "willexecutors_export", path, subset)
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
|
||||
@@ -88,6 +88,27 @@ def _user_facing(e):
|
||||
return UserFacingException(_("Will-Executor not present"))
|
||||
if isinstance(e, will_mod.NoWillExecutorNotPresent):
|
||||
return UserFacingException(_("No backup transaction or will-executor selected"))
|
||||
if isinstance(e, will_mod.HeirChangeException):
|
||||
return UserFacingException(_("The heirs changed: a new will must be prepared."))
|
||||
if isinstance(e, will_mod.WillexecutorChangeException):
|
||||
return UserFacingException(
|
||||
_("A will-executor changed: a new will must be prepared.")
|
||||
)
|
||||
if isinstance(e, will_mod.NotCompleteWillException):
|
||||
# ``WillException.__init__`` stores the detail in ``self.msg`` but calls
|
||||
# ``Exception.__init__(self)`` without it, so ``e.args`` is always empty;
|
||||
# the default sentinel message is "WillException".
|
||||
detail = getattr(e, "msg", None)
|
||||
if detail and detail != "WillException":
|
||||
return UserFacingException(
|
||||
_(
|
||||
"The wallet contains funds that the current will does not "
|
||||
"cover yet: a new will must be prepared."
|
||||
)
|
||||
)
|
||||
return UserFacingException(
|
||||
_("The will contains no valid transaction: a new will must be prepared.")
|
||||
)
|
||||
if isinstance(e, will_mod.AmountException):
|
||||
return UserFacingException(
|
||||
_(
|
||||
@@ -121,6 +142,21 @@ def _user_facing(e):
|
||||
"but less than the locktime"
|
||||
)
|
||||
)
|
||||
if isinstance(e, Willexecutors.NoServersForChainError):
|
||||
if e.url:
|
||||
return UserFacingException(
|
||||
_(
|
||||
"Could not reach the configured welist server.\n\n"
|
||||
"Server: {url}\n"
|
||||
"Error: {reason}\n\n"
|
||||
"Please verify the welist server URL in the plugin settings."
|
||||
).format(url=e.url, reason=e.reason or "empty response")
|
||||
)
|
||||
return UserFacingException(
|
||||
_("No active will-executor found for the {chain} network.").format(
|
||||
chain=e.chain
|
||||
)
|
||||
)
|
||||
return e
|
||||
|
||||
|
||||
@@ -352,6 +388,7 @@ class BalController:
|
||||
self.date_to_check = resolve_date_to_check(
|
||||
self.plugin.is_basic_mode(), self.will_settings,
|
||||
built_locktime=_new_locktime,
|
||||
creation_date=Will.get_creation_time(self.willitems),
|
||||
)
|
||||
self.willexecutors = Willexecutors.get_willexecutors(
|
||||
self.plugin, update=False, task=False
|
||||
@@ -472,6 +509,11 @@ class BalController:
|
||||
self.wallet.dust_threshold(),
|
||||
max_fee=self.plugin.MAX_WILLEXECUTOR_FEE.get(),
|
||||
)
|
||||
except will_mod.AmountException as e:
|
||||
# Mirror the GUI (BalWindow.build_inheritance_transaction): an
|
||||
# amount mismatch is only a WARNING here, the flow continues (the
|
||||
# rebuild/normalisation below reconciles the shares).
|
||||
_logger.warning(f"prepare will: check_amounts: {e}")
|
||||
except Exception as e:
|
||||
raise _user_facing(e) from e
|
||||
|
||||
@@ -949,6 +991,8 @@ class BalController:
|
||||
heir.append(locktime)
|
||||
else:
|
||||
heir.append(self.will_settings["locktime"])
|
||||
if not self.plugin.ENABLE_MULTIVERSE.get():
|
||||
heir[3] = self.will_settings["locktime"]
|
||||
if is_op_return_address(address):
|
||||
heir[2] = "0"
|
||||
return Heirs.validate_heir(heir[0], heir[1:])
|
||||
@@ -1034,7 +1078,7 @@ class BalController:
|
||||
return self.willexecutors_show(url)
|
||||
|
||||
def willexecutors_update(self, url, address=None, base_fee=None, info=None,
|
||||
rename_to=None):
|
||||
promo_code=None, rename_to=None):
|
||||
if url not in self.willexecutors:
|
||||
raise UserFacingException(_("Will-Executor not found: {}").format(url))
|
||||
we = self.willexecutors[url]
|
||||
@@ -1045,6 +1089,8 @@ class BalController:
|
||||
we["base_fee"] = int(base_fee)
|
||||
if info is not None:
|
||||
we["info"] = info.strip() or "New Will Executor"
|
||||
if promo_code is not None:
|
||||
we["promo_code"] = promo_code
|
||||
if rename_to and rename_to != url:
|
||||
if rename_to in self.willexecutors:
|
||||
raise UserFacingException(
|
||||
@@ -1065,17 +1111,38 @@ class BalController:
|
||||
Willexecutors.save(self.plugin, self.willexecutors)
|
||||
return {"deleted": deleted}
|
||||
|
||||
def willexecutors_select(self, urls=None, select=True):
|
||||
"""Select/deselect one, many or all will-executors."""
|
||||
selected = {}
|
||||
targets = urls if urls is not None else list(self.willexecutors)
|
||||
def willexecutors_select(self, urls=None, select=True, only_valid=False):
|
||||
"""Select or deselect will-executors.
|
||||
|
||||
Mirrors the GUI's single-toggle and ``set_select_all(select,
|
||||
only_valid)`` bulk actions. ``urls`` is the set of records to act on
|
||||
(all of them when omitted); with ``only_valid`` the selection is
|
||||
restricted by validity: selecting sets the valid ones to True and the
|
||||
invalid ones to False, while deselecting only clears the invalid ones.
|
||||
"""
|
||||
targets = (
|
||||
list(self.willexecutors)
|
||||
if urls is None
|
||||
else [url for url in urls if url in self.willexecutors]
|
||||
)
|
||||
for url in targets:
|
||||
if url not in self.willexecutors:
|
||||
continue
|
||||
self.willexecutors[url]["selected"] = bool(select)
|
||||
selected[url] = bool(select)
|
||||
we = self.willexecutors[url]
|
||||
if only_valid:
|
||||
is_valid = Willexecutors.is_valid(
|
||||
we,
|
||||
max_fee=self.plugin.MAX_WILLEXECUTOR_FEE.get(),
|
||||
dust=self.wallet.dust_threshold(),
|
||||
)
|
||||
if select:
|
||||
we["selected"] = bool(is_valid)
|
||||
elif not is_valid:
|
||||
we["selected"] = False
|
||||
else:
|
||||
we["selected"] = bool(select)
|
||||
Willexecutors.save(self.plugin, self.willexecutors)
|
||||
return selected
|
||||
return {
|
||||
url: bool(self.willexecutors[url].get("selected")) for url in targets
|
||||
}
|
||||
|
||||
def willexecutors_ping(self, urls=None):
|
||||
"""Ping the (selected) will-executor servers and refresh their info.
|
||||
@@ -1125,10 +1192,12 @@ class BalController:
|
||||
|
||||
result = {}
|
||||
last_error = None
|
||||
any_server_reached = False
|
||||
try:
|
||||
resp = Willexecutors.send_request(
|
||||
"get", url, timeout=10, max_retries=1, retry_sleep=1
|
||||
)
|
||||
any_server_reached = True
|
||||
if not isinstance(resp, dict):
|
||||
last_error = "invalid response format"
|
||||
_logger.warning(
|
||||
@@ -1154,12 +1223,17 @@ class BalController:
|
||||
last_error = str(e)
|
||||
_logger.error(f"fetch_will_executors_list: {url} -> {type(e).__name__}: {e}")
|
||||
|
||||
if not result and not basic:
|
||||
raise UserFacingException(
|
||||
_("Could not reach the configured welist server.\nServer: {}\nError: {}").format(
|
||||
url, last_error or "empty response"
|
||||
if not result:
|
||||
if not basic:
|
||||
# Advanced mode: always raise with full details.
|
||||
raise Willexecutors.NoServersForChainError(
|
||||
chainname,
|
||||
url=url,
|
||||
reason=last_error or "empty response",
|
||||
)
|
||||
)
|
||||
if any_server_reached:
|
||||
# Basic mode: the server answered but has no data for this chain.
|
||||
raise Willexecutors.NoServersForChainError(chainname)
|
||||
return result
|
||||
|
||||
def willexecutors_download(self):
|
||||
@@ -1179,18 +1253,41 @@ class BalController:
|
||||
raise UserFacingException(
|
||||
_("Invalid entry {} in will-executors file").format(url)
|
||||
)
|
||||
if url not in self.willexecutors:
|
||||
we = dict(we)
|
||||
we.setdefault("selected", False)
|
||||
we.setdefault("status", "New")
|
||||
we.setdefault("promo_code", None)
|
||||
self.willexecutors[url] = we
|
||||
# Mirror the GUI import (``willexecutors_list.update(data)``):
|
||||
# existing URLs are overwritten with the imported record, missing
|
||||
# fields get sane defaults.
|
||||
we = dict(we)
|
||||
we.setdefault("selected", False)
|
||||
we.setdefault("status", "New")
|
||||
we.setdefault("promo_code", None)
|
||||
self.willexecutors[url] = we
|
||||
Willexecutors.save(self.plugin, self.willexecutors)
|
||||
return {"imported": len(data), "total": len(self.willexecutors)}
|
||||
|
||||
def willexecutors_export(self, path):
|
||||
write_json_file(path, self.willexecutors)
|
||||
return {"exported": len(self.willexecutors), "path": path}
|
||||
def willexecutors_export(self, path, subset=None):
|
||||
"""Export the will-executors to ``path``.
|
||||
|
||||
``subset`` mirrors the GUI export filter: ``"selected"`` writes only
|
||||
the selected records, ``"valid"`` only the valid ones, anything else
|
||||
(or ``None``) writes every record.
|
||||
"""
|
||||
data = self.willexecutors
|
||||
if subset == "selected":
|
||||
data = {
|
||||
url: we for url, we in data.items() if Willexecutors.is_selected(we)
|
||||
}
|
||||
elif subset == "valid":
|
||||
data = {
|
||||
url: we
|
||||
for url, we in data.items()
|
||||
if Willexecutors.is_valid(
|
||||
we,
|
||||
max_fee=self.plugin.MAX_WILLEXECUTOR_FEE.get(),
|
||||
dust=self.wallet.dust_threshold(),
|
||||
)
|
||||
}
|
||||
write_json_file(path, data)
|
||||
return {"exported": len(data), "path": path}
|
||||
|
||||
# ------------------------------------------------------------------ #
|
||||
# Settings
|
||||
@@ -1290,11 +1387,3 @@ class BalController:
|
||||
)
|
||||
return value
|
||||
return str(raw)
|
||||
|
||||
|
||||
def get_decimal_point(plugin):
|
||||
"""Standalone helper returning Electrum's configured BTC decimal point."""
|
||||
try:
|
||||
return plugin.config.BTC_AMOUNTS_DECIMAL_POINT
|
||||
except AttributeError:
|
||||
return 8
|
||||
|
||||
@@ -823,11 +823,19 @@ class Will:
|
||||
for utxo in all_utxos:
|
||||
wallet_balance += utxo.value_sats()
|
||||
|
||||
if fixed_amount >= wallet_balance:
|
||||
if fixed_amount > 0 and fixed_amount >= wallet_balance:
|
||||
# Only a REAL fixed amount needs to be funded: with no fixed heirs
|
||||
# (all percentages) fixed_amount is 0 and ``0 >= 0`` would wrongly
|
||||
# flag an empty/fully-committed wallet as an amount error.
|
||||
raise FixedAmountException(
|
||||
f"Fixed amount({fixed_amount}) >= {wallet_balance}"
|
||||
)
|
||||
if perc_amount != 100:
|
||||
if perc_heirs and perc_amount != 100:
|
||||
# Percentages only have to add up to 100% when the will actually
|
||||
# uses percentage heirs. A will made ONLY of fixed-amount heirs has
|
||||
# no percentages, so perc_amount is 0 - which used to raise here and
|
||||
# left "Checking variables" stuck on "Wait" for every fixed-only
|
||||
# will (the build normalises the fixed shares anyway).
|
||||
raise PercAmountException(f"Perc amount({perc_amount}) =! 100%")
|
||||
|
||||
for url, wex in willexecutors.items():
|
||||
@@ -835,7 +843,7 @@ class Will:
|
||||
if max_fee is not None and int(wex["base_fee"]) > max_fee:
|
||||
raise WillExecutorFeeTooHighException(wex, max_fee)
|
||||
temp_balance = wallet_balance - int(wex["base_fee"])
|
||||
if fixed_amount >= temp_balance:
|
||||
if fixed_amount > 0 and fixed_amount >= temp_balance:
|
||||
raise FixedAmountException(
|
||||
f"Willexecutor{url} excess base fee({wex['base_fee']}), {fixed_amount} >={temp_balance}"
|
||||
)
|
||||
|
||||
@@ -691,11 +691,22 @@ class BalBuildWillDialog(BalDialog):
|
||||
# Manual next-steps hint (Sign / Broadcast) shown to the user after the
|
||||
# dialog finishes; None when nothing is left to do.
|
||||
self._next_steps_hint = None
|
||||
# Set to True by _sync_locktime_to_built_txs when the delivery date was
|
||||
# automatically anticipated during a rebuild. Used to explain to the
|
||||
# user WHY signing is being requested (otherwise the sign prompt appears
|
||||
# without any reason, as the owner reported).
|
||||
# Set to True by _build_success_report when the rebuild moved the
|
||||
# delivery date one day earlier than the previous will. Used both to
|
||||
# show the "Anticipated" warning on the "Building your will" row and to
|
||||
# explain WHY signing is being requested (otherwise the sign prompt
|
||||
# appears without any reason, as the owner reported).
|
||||
self._date_was_anticipated = False
|
||||
# The anticipated locktime (UNIX timestamp) captured by
|
||||
# _build_success_report, formatted into the "Anticipated - new
|
||||
# delivery date: ..." warning. None when the last build did not
|
||||
# anticipate the delivery.
|
||||
self._anticipated_locktime = None
|
||||
# The will's minimum locktime captured BEFORE the rebuild (see
|
||||
# task_phase1). _build_success_report compares it with the rebuilt one
|
||||
# to tell whether the delivery was anticipated by one day. None when no
|
||||
# build ran yet.
|
||||
self._previous_min_locktime = None
|
||||
# Set to True right after we broadcast an automatic invalidation
|
||||
# transaction (the "postpone" path). On the very next phase-1 re-check
|
||||
# Electrum may not have seen the invalidation tx yet, so it would still
|
||||
@@ -789,18 +800,32 @@ class BalBuildWillDialog(BalDialog):
|
||||
_logger.debug("variables ok")
|
||||
self.msg_set_status(_("Checking variables"), varrow, _("Ok"), self.COLOR_OK)
|
||||
except AmountException:
|
||||
self.msg_set_checking(
|
||||
self.msg_warning(
|
||||
_(
|
||||
"In the inheritance process, "
|
||||
"the entire wallet will always be fully emptied. \n"
|
||||
"Your settings require an adjustment of the amounts"
|
||||
)
|
||||
)
|
||||
# The amount check is a WARNING, not a hard failure: the build can
|
||||
# still normalise the shares (see BalWindow.build_inheritance_
|
||||
# transaction, which shows the same warning and continues). Report
|
||||
# it on the "Checking variables" row itself, with the warning colour.
|
||||
# Previously this was routed to msg_set_checking(), i.e. the
|
||||
# "Checking your will" row, and then immediately overwritten by the
|
||||
# msg_set_checking() call below - so the warning was lost AND the
|
||||
# "Checking variables" row stayed stuck on its initial "Wait".
|
||||
self.msg_set_status(
|
||||
_("Checking variables"),
|
||||
varrow,
|
||||
_(
|
||||
"In the inheritance process, "
|
||||
"the entire wallet will always be fully emptied."
|
||||
),
|
||||
self.COLOR_WARNING,
|
||||
)
|
||||
except WillExecutorFeeTooHighException as e:
|
||||
self.msg_set_checking(
|
||||
self.msg_warning(_("Will-executor fee too high: {}").format(e))
|
||||
# Same reasoning as the AmountException branch above: show the
|
||||
# warning on the "Checking variables" row so it is neither lost nor
|
||||
# left stuck on "Wait".
|
||||
self.msg_set_status(
|
||||
_("Checking variables"),
|
||||
varrow,
|
||||
_("Will-executor fee too high: {}").format(e),
|
||||
self.COLOR_WARNING,
|
||||
)
|
||||
|
||||
self.msg_set_checking()
|
||||
@@ -897,6 +922,18 @@ class BalBuildWillDialog(BalDialog):
|
||||
|
||||
if have_to_build:
|
||||
self.msg_set_building()
|
||||
# Capture the delivery date of the CURRENT (previous) will BEFORE
|
||||
# the rebuild overwrites it, so _build_success_report can tell
|
||||
# whether the rebuild ANTICIPATED the delivery by one day. The core
|
||||
# anticipates by moving the rebuilt txs one day EARLIER than the
|
||||
# previous will that spends the same coins (Will.check_anticipate /
|
||||
# Will.search_anticipate), so comparing the two is the only reliable
|
||||
# signal: a relative recipe ("1y"/"30d") is anchored to the built tx,
|
||||
# which is why comparing the built locktime with the STORED value
|
||||
# (see _sync_locktime_to_built_txs) misses the anticipation.
|
||||
self._previous_min_locktime = Will.get_min_locktime(
|
||||
self.bal_window.willitems
|
||||
)
|
||||
try:
|
||||
txs = self.bal_window.build_will()
|
||||
if not txs:
|
||||
@@ -1085,7 +1122,40 @@ class BalBuildWillDialog(BalDialog):
|
||||
# auto-anticipated) transactions, otherwise the next Check would wrongly
|
||||
# ask to invalidate. See _sync_locktime_to_built_txs for the full why.
|
||||
self._sync_locktime_to_built_txs()
|
||||
self.msg_set_building(self.msg_ok())
|
||||
# Detect an automatic anticipation by comparing the will's delivery date
|
||||
# BEFORE the rebuild (captured in task_phase1) with the one AFTER it:
|
||||
# the core anticipates by moving the rebuilt txs one day earlier than
|
||||
# the previous will that spends the same coins (Will.check_anticipate).
|
||||
# This is format-agnostic: it works whether the stored recipe is an
|
||||
# absolute timestamp or a relative "1y"/"30d" recipe (anchoring makes a
|
||||
# relative recipe unusable for a stored-vs-built comparison).
|
||||
new_min_locktime = Will.get_min_locktime(self.bal_window.willitems)
|
||||
previous_min_locktime = self._previous_min_locktime
|
||||
self._date_was_anticipated = (
|
||||
previous_min_locktime is not None
|
||||
and new_min_locktime is not None
|
||||
and int(new_min_locktime) < int(previous_min_locktime)
|
||||
)
|
||||
self._anticipated_locktime = (
|
||||
int(new_min_locktime) if self._date_was_anticipated else None
|
||||
)
|
||||
# Owner request: when the rebuild anticipated the delivery, do NOT show
|
||||
# a plain "Ok" on the "Building your will" row - show a warning that
|
||||
# names the anticipation and the NEW delivery date, so the user is told
|
||||
# the inheritance will be delivered one day earlier. The sign step then
|
||||
# explains WHY signing is requested on its OWN row ("Signing your
|
||||
# will"), leaving this warning visible.
|
||||
if self._anticipated_locktime is not None:
|
||||
new_date = BalTimestamp._safe_fromtimestamp(
|
||||
self._anticipated_locktime
|
||||
).strftime("%Y-%m-%d")
|
||||
self.msg_set_building(
|
||||
self.msg_alert(
|
||||
_("Anticipated - new delivery date: {}").format(new_date)
|
||||
)
|
||||
)
|
||||
else:
|
||||
self.msg_set_building(self.msg_ok())
|
||||
# List EACH heir on its OWN line, green + bold (owner request: revert the
|
||||
# one-line "Heirs: a, b, c" form of v0.4.6). Heir names can be long, and
|
||||
# now that the report area scrolls (allegato1) there is no need to cram
|
||||
@@ -1177,10 +1247,10 @@ class BalBuildWillDialog(BalDialog):
|
||||
f"sync delivery date to built tx locktime: "
|
||||
f"{current} -> {min_locktime}"
|
||||
)
|
||||
# Remember that we anticipated the date, so the later sign
|
||||
# prompt can explain WHY signing is needed
|
||||
# (see on_success_phase1).
|
||||
self._date_was_anticipated = True
|
||||
# NOTE: this only SYNCS the stored date. Whether the rebuild
|
||||
# ANTICIPATED the delivery is decided in _build_success_report
|
||||
# by comparing the previous and the rebuilt locktimes (the only
|
||||
# format-agnostic signal, see there).
|
||||
# update_setting_widgets stores the value, persists it and
|
||||
# refreshes the date widgets in all panels/wizard (the .ics
|
||||
# calendar too).
|
||||
@@ -1624,19 +1694,18 @@ class BalBuildWillDialog(BalDialog):
|
||||
# If the will was rebuilt with an automatically anticipated
|
||||
# delivery date, explain WHY we are now asking to sign:
|
||||
# otherwise the sign prompt appears with no reason (owner
|
||||
# feedback). The note is shown on the "Building your will"
|
||||
# row (orange warning) before the modal password prompt
|
||||
# opens, so the user can read it.
|
||||
# feedback). This note goes on its OWN "Signing your will" row
|
||||
# so it does NOT overwrite the "Anticipated - new delivery
|
||||
# date" warning already shown on the "Building your will" row,
|
||||
# and it is readable before the modal password prompt opens.
|
||||
if self._date_was_anticipated:
|
||||
self.msg_set_building(
|
||||
"<b>{}</b>".format(
|
||||
_(
|
||||
"The delivery date was automatically moved "
|
||||
"one day earlier so the updated will can "
|
||||
"correctly replace the previous one.\n"
|
||||
"Please sign (and broadcast) to confirm "
|
||||
"the change."
|
||||
)
|
||||
self.msg_set_signing(
|
||||
_(
|
||||
"The delivery date was automatically moved "
|
||||
"one day earlier so the updated will can "
|
||||
"correctly replace the previous one.\n"
|
||||
"Please sign (and broadcast) to confirm "
|
||||
"the change."
|
||||
)
|
||||
)
|
||||
password = self.bal_window.get_wallet_password(
|
||||
|
||||
@@ -835,11 +835,11 @@ class BalWindow:
|
||||
self.window.wallet.dust_threshold(),
|
||||
max_fee=self.bal_plugin.MAX_WILLEXECUTOR_FEE.get(),
|
||||
)
|
||||
except AmountException as e:
|
||||
except AmountException:
|
||||
self.show_warning(
|
||||
_(
|
||||
"In the inheritance process, the entire wallet will always be fully emptied. Your settings require an adjustment of the amounts.{}"
|
||||
).format(e)
|
||||
"In the inheritance process, the entire wallet will always be fully emptied."
|
||||
)
|
||||
)
|
||||
except WillExecutorFeeTooHighException as e:
|
||||
self.show_error(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user