diff --git a/electrum/gui/qt/channel_details.py b/electrum/gui/qt/channel_details.py index 1ff9cd990..cbe055d9e 100644 --- a/electrum/gui/qt/channel_details.py +++ b/electrum/gui/qt/channel_details.py @@ -200,9 +200,9 @@ class ChannelDetailsDialog(QtWidgets.QDialog, MessageBoxMixin): w = QtWidgets.QTreeView(self) htlc_dict = chan.get_payments() htlc_list = [] - for rhash, _list in htlc_dict.items(): - for _tuple in _list: - htlc_list.append((rhash.hex(),) + _tuple) + for rhash, plist in htlc_dict.items(): + for htlc_with_status in plist: + htlc_list.append((rhash.hex(),) + htlc_with_status) w.setModel(self.make_model(htlc_list)) w.header().setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents) vbox.addWidget(w) diff --git a/electrum/lnchannel.py b/electrum/lnchannel.py index 908ce6e7a..22aad8989 100644 --- a/electrum/lnchannel.py +++ b/electrum/lnchannel.py @@ -24,7 +24,7 @@ import binascii import json from enum import IntEnum from typing import (Optional, Dict, List, Tuple, NamedTuple, Set, Callable, - Iterable, Sequence, TYPE_CHECKING, Iterator, Union) + Iterable, Sequence, TYPE_CHECKING, Iterator, Union, Mapping) import time import threading from abc import ABC, abstractmethod @@ -140,6 +140,13 @@ def htlcsum(htlcs: Iterable[UpdateAddHtlc]): return sum([x.amount_msat for x in htlcs]) +class HTLCWithStatus(NamedTuple): + channel_id: bytes + htlc: UpdateAddHtlc + direction: Direction + status: str + + class AbstractChannel(Logger, ABC): storage: Union['StoredDict', dict] config: Dict[HTLCOwner, Union[LocalConfig, RemoteConfig]] @@ -722,7 +729,7 @@ class Channel(AbstractChannel): def get_next_feerate(self, subject: HTLCOwner) -> int: return self.hm.get_feerate_in_next_ctx(subject) - def get_payments(self, status=None): + def get_payments(self, status=None) -> Mapping[bytes, List[HTLCWithStatus]]: out = defaultdict(list) for direction, htlc in self.hm.all_htlcs_ever(): htlc_proposer = LOCAL if direction is SENT else REMOTE @@ -734,7 +741,9 @@ class Channel(AbstractChannel): _status = 'inflight' if status and status != _status: continue - out[htlc.payment_hash].append((self.channel_id, htlc, direction, _status)) + htlc_with_status = HTLCWithStatus( + channel_id=self.channel_id, htlc=htlc, direction=direction, status=_status) + out[htlc.payment_hash].append(htlc_with_status) return out def open_with_first_pcp(self, remote_pcp: bytes, remote_sig: bytes) -> None: diff --git a/electrum/lnworker.py b/electrum/lnworker.py index 2ce539c77..10dc6bde8 100644 --- a/electrum/lnworker.py +++ b/electrum/lnworker.py @@ -48,7 +48,7 @@ from .lnpeer import Peer, LN_P2P_NETWORK_TIMEOUT from .lnaddr import lnencode, LnAddr, lndecode from .ecc import der_sig_from_sig_string from .lnchannel import Channel, AbstractChannel -from .lnchannel import ChannelState, PeerState +from .lnchannel import ChannelState, PeerState, HTLCWithStatus from .lnrater import LNRater from . import lnutil from .lnutil import funding_output_script @@ -777,24 +777,27 @@ class LNWallet(LNWorker): util.trigger_callback('channel', self.wallet, chan) super().peer_closed(peer) - def get_payments(self, *, status=None): - # return one item per payment_hash - # note: with AMP we will have several channels per payment + def get_payments(self, *, status=None) -> Mapping[bytes, List[HTLCWithStatus]]: out = defaultdict(list) for chan in self.channels.values(): d = chan.get_payments(status=status) - for k, v in d.items(): - out[k] += v + for payment_hash, plist in d.items(): + out[payment_hash] += plist return out - def get_payment_value(self, info: Optional['PaymentInfo'], plist): + def get_payment_value( + self, info: Optional['PaymentInfo'], plist: List[HTLCWithStatus], + ) -> Tuple[int, int, int]: + assert plist amount_msat = 0 fee_msat = None - for chan_id, htlc, _direction, _status in plist: + for htlc_with_status in plist: + htlc = htlc_with_status.htlc + _direction = htlc_with_status.direction amount_msat += int(_direction) * htlc.amount_msat if _direction == SENT and info and info.amount_msat: fee_msat = (fee_msat or 0) - info.amount_msat - amount_msat - timestamp = min([htlc.timestamp for chan_id, htlc, _direction, _status in plist]) + timestamp = min([htlc_with_status.htlc.timestamp for htlc_with_status in plist]) return amount_msat, fee_msat, timestamp def get_lightning_history(self):