From 8f9951ebedf4120f4c31d111630c003994d8ea5a Mon Sep 17 00:00:00 2001 From: f321x Date: Sun, 20 Jul 2025 12:46:11 +0200 Subject: [PATCH 1/2] fix: cli: check_hold_invoice showing settled invoice as unpaid the cli command `check_hold_invoice` incorrectly assumes that `lnworker.is_accepted_mpp(payment_hash)` is true for settled invoices, however it is not as the received mpp entries will be removed from the `lnworker.received_mpp_htlcs` shortly after adding the preimage to lnworker (after the htlcs got removed from the channel). Also renames `amount_sat` in the `check_hold_invoice` response to `amount_sat_received` to make it more obvious that this is the currently received amount instead of the amount the invoice of `payment_hash` has been created with. --- electrum/commands.py | 15 ++++++++++----- tests/test_commands.py | 10 +++++++++- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/electrum/commands.py b/electrum/commands.py index ff925d68d..eb3641474 100644 --- a/electrum/commands.py +++ b/electrum/commands.py @@ -1427,6 +1427,8 @@ class Commands(Logger): assert payment_hash in wallet.lnworker.dont_settle_htlcs, f"Invoice {payment_hash=} not a hold invoice?" assert wallet.lnworker.is_accepted_mpp(bfh(payment_hash)), \ f"MPP incomplete, cannot settle hold invoice {payment_hash} yet" + info: Optional['PaymentInfo'] = wallet.lnworker.get_payment_info(bfh(payment_hash)) + assert (wallet.lnworker.get_payment_mpp_amount_msat(bfh(payment_hash)) or 0) >= (info.amount_msat or 0) del wallet.lnworker.dont_settle_htlcs[payment_hash] wallet.lnworker.save_preimage(bfh(payment_hash), bfh(preimage)) util.trigger_callback('wallet_updated', wallet) @@ -1474,17 +1476,20 @@ class Commands(Logger): status = "unknown" if info is None: pass - elif not is_accepted_mpp: + elif not is_accepted_mpp and not wallet.lnworker.get_preimage_hex(payment_hash): + # is_accepted_mpp is False for settled payments status = "unpaid" elif is_accepted_mpp and payment_hash in wallet.lnworker.dont_settle_htlcs: status = "paid" - elif (payment_hash in wallet.lnworker._preimages - and payment_hash not in wallet.lnworker.dont_settle_htlcs - and is_accepted_mpp): + elif wallet.lnworker.get_preimage_hex(payment_hash) is not None \ + and payment_hash not in wallet.lnworker.dont_settle_htlcs: status = "settled" + plist = wallet.lnworker.get_payments(status='settled')[bfh(payment_hash)] + _dir, amount_msat, _fee, _ts = wallet.lnworker.get_payment_value(info, plist) + amount_sat = amount_msat // 1000 result = { "status": status, - "amount_sat": amount_sat + "amount_sat_received": amount_sat } return result diff --git a/tests/test_commands.py b/tests/test_commands.py index c142bb57d..412b0214d 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -495,7 +495,7 @@ class TestCommandsTestnet(ElectrumTestCase): mock.patch.object(wallet.lnworker, 'get_payment_mpp_amount_msat', return_value=10_000 * 1000): status: dict = await cmds.check_hold_invoice(payment_hash=payment_hash, wallet=wallet) assert status['status'] == 'paid' - assert status['amount_sat'] == 10000 + assert status['amount_sat_received'] == 10000 settle_result = await cmds.settle_hold_invoice( preimage=preimage.hex(), @@ -504,6 +504,14 @@ class TestCommandsTestnet(ElectrumTestCase): assert settle_result['settled'] == payment_hash assert wallet.lnworker._preimages[payment_hash] == preimage.hex() assert payment_hash not in wallet.lnworker.dont_settle_htlcs + with (mock.patch.object( + wallet.lnworker, + 'get_payment_value', + return_value=(None, 10000*1000, None, None), + )): + settled_status: dict = await cmds.check_hold_invoice(payment_hash=payment_hash, wallet=wallet) + assert settled_status['status'] == 'settled' + assert settled_status['amount_sat_received'] == 10000 with self.assertRaises(AssertionError): # cancelling a settled invoice should raise From b4de29e6920e5ba9d381a671d897d92caa635794 Mon Sep 17 00:00:00 2001 From: Felix <51097237+f321x@users.noreply.github.com> Date: Sun, 20 Jul 2025 17:47:33 +0200 Subject: [PATCH 2/2] Add `invoice_amount_sat` to check_hold_invoice response Adds an additional value to the `check_hold_invoice` cli command: `invoice_amount_sat` which returns the requested amount value of the hold invoice. Co-authored-by: ghost43 --- electrum/commands.py | 4 +++- tests/test_commands.py | 5 +++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/electrum/commands.py b/electrum/commands.py index eb3641474..f85d15eee 100644 --- a/electrum/commands.py +++ b/electrum/commands.py @@ -1489,8 +1489,10 @@ class Commands(Logger): amount_sat = amount_msat // 1000 result = { "status": status, - "amount_sat_received": amount_sat + "received_amount_sat": amount_sat, } + if info is not None: + result["invoice_amount_sat"] = (info.amount_msat or 0) // 1000 return result @command('w') diff --git a/tests/test_commands.py b/tests/test_commands.py index 412b0214d..6ef5d1dad 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -495,7 +495,7 @@ class TestCommandsTestnet(ElectrumTestCase): mock.patch.object(wallet.lnworker, 'get_payment_mpp_amount_msat', return_value=10_000 * 1000): status: dict = await cmds.check_hold_invoice(payment_hash=payment_hash, wallet=wallet) assert status['status'] == 'paid' - assert status['amount_sat_received'] == 10000 + assert status['received_amount_sat'] == 10000 settle_result = await cmds.settle_hold_invoice( preimage=preimage.hex(), @@ -511,7 +511,8 @@ class TestCommandsTestnet(ElectrumTestCase): )): settled_status: dict = await cmds.check_hold_invoice(payment_hash=payment_hash, wallet=wallet) assert settled_status['status'] == 'settled' - assert settled_status['amount_sat_received'] == 10000 + assert settled_status['received_amount_sat'] == 10000 + assert settled_status['invoice_amount_sat'] == 10000 with self.assertRaises(AssertionError): # cancelling a settled invoice should raise