willexecutors: fee-bound is_valid (extremes allowed), is_selected flag-only; fix merge_will crash on missing date_to_check; DNSSEC async, ical folding, pyright/ruff cleanup; refresh karen7/samanta7 fixtures

This commit is contained in:
2026-08-01 22:08:53 -04:00
parent 06d61d78d0
commit 693479b0da
24 changed files with 272 additions and 204 deletions

View File

@@ -3187,7 +3187,9 @@
"lightning_preimages": {},
"lightning_xprv": "vprv9HMaVA1cGK7XCUCiTrrdD9kGgiSeiwpqDDYfAafTZoSXyZtmQYnQ4CUvsZggS4fWrF3kve47MFWjrWLJ6t4uXjzs2XagtmBeUqoaRRFpJGF",
"notes_text": "",
"num_parents": {},
"num_parents": {
"2c659529455fdacab80781dab351553428e85f2a491866b0a8274dbedaff4f4c": 4
},
"onchain_channel_backups": {},
"payment_requests": {
"6e7ca1969b": {
@@ -3260,7 +3262,6 @@
"a001edc1d43b5b41adc5a4c5ce9b6edd9dcad9fa3e50cca287d256a23cca9d4e:0": 50000,
"a1aee934c5dda700d15934667507f90db1ce36d7dd3068165b54159df320cd02:0": 50000,
"aa407bf21c31fa3ebe8bf074767bfec17df01644da94b3b709c3d3551f3210ca:0": 50000,
"adb13f7887359732c227e0d0523090de7d6cef7e7c73fb3b0a8b67844efbcd91:0": 1000,
"b28b20fb9089f2d021d812dc34ce461fdcd800137434edaa09160a395c182c8c:0": 50000,
"b6e993fb2b0584bb35b8eefcfbe6ba7c9b9b7875e69389063c96f78dd1fca9e1:0": 50000,
"bdaa76d37810e4d4ad1d2e7ac6e198ad96c48683e552e874901a7af3d8ae4e50:0": 50000,
@@ -3718,9 +3719,6 @@
"5fb4dbd05379842b11a048ee73467fff68ef04500bf59e0e1a0388474b0e259a": {
"af9e9fbb8e65d724bbf483ed4b7577ff183b0e8ddba91ca40456d43b3135f81e:0": 1250000000
},
"61d6068a9000df4a2d0c919d0845ceb7b9f690e609fc27238e38facecbe38d31": {
"adb13f7887359732c227e0d0523090de7d6cef7e7c73fb3b0a8b67844efbcd91:2": 316818514
},
"6232f0790f4bc993b8bd042828a1f626b0ae3ac20b1dcf5a479be57c1035de29": {
"316b0ac8e6516b59633a46dd5f4fa19da180f799f871a57085f6a7e99bb561e7:0": 1250000000
},
@@ -3811,11 +3809,6 @@
"8cebd66ae223c28c1db0fbd9638668ae9a28c757b164c97e93a22c9b2ef9fb8c:0": 610351,
"b3e3d7cba32180e7a72a2e66126d6b2bee9e386788ee099c5f032efaa8772fe3:0": 751351
},
"7d1852bfc82939c14ac37a01ad558273fcdc304c50eb3dc87272643bb2ce36b6": {
"adb13f7887359732c227e0d0523090de7d6cef7e7c73fb3b0a8b67844efbcd91:1": 40001,
"adb13f7887359732c227e0d0523090de7d6cef7e7c73fb3b0a8b67844efbcd91:3": 336619671,
"adb13f7887359732c227e0d0523090de7d6cef7e7c73fb3b0a8b67844efbcd91:4": 346520250
},
"8017a32067302648ad152b7a87fdb1c2c4f19c174a5240e88666ba987063163c": {
"1d30124dd0acb5c11a2cb8e607c50b5f402a7be178cafb264747fb0dab37c8cd:0": 1250000000
},
@@ -4387,9 +4380,6 @@
"2af047c4a003fb7b90ce2c8fc49bcdb3eaee0fff213b14dc1645b9fb18b8f0f6": {
"0": "d2d953e950d28c021a5ddf6f77cfb9551af2fd33ccc7473b20a31d208e7bd308"
},
"2c659529455fdacab80781dab351553428e85f2a491866b0a8274dbedaff4f4c": {
"0": "adb13f7887359732c227e0d0523090de7d6cef7e7c73fb3b0a8b67844efbcd91"
},
"2c6d3a41eb0f5589e2586138b2bee1cf453144fe48dc73c2a3b0f4d0a3bfd596": {
"0": "5c6d7a19cfb35a98949a25c5fede1dd798a7e1509e0067d000319126c34f8c15"
},
@@ -5179,7 +5169,7 @@
"2": "8cebb4ea3a63829a2787c3a473f14b4f73ced07552f73ff8c2b1152169042550"
}
},
"stored_height": 2336,
"stored_height": 2381,
"submarine_swaps": {},
"transactions": {
"00fda0d8fdc53b1f95410bafca884c5dff8ac1e5c168ace5f09a32d872b7413a": "020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0402460100ffffffff02807c814a00000000160014b51c529851d6140f1a37f2aa46bafe171a549f210000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
@@ -5360,7 +5350,6 @@
"ab1012eb232c0070b566b6620a8b839e8fa78831cf8216337c1db71e35b89953": "020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0402d70100ffffffff0240be402500000000160014ddc0da8880db383448d588868cd34ab79779dd7c0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
"ab74079fca87f186df5676c62de63d8b21e98746c8c8888f108310bc7849e70e": "020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04021e0100ffffffff0200f9029500000000160014178787a67beeadb99e36f6c5513fe8e2b02e800b0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
"ad3f3d67b74bb4b9b4457f1ccb99ea3dad02ad24c0f4d2383ff1fd12f7c0a684": "020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0402f20200ffffffff02902f500900000000160014ea779f0f8e203034ae25cd71e52c1a81ac488e2b0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
"adb13f7887359732c227e0d0523090de7d6cef7e7c73fb3b0a8b67844efbcd91": "cHNidP8BAM4CAAAAAUxP/9q+TSeosGYYSSpf6Cg0VVGz2oEHuMraX0UplWUsAAAAAAD9////BegDAAAAAAAAFgAUHJ2Hucc2GI5sonbAeh3TaBHHeApBnAAAAAAAABYAFI4fw5lhxUeH/de1zz5ZwJW5c0+8UkTiEgAAAAAWABR+Ga8pbyXQkvI6DCCII+ZcgaKvnZdoEBQAAAAAFgAUjh/DmWHFR4f917XPPlnAlblzT7y6eqcUAAAAABYAFI4fw5lhxUeH/de1zz5ZwJW5c0+8wKJObAABAR+2yJo7AAAAABYAFH77QT1b74D8A9KpXC1rH06KZ0UgAQC/AgAAAAABAd8W8LQ4gBPr4BMdIIFgxnlK/0pm2Hv7VRK0tdMKsspOAAAAAAD9////AbbImjsAAAAAFgAUfvtBPVvvgPwD0qlcLWsfTopnRSACRzBEAiBiDWmocrmu+1Hip22YEAiBWHdkSIwuaYOqolHI5yjlJwIgaVVzZF7VDoudB+M8a9n375i5hXF+w+RnR2RYs+oKnUgBIQMAYJEwf6yH90elPJ15yFBJZBFMuZDDwEIcyvu85pUc5uYIAAAiBgMlkmiTZPOkeW/DWh8YN5HrfF2yXm82+g8ekmVO1nnHkRBZSzQGAAAAgAEAAAARAAAAAAAAAAAA",
"ae8e62c0ec616466782a4f861d108ad06e593af6c8a4fe3d2c9ca1386fd559bd": "020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0402200100ffffffff0200f9029500000000160014d2b8a4b410689315e81b354969e36584451f85530000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
"af9e9fbb8e65d724bbf483ed4b7577ff183b0e8ddba91ca40456d43b3135f81e": "020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff04023a0100ffffffff02807c814a00000000160014b2da19ab366b4a2f09d6dd233192d9339444ca980000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000",
"b00e9f65ca32f0ab7a05666f21a78b461623c43d1297a731f09a807f2c9dc497": "020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0402850300ffffffff02aa19a8040000000016001439690f010cb6ee0ab0180e01d1a9f6b3417af06b0000000000000000266a24aa21a9edb6b7b0b5bded40786dbf759cf9af7726000596503854971f2cc19c3fed02f4a10120000000000000000000000000000000000000000000000000000000000000000000000000",
@@ -6352,11 +6341,6 @@
false,
1
],
"adb13f7887359732c227e0d0523090de7d6cef7e7c73fb3b0a8b67844efbcd91": [
234,
true,
1
],
"ae8e62c0ec616466782a4f861d108ad06e593af6c8a4fe3d2c9ca1386fd559bd": [
null,
false,
@@ -7395,11 +7379,6 @@
"88a56990a69eb1a7c11595b7a88097d799fb6070bb2f77ea34e7f2fe8d54d867:1": 100000
}
},
"adb13f7887359732c227e0d0523090de7d6cef7e7c73fb3b0a8b67844efbcd91": {
"bcrt1q0ma5z02ma7q0cq7j49wz66clf69xw3fq2zl05n": {
"2c659529455fdacab80781dab351553428e85f2a491866b0a8274dbedaff4f4c:0": 999999670
}
},
"b020ccbf483abab08d6553b7fec974ce9f8ab43654863757e3ec7694c399f86c": {
"bcrt1qazle627r46apscly8lj4q5cxfxgrtuew879jde": {
"335d73d9f9295b283a07187652a587830eb1eb2ee2829ef566dde8445946e474:1": 68897247707
@@ -13151,21 +13130,21 @@
"BROADCASTED": false,
"CHECKED": false,
"CHECK_FAIL": false,
"COMPLETE": false,
"COMPLETE": true,
"CONFIRMED": false,
"ERROR": false,
"EXPIRED": false,
"EXPORTED": false,
"IMPORTED": false,
"INVALIDATED": true,
"INVALIDATED": false,
"MEMPOOL": false,
"PARTIALLY_SIGNED": false,
"PUSHED": false,
"PUSHED": true,
"PUSH_FAIL": false,
"REPLACED": false,
"RESTORED": false,
"UPDATED": false,
"VALID": false,
"VALID": true,
"_id": "adb13f7887359732c227e0d0523090de7d6cef7e7c73fb3b0a8b67844efbcd91",
"baltx_fees": 1,
"change": null,
@@ -13205,25 +13184,30 @@
},
"sigs_have": 0,
"sigs_required": 1,
"status": "New.Invalidated",
"time": 1785562346.7776835,
"tx": "cHNidP8BAM4CAAAAAUxP/9q+TSeosGYYSSpf6Cg0VVGz2oEHuMraX0UplWUsAAAAAAD9////BegDAAAAAAAAFgAUHJ2Hucc2GI5sonbAeh3TaBHHeApBnAAAAAAAABYAFI4fw5lhxUeH/de1zz5ZwJW5c0+8UkTiEgAAAAAWABR+Ga8pbyXQkvI6DCCII+ZcgaKvnZdoEBQAAAAAFgAUjh/DmWHFR4f917XPPlnAlblzT7y6eqcUAAAAABYAFI4fw5lhxUeH/de1zz5ZwJW5c0+8wKJObAABAR+2yJo7AAAAABYAFH77QT1b74D8A9KpXC1rH06KZ0UgAQC/AgAAAAABAd8W8LQ4gBPr4BMdIIFgxnlK/0pm2Hv7VRK0tdMKsspOAAAAAAD9////AbbImjsAAAAAFgAUfvtBPVvvgPwD0qlcLWsfTopnRSACRzBEAiBiDWmocrmu+1Hip22YEAiBWHdkSIwuaYOqolHI5yjlJwIgaVVzZF7VDoudB+M8a9n375i5hXF+w+RnR2RYs+oKnUgBIQMAYJEwf6yH90elPJ15yFBJZBFMuZDDwEIcyvu85pUc5uYIAAAiBgMlkmiTZPOkeW/DWh8YN5HrfF2yXm82+g8ekmVO1nnHkRBZSzQGAAAAgAEAAAARAAAAAAAAAAAA",
"status": "New.Firmato.Pushed",
"time": 1785620332.2813325,
"tx": "020000000001014c4fffdabe4d27a8b06618492a5fe828345551b3da8107b8cada5f452995652c0000000000fdffffff05e8030000000000001600141c9d87b9c736188e6ca276c07a1dd36811c7780a419c0000000000001600148e1fc39961c54787fdd7b5cf3e59c095b9734fbc5244e212000000001600147e19af296f25d092f23a0c208823e65c81a2af9d97681014000000001600148e1fc39961c54787fdd7b5cf3e59c095b9734fbcba7aa714000000001600148e1fc39961c54787fdd7b5cf3e59c095b9734fbc0247304402205b777b06e8392136b30177d8a353bde7238a5aa5235eaf973a298c0eb974b4750220783b0b1c7093c93a2aee94829c6e0f6288cecd9e8eba94c61b9c54c2c84f4d2c0121032592689364f3a4796fc35a1f183791eb7c5db25e6f36fa0f1e92654ed679c791c0a24e6c",
"willexecutor": {
"address": "bcrt1qrjwc0ww8xcvgum9zwmq858wndqguw7q27ek3sk",
"balance": 90000,
"base_fee": 1000,
"broadcast_status": "Riuscito",
"chain": "regtest",
"count_win": 0,
"id": 66,
"info": "BAL devel willexecutor server",
"last_block": 0,
"last_update": 1785557736.334134,
"last_update": 1785592563.693952,
"onion_url": null,
"points": 0,
"promo_code": null,
"selected": true,
"status": 200,
"tld": "localhost",
"txs": "020000000001014c4fffdabe4d27a8b06618492a5fe828345551b3da8107b8cada5f452995652c0000000000fdffffff05e8030000000000001600141c9d87b9c736188e6ca276c07a1dd36811c7780a419c0000000000001600148e1fc39961c54787fdd7b5cf3e59c095b9734fbc5244e212000000001600147e19af296f25d092f23a0c208823e65c81a2af9d97681014000000001600148e1fc39961c54787fdd7b5cf3e59c095b9734fbcba7aa714000000001600148e1fc39961c54787fdd7b5cf3e59c095b9734fbc0247304402205b777b06e8392136b30177d8a353bde7238a5aa5235eaf973a298c0eb974b4750220783b0b1c7093c93a2aee94829c6e0f6288cecd9e8eba94c61b9c54c2c84f4d2c0121032592689364f3a4796fc35a1f183791eb7c5db25e6f36fa0f1e92654ed679c791c0a24e6c\n",
"txsids": [
"adb13f7887359732c227e0d0523090de7d6cef7e7c73fb3b0a8b67844efbcd91"
],
"unconfirmed_balance": 0,
"url": "http://localhost:9133",
"version": "0.3.2"

File diff suppressed because one or more lines are too long

View File

@@ -33,7 +33,7 @@ import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.pardir))
import pytest # noqa: E402
import pytest # noqa: E402 # pyright: ignore[reportMissingImports]
from bal.core.will import ( # noqa: E402
NotCompleteWillException,

View File

@@ -140,6 +140,7 @@ def test_prepare_lists_mixed_dust_continues():
"dust": ["bcrt1q08z5t4x74u2883sx2qwsmzk2hj8e5n7z83e4vy", "1%", "30d"],
})
raised = False
result = None
try:
result, _onlyfixed = h.prepare_lists(5200, 100, wallet)
except HeirAmountIsDustException:
@@ -166,6 +167,7 @@ def test_prepare_lists_multi_locktime_continues():
"late_valid": ["bcrt1q08z5t4x74u2883sx2qwsmzk2hj8e5n7z83e4vy", 5000, "60d"],
})
raised = False
result = None
try:
result, _onlyfixed = h.prepare_lists(5200, 100, wallet)
except HeirAmountIsDustException:

View File

@@ -14,7 +14,7 @@ import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.pardir))
import pytest
import pytest # pyright: ignore[reportMissingImports]
from bal.core.util import Util

View File

@@ -26,7 +26,7 @@ import json
import os
import sys
import pytest
import pytest # pyright: ignore[reportMissingImports]
# ------------------------------------------------------------------ #
# Electrum regtest mode (replaces mocking bitcoin.is_address)

View File

@@ -30,7 +30,7 @@ import time
import traceback
from unittest.mock import MagicMock, patch
import pytest
import pytest # pyright: ignore[reportMissingImports]
# Make the plugin package importable when run directly (tests/ is one level
# below the repo root that contains the ``bal`` package).
@@ -274,7 +274,7 @@ def test_e2_karen7_add_remove_heir():
heirs["charlie"] = ["addr_charlie", "20000", "30d"]
assert "charlie" in heirs
assert "charlie" in wallet.db.get("heirs", {})
assert "charlie" in (wallet.db.get("heirs") or {})
removed = heirs.pop("alice")
assert removed is not None
@@ -622,6 +622,7 @@ def test_e5_build_with_real_wallet_heirs_and_utxos():
"bal.core.heirs.PartialTransaction.from_io",
side_effect=_fake_from_io,
):
result = None
try:
result = h.buildTransactions(
bal_plugin, wallet, tx_fees=1, utxos=utxos

View File

@@ -113,5 +113,5 @@ def test_same_heirs_empty():
if __name__ == "__main__":
import pytest
import pytest # pyright: ignore[reportMissingImports]
raise SystemExit(pytest.main([__file__, "-v"]))

View File

@@ -444,6 +444,46 @@ def test_merge_will_new_ids_added_wholesale():
assert new_id in fake.will
def test_merge_will_missing_date_to_check_defaults_to_now():
# Regression: merge_will read self.date_to_check (which is only set by
# init_class_variables) and crashed with AttributeError when merging a
# will file was the first action of a session.
wid = "missing_dtc"
imported_tx = _make_partial_tx(locktime=1000, signed=True)
imported = {wid: _make_willitem_with_tx(imported_tx, key=wid)}
fake, calls = _make_merge_fake({})
del fake.date_to_check
window_mod.BalWindow.merge_will(fake, imported)
assert isinstance(fake.date_to_check, (int, float)), \
"date_to_check must fall back to a timestamp"
assert wid in fake.will
assert "update_all" in calls
def test_merge_will_validity_error_logs_without_crashing():
# Regression: the except handler passed log_error(e, self.bal_window);
# BalWindow has no such attribute, so a validity failure raised a second
# AttributeError that masked the original error.
from unittest.mock import patch
wid = "validity_err"
imported_tx = _make_partial_tx(locktime=1000, signed=True)
imported = {wid: _make_willitem_with_tx(imported_tx, key=wid)}
fake, calls = _make_merge_fake({})
fake.show_error = lambda msg: calls.append(("show_error", msg))
with patch.object(
window_mod.Util, "get_available_utxos", side_effect=RuntimeError("boom")
):
window_mod.BalWindow.merge_will(fake, imported)
assert any(c[0] == "show_error" for c in calls), \
"the validity error must be surfaced via show_error"
assert "update_all" in calls, "merge must complete after the error"
def test_merge_will_from_file_invalid_file_raises():
from bal.gui.qt.common import FileImportFailed

View File

@@ -35,11 +35,13 @@ import sys
import time
from unittest.mock import patch
import pytest
import pytest # pyright: ignore[reportMissingImports]
from electrum import constants
constants.net = constants.BitcoinRegtest
_VALID_REG_ADDR = "bcrt1q0567jspgutk84axs4l7sm04u86yjkzg27dv6fk"
sys.path.insert(0, os.path.join(os.path.dirname(__file__), os.pardir))
from electrum import bitcoin
@@ -250,7 +252,11 @@ class FakeBalWindow:
f = False
for _u, w in self.willexecutors.items():
if Willexecutors.is_selected(
w, max_fee=self.bal_plugin.MAX_WILLEXECUTOR_FEE.get()
w
) and Willexecutors.is_valid(
w,
max_fee=self.bal_plugin.MAX_WILLEXECUTOR_FEE.get(),
dust=self.wallet.dust_threshold(),
):
f = True
if not f:
@@ -508,47 +514,70 @@ class TestNoWillexecutorKaren7:
"selected": True,
"base_fee": base_fee,
"url": "https://we.example.com",
"address": self.wallet._CHANGE_ADDR,
"sort": 0,
}
}
self.bal_plugin._willexecutors.set({"regtest": we_data})
# ------------------------------------------------------------------ #
# E. is_selected with max_fee
# E. is_selected / is_valid semantics
# ------------------------------------------------------------------ #
def test_is_selected_fee_below_max_is_selected(self):
"""is_selected returns True when base_fee < max_fee."""
we = {"selected": True, "base_fee": 1000}
assert Willexecutors.is_selected(we, max_fee=500000) is True
def test_is_selected_fee_equal_max_is_not_selected(self):
"""is_selected returns False when base_fee == max_fee."""
we = {"selected": True, "base_fee": 500000}
assert Willexecutors.is_selected(we, max_fee=500000) is False
def test_is_selected_fee_above_max_is_not_selected(self):
"""is_selected returns False when base_fee > max_fee."""
def test_is_selected_only_checks_selected_flag(self):
"""is_selected ignores the fee entirely; it only reflects the
selected flag. Fee-range enforcement lives in is_valid."""
we = {"selected": True, "base_fee": 600000}
assert Willexecutors.is_selected(we, max_fee=500000) is False
def test_is_selected_without_max_fee_ignores_fee(self):
"""is_selected without max_fee only checks the selected flag."""
we = {"selected": True, "base_fee": 500000}
assert Willexecutors.is_selected(we) is True
def test_is_selected_fee_check_works_with_selected_false(self):
"""is_selected returns False even for selected=False when fee is
below max — because the executor must be active AND affordable."""
we = {"selected": False, "base_fee": 1000}
assert Willexecutors.is_selected(we, max_fee=500000) is False
assert Willexecutors.is_selected(we) is False
def test_is_selected_fee_too_high_still_raises(self):
"""A selected will-executor with base_fee >= MAX_WILLEXECUTOR_FEE
is treated as NOT selected, so build_will still raises."""
def test_is_selected_setter_sets_flag(self):
"""is_selected(value) acts as a setter for the selected flag."""
we = {"selected": False}
assert Willexecutors.is_selected(we, True) is True
assert we["selected"] is True
def test_is_selected_missing_flag_defaults_to_false(self):
"""A dict without the 'selected' key is treated as not selected."""
assert Willexecutors.is_selected({}) is False
def test_is_valid_fee_equal_max_is_valid(self):
"""is_valid allows the boundary value base_fee == max_fee."""
we = {"selected": True, "base_fee": 500000,
"address": _VALID_REG_ADDR}
assert Willexecutors.is_valid(we, max_fee=500000, dust=546) is True
def test_is_valid_fee_above_max_is_invalid(self):
"""is_valid rejects base_fee > max_fee."""
we = {"selected": True, "base_fee": 600000,
"address": _VALID_REG_ADDR}
assert Willexecutors.is_valid(we, max_fee=500000, dust=546) is False
def test_is_valid_fee_equal_dust_is_valid(self):
"""is_valid allows the boundary value base_fee == dust."""
we = {"selected": True, "base_fee": 546,
"address": _VALID_REG_ADDR}
assert Willexecutors.is_valid(we, max_fee=500000, dust=546) is True
def test_is_valid_fee_below_dust_is_invalid(self):
"""is_valid rejects base_fee < dust."""
we = {"selected": True, "base_fee": 545,
"address": _VALID_REG_ADDR}
assert Willexecutors.is_valid(we, max_fee=500000, dust=546) is False
def test_is_valid_requires_valid_address(self):
"""is_valid rejects executors whose address is missing or invalid."""
we = {"selected": True, "base_fee": 1000}
assert Willexecutors.is_valid(we, max_fee=500000, dust=546) is False
def test_build_will_fee_above_max_still_raises(self):
"""A selected will-executor whose fee is outside the valid range
(base_fee > MAX_WILLEXECUTOR_FEE) is not considered valid, so
build_will still raises NoWillExecutorNotPresent."""
self.bal_window.init_class_variables()
# Add a selected executor with fee >= max (500000)
# Add a selected executor with fee > max (500000)
self._add_selected_willexecutor(base_fee=600000)
with pytest.raises(NoWillExecutorNotPresent):