From c040d5323c584e9cd9d994d975f5828e78c377b1 Mon Sep 17 00:00:00 2001 From: svatantrya Date: Sat, 12 Sep 2026 12:23:09 -0400 Subject: [PATCH] gui: show heir/willexecutor addresses and decoded OP_RETURN in will detail WillWidget now renders, for every will transaction in the Will Details window: - each heir's receiving address (or the decoded OP_RETURN payload text when the heir is an OP_RETURN recipient) - the will-executor's payout address Test: test_will_widget_shows_addresses_and_decodes_opreturn in tests/test_import_will_details.py. --- bal/gui/qt/widgets.py | 31 +++++++++++++++++----- tests/test_import_will_details.py | 44 +++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/bal/gui/qt/widgets.py b/bal/gui/qt/widgets.py index 2e84ef6..3a181b9 100644 --- a/bal/gui/qt/widgets.py +++ b/bal/gui/qt/widgets.py @@ -20,6 +20,7 @@ Contents: from typing import TYPE_CHECKING +from ...core.heirs import get_op_return_hex, is_op_return_address from ...core.input_rules import ( LockTimeEditor, normalize_locktime_raw_text, @@ -1331,14 +1332,28 @@ class WillWidget(QWidget): ) detaillayout.addWidget(QLabel("")) detaillayout.addWidget(QLabel("Heirs:")) - for heir in self.will[w].heirs: - if 'w!ll3x3c"' not in heir: - decoded_amount = Util.decode_amount( - self.will[w].heirs[heir][3], self._bal_parent.decimal_point - ) + for heir_name in self.will[w].heirs: + if 'w!ll3x3c"' in heir_name: + continue + h = self.will[w].heirs[heir_name] + decoded_amount = Util.decode_amount( + h[3], self._bal_parent.decimal_point + ) + if is_op_return_address(h[0]): + data_hex = get_op_return_hex(h[0]) or "" + try: + decoded = bytes.fromhex(data_hex).decode( + "utf-8", errors="replace" + ) + except Exception: + decoded = h[0] + detaillayout.addWidget(qlabel(heir_name, "OP_RETURN: " + decoded)) + else: detaillayout.addWidget( qlabel( - heir, f"{decoded_amount} {self._bal_parent.base_unit_name}" + heir_name, + f"{decoded_amount} {self._bal_parent.base_unit_name} " + f"[{h[0]}]", ) ) if self.will[w].we: @@ -1354,6 +1369,10 @@ class WillWidget(QWidget): f"{decoded_amount} {self._bal_parent.base_unit_name}", ) ) + if self.will[w].we.get("address"): + detaillayout.addWidget( + qlabel(_("Address"), self.will[w].we["address"]) + ) detaillayout.addStretch() pal = QPalette() pal.setColor( diff --git a/tests/test_import_will_details.py b/tests/test_import_will_details.py index ec48699..c14742d 100644 --- a/tests/test_import_will_details.py +++ b/tests/test_import_will_details.py @@ -171,6 +171,50 @@ def test_will_widget_explicit_will(): assert w2.will is live +# ------------------------------------------------------------------ # +# WillWidget shows heir/willexecutor addresses and decodes OP_RETURN +# ------------------------------------------------------------------ # + +def test_will_widget_shows_addresses_and_decodes_opreturn(): + from PyQt6.QtWidgets import QLabel + + from bal.core.will import WillItem + from bal.gui.qt.widgets import WillWidget + + op_hex = "68656c6c6f" # "hello" in hex + heirs = { + "bob": ["bc1qtestaddr", 1_000_000, 1000, 500_000], + "msg": [f"OP_RETURN:{op_hex}", 0, 1000, 0], + } + wi = WillItem( + _make_willitem_dict( + heirs=heirs, + willexecutor={ + "url": "https://exec.example", + "address": "bc1qexecaddr", + "base_fee": 200_000, + }, + ) + ) + wi._id = "w0" + fake_parent = SimpleNamespace( + decimal_point=8, + base_unit_name="BTC", + bal_window=SimpleNamespace( + willitems={}, + bal_plugin=SimpleNamespace( + _hide_replaced=False, _hide_invalidated=False + ), + show_transaction=lambda *a, **k: None, + ), + ) + w = WillWidget(parent=fake_parent, will={"w0": wi}) + texts = [lbl.text() for lbl in w.findChildren(QLabel)] + assert any("bc1qtestaddr" in t for t in texts), texts + assert any("OP_RETURN: hello" in t for t in texts), texts + assert any("bc1qexecaddr" in t for t in texts), texts + + # ------------------------------------------------------------------ # # WillDetailDialog external-will mode # ------------------------------------------------------------------ #