cli: return closest htlc expiry from check_hold_invoice
Adds a `closest_htlc_expiry_height` value to the `check_hold_invoice` cli command response. This allows to see the next absolute expiry height of the pending htlcs of a payment. Note, htlcs will get failed before the actual expiry height (if block_height + 144 > htlc.cltv_abs).
This commit is contained in:
@@ -1465,7 +1465,13 @@ class Commands(Logger):
|
|||||||
async def check_hold_invoice(self, payment_hash: str, wallet: Abstract_Wallet = None) -> dict:
|
async def check_hold_invoice(self, payment_hash: str, wallet: Abstract_Wallet = None) -> dict:
|
||||||
"""
|
"""
|
||||||
Checks the status of a lightning hold invoice 'payment_hash'.
|
Checks the status of a lightning hold invoice 'payment_hash'.
|
||||||
Possible states: unpaid, paid, settled, unknown (cancelled or not found)
|
Returns: {
|
||||||
|
"status": unpaid | paid | settled | unknown (cancelled or not found),
|
||||||
|
"received_amount_sat": currently received amount (pending htlcs or final after settling),
|
||||||
|
"invoice_amount_sat": Invoice amount, Optional (only if invoice is found),
|
||||||
|
"closest_htlc_expiry_height": Closest absolute expiry height of all received htlcs
|
||||||
|
(Note: HTLCs will get failed automatically if block_height + 144 > htlc_expiry_height)
|
||||||
|
}
|
||||||
|
|
||||||
arg:str:payment_hash:Payment hash in hex of the hold invoice
|
arg:str:payment_hash:Payment hash in hex of the hold invoice
|
||||||
"""
|
"""
|
||||||
@@ -1473,24 +1479,28 @@ class Commands(Logger):
|
|||||||
info: Optional['PaymentInfo'] = wallet.lnworker.get_payment_info(bfh(payment_hash))
|
info: Optional['PaymentInfo'] = wallet.lnworker.get_payment_info(bfh(payment_hash))
|
||||||
is_accepted_mpp: bool = wallet.lnworker.is_accepted_mpp(bfh(payment_hash))
|
is_accepted_mpp: bool = wallet.lnworker.is_accepted_mpp(bfh(payment_hash))
|
||||||
amount_sat = (wallet.lnworker.get_payment_mpp_amount_msat(bfh(payment_hash)) or 0) // 1000
|
amount_sat = (wallet.lnworker.get_payment_mpp_amount_msat(bfh(payment_hash)) or 0) // 1000
|
||||||
status = "unknown"
|
result = {
|
||||||
|
"status": "unknown",
|
||||||
|
"received_amount_sat": amount_sat,
|
||||||
|
}
|
||||||
if info is None:
|
if info is None:
|
||||||
pass
|
pass
|
||||||
elif not is_accepted_mpp and not wallet.lnworker.get_preimage_hex(payment_hash):
|
elif not is_accepted_mpp and not wallet.lnworker.get_preimage_hex(payment_hash):
|
||||||
# is_accepted_mpp is False for settled payments
|
# is_accepted_mpp is False for settled payments
|
||||||
status = "unpaid"
|
result["status"] = "unpaid"
|
||||||
elif is_accepted_mpp and payment_hash in wallet.lnworker.dont_settle_htlcs:
|
elif is_accepted_mpp and payment_hash in wallet.lnworker.dont_settle_htlcs:
|
||||||
status = "paid"
|
result["status"] = "paid"
|
||||||
|
payment_key: str = wallet.lnworker._get_payment_key(bfh(payment_hash)).hex()
|
||||||
|
htlc_status = wallet.lnworker.received_mpp_htlcs[payment_key]
|
||||||
|
result["closest_htlc_expiry_height"] = min(
|
||||||
|
htlc.cltv_abs for _, htlc in htlc_status.htlc_set
|
||||||
|
)
|
||||||
elif wallet.lnworker.get_preimage_hex(payment_hash) is not None \
|
elif wallet.lnworker.get_preimage_hex(payment_hash) is not None \
|
||||||
and payment_hash not in wallet.lnworker.dont_settle_htlcs:
|
and payment_hash not in wallet.lnworker.dont_settle_htlcs:
|
||||||
status = "settled"
|
result["status"] = "settled"
|
||||||
plist = wallet.lnworker.get_payments(status='settled')[bfh(payment_hash)]
|
plist = wallet.lnworker.get_payments(status='settled')[bfh(payment_hash)]
|
||||||
_dir, amount_msat, _fee, _ts = wallet.lnworker.get_payment_value(info, plist)
|
_dir, amount_msat, _fee, _ts = wallet.lnworker.get_payment_value(info, plist)
|
||||||
amount_sat = amount_msat // 1000
|
result["received_amount_sat"] = amount_msat // 1000
|
||||||
result = {
|
|
||||||
"status": status,
|
|
||||||
"received_amount_sat": amount_sat,
|
|
||||||
}
|
|
||||||
if info is not None:
|
if info is not None:
|
||||||
result["invoice_amount_sat"] = (info.amount_msat or 0) // 1000
|
result["invoice_amount_sat"] = (info.amount_msat or 0) // 1000
|
||||||
return result
|
return result
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from os import urandom
|
|||||||
|
|
||||||
from electrum.commands import Commands, eval_bool
|
from electrum.commands import Commands, eval_bool
|
||||||
from electrum import storage, wallet
|
from electrum import storage, wallet
|
||||||
|
from electrum.lnworker import RecvMPPResolution
|
||||||
from electrum.wallet import restore_wallet_from_text, Abstract_Wallet
|
from electrum.wallet import restore_wallet_from_text, Abstract_Wallet
|
||||||
from electrum.address_synchronizer import TX_HEIGHT_UNCONFIRMED
|
from electrum.address_synchronizer import TX_HEIGHT_UNCONFIRMED
|
||||||
from electrum.simple_config import SimpleConfig
|
from electrum.simple_config import SimpleConfig
|
||||||
@@ -491,11 +492,22 @@ class TestCommandsTestnet(ElectrumTestCase):
|
|||||||
wallet=wallet,
|
wallet=wallet,
|
||||||
)
|
)
|
||||||
|
|
||||||
with mock.patch.object(wallet.lnworker, 'is_accepted_mpp', return_value=True), \
|
mock_htlc1 = mock.Mock()
|
||||||
mock.patch.object(wallet.lnworker, 'get_payment_mpp_amount_msat', return_value=10_000 * 1000):
|
mock_htlc1.cltv_abs = 800_000
|
||||||
|
mock_htlc1.amount_msat = 4_500_000
|
||||||
|
mock_htlc2 = mock.Mock()
|
||||||
|
mock_htlc2.cltv_abs = 800_144
|
||||||
|
mock_htlc2.amount_msat = 5_500_000
|
||||||
|
mock_htlc_status = mock.Mock()
|
||||||
|
mock_htlc_status.htlc_set = [(None, mock_htlc1), (None, mock_htlc2)]
|
||||||
|
mock_htlc_status.resolution = RecvMPPResolution.ACCEPTED
|
||||||
|
|
||||||
|
payment_key = wallet.lnworker._get_payment_key(bytes.fromhex(payment_hash)).hex()
|
||||||
|
with mock.patch.dict(wallet.lnworker.received_mpp_htlcs, {payment_key: mock_htlc_status}):
|
||||||
status: dict = await cmds.check_hold_invoice(payment_hash=payment_hash, wallet=wallet)
|
status: dict = await cmds.check_hold_invoice(payment_hash=payment_hash, wallet=wallet)
|
||||||
assert status['status'] == 'paid'
|
assert status['status'] == 'paid'
|
||||||
assert status['received_amount_sat'] == 10000
|
assert status['received_amount_sat'] == 10000
|
||||||
|
assert status['closest_htlc_expiry_height'] == 800_000
|
||||||
|
|
||||||
settle_result = await cmds.settle_hold_invoice(
|
settle_result = await cmds.settle_hold_invoice(
|
||||||
preimage=preimage.hex(),
|
preimage=preimage.hex(),
|
||||||
|
|||||||
Reference in New Issue
Block a user