diff --git a/electrum/gui/qt/channel_details.py b/electrum/gui/qt/channel_details.py
index 357346b27..d60a211cb 100644
--- a/electrum/gui/qt/channel_details.py
+++ b/electrum/gui/qt/channel_details.py
@@ -38,6 +38,50 @@ class LinkedLabel(QtWidgets.QLabel):
class ChannelDetailsDialog(QtWidgets.QDialog, MessageBoxMixin, QtEventListener):
+ def __init__(self, window: 'ElectrumWindow', chan: AbstractChannel):
+ super().__init__(window)
+ # initialize instance fields
+ self.window = window
+ self.wallet = window.wallet
+ self.chan = chan
+ self.format_msat = lambda msat: window.format_amount_and_units(msat / 1000)
+ self.format_sat = lambda sat: window.format_amount_and_units(sat)
+ # register callbacks for updating
+ self.register_callbacks()
+ title = _('Lightning Channel') if not self.chan.is_backup() else _('Channel Backup')
+ self.setWindowTitle(title)
+ self.setMinimumSize(800, 400)
+ # activity labels. not used for backups.
+ self.local_balance_label = SelectableLabel()
+ self.remote_balance_label = SelectableLabel()
+ self.can_send_label = SelectableLabel()
+ self.can_receive_label = SelectableLabel()
+ # add widgets
+ vbox = QtWidgets.QVBoxLayout(self)
+ if self.chan.is_backup():
+ vbox.addWidget(QLabel('\n'.join([
+ _("This is a channel backup."),
+ _("It shows a channel that was opened with another instance of this wallet"),
+ _("A backup does not contain information about your local balance in the channel."),
+ _("You can use it to request a force close.")
+ ])))
+
+ form = self.get_common_form(chan)
+ vbox.addLayout(form)
+ if not self.chan.is_closed() and not self.chan.is_backup():
+ hbox_stats = self.get_hbox_stats(chan)
+ form.addRow(QLabel(_('Channel stats')+ ':'), hbox_stats)
+
+ if not self.chan.is_backup():
+ # add htlc tree view to vbox (wouldn't scale correctly in QFormLayout)
+ vbox.addWidget(QLabel(_('Payments (HTLCs):')))
+ w = self.create_htlc_list(chan)
+ vbox.addWidget(w)
+
+ vbox.addLayout(Buttons(CloseButton(self)))
+ # initialize sent/received fields
+ self.update()
+
def make_htlc_item(self, i: UpdateAddHtlc, direction: Direction) -> HTLCItem:
it = HTLCItem(_('Sent HTLC with ID {}' if Direction.SENT == direction else 'Received HTLC with ID {}').format(i.htlc_id))
it.appendRow([HTLCItem(_('Amount')),HTLCItem(self.format_msat(i.amount_msat))])
@@ -113,6 +157,8 @@ class ChannelDetailsDialog(QtWidgets.QDialog, MessageBoxMixin, QtEventListener):
self.update()
def update(self):
+ if self.chan.is_closed() or self.chan.is_backup():
+ return
self.can_send_label.setText(self.format_msat(self.chan.available_to_spend(LOCAL)))
self.can_receive_label.setText(self.format_msat(self.chan.available_to_spend(REMOTE)))
self.sent_label.setText(self.format_msat(self.chan.total_msat(Direction.SENT)))
@@ -122,55 +168,47 @@ class ChannelDetailsDialog(QtWidgets.QDialog, MessageBoxMixin, QtEventListener):
@QtCore.pyqtSlot(str)
def show_tx(self, link_text: str):
- funding_tx = self.wallet.db.get_transaction(self.chan.funding_outpoint.txid)
- if not funding_tx:
- self.show_error(_("Funding transaction not found."))
+ tx = self.wallet.adb.get_transaction(link_text)
+ if not tx:
+ self.show_error(_("Transaction not found."))
return
- self.window.show_transaction(funding_tx, tx_desc=_('Funding Transaction'))
+ self.window.show_transaction(tx, tx_desc=_('Transaction'))
- def __init__(self, window: 'ElectrumWindow', chan_id: bytes):
- super().__init__(window)
-
- # initialize instance fields
- self.window = window
- self.wallet = window.wallet
- chan = self.chan = window.wallet.lnworker.channels[chan_id]
- self.format_msat = lambda msat: window.format_amount_and_units(msat / 1000)
- self.format_sat = lambda sat: window.format_amount_and_units(sat)
-
- # register callbacks for updating
- self.register_callbacks()
-
- # set attributes of QDialog
- self.setWindowTitle(_('Channel Details'))
- self.setMinimumSize(800, 400)
-
- # add layouts
- vbox = QtWidgets.QVBoxLayout(self)
+ def get_common_form(self, chan):
form = QtWidgets.QFormLayout(None)
remote_id_e = ShowQRLineEdit(chan.node_id.hex(), self.window.config, title=_("Remote Node ID"))
form.addRow(QLabel(_('Remote Node') + ':'), remote_id_e)
channel_id_e = ShowQRLineEdit(chan.channel_id.hex(), self.window.config, title=_("Channel ID"))
form.addRow(QLabel(_('Channel ID') + ':'), channel_id_e)
- funding_label_text = f'{chan.funding_outpoint.txid}:{chan.funding_outpoint.output_index}'
- form.addRow(QLabel(_('Funding Outpoint') + ':'), LinkedLabel(funding_label_text, self.show_tx))
+
form.addRow(QLabel(_('Short Channel ID') + ':'), QLabel(str(chan.short_channel_id)))
form.addRow(QLabel(_('State') + ':'), SelectableLabel(chan.get_state_for_GUI()))
+
self.capacity = self.format_sat(chan.get_capacity())
form.addRow(QLabel(_('Capacity') + ':'), SelectableLabel(self.capacity))
- form.addRow(QLabel(_('Channel type:')), SelectableLabel(chan.storage['channel_type'].name_minimal))
- initiator = 'Local' if chan.constraints.is_initiator else 'Remote'
- form.addRow(QLabel(_('Initiator:')), SelectableLabel(initiator))
- vbox.addLayout(form)
+ if not chan.is_backup():
+ form.addRow(QLabel(_('Channel type:')), SelectableLabel(chan.storage['channel_type'].name_minimal))
+ initiator = 'Local' if chan.constraints.is_initiator else 'Remote'
+ form.addRow(QLabel(_('Initiator:')), SelectableLabel(initiator))
+ else:
+ form.addRow(QLabel("Backup Type"), QLabel("imported" if self.chan.is_imported else "on-chain"))
+ funding_txid = chan.funding_outpoint.txid
+ funding_label_text = f'{funding_txid}:{chan.funding_outpoint.output_index}'
+ form.addRow(QLabel(_('Funding Outpoint') + ':'), LinkedLabel(funding_label_text, self.show_tx))
+ if chan.is_closed():
+ item = chan.get_closing_height()
+ if item:
+ closing_txid, closing_height, timestamp = item
+ closing_label_text = f'{closing_txid}'
+ form.addRow(QLabel(_('Closing Transaction') + ':'), LinkedLabel(closing_label_text, self.show_tx))
+ return form
+
+ def get_hbox_stats(self, chan):
hbox_stats = QHBoxLayout()
form_layout_left = QtWidgets.QFormLayout(None)
form_layout_right = QtWidgets.QFormLayout(None)
- self.local_balance_label = SelectableLabel()
- self.remote_balance_label = SelectableLabel()
form_layout_left.addRow(_('Local balance') + ':', self.local_balance_label)
form_layout_right.addRow(_('Remote balance') + ':', self.remote_balance_label)
- self.can_send_label = SelectableLabel()
- self.can_receive_label = SelectableLabel()
form_layout_left.addRow(_('Can send') + ':', self.can_send_label)
form_layout_right.addRow(_('Can receive') + ':', self.can_receive_label)
local_reserve_label = SelectableLabel("{}".format(
@@ -209,9 +247,9 @@ class ChannelDetailsDialog(QtWidgets.QDialog, MessageBoxMixin, QtEventListener):
hbox_stats.addWidget(line_separator)
# channel stats right column
hbox_stats.addLayout(form_layout_right, 50)
- vbox.addLayout(hbox_stats)
- # add htlc tree view to vbox (wouldn't scale correctly in QFormLayout)
- vbox.addWidget(QLabel(_('Payments (HTLCs):')))
+ return hbox_stats
+
+ def create_htlc_list(self, chan):
w = QtWidgets.QTreeView(self)
htlc_dict = chan.get_payments()
htlc_list = []
@@ -220,10 +258,7 @@ class ChannelDetailsDialog(QtWidgets.QDialog, MessageBoxMixin, QtEventListener):
htlc_list.append(htlc_with_status)
w.setModel(self.make_model(htlc_list))
w.header().setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeToContents)
- vbox.addWidget(w)
- vbox.addLayout(Buttons(CloseButton(self)))
- # initialize sent/received fields
- self.update()
+ return w
def closeEvent(self, event):
self.unregister_callbacks()
diff --git a/electrum/gui/qt/channels_list.py b/electrum/gui/qt/channels_list.py
index 82367a8d4..6340645c3 100644
--- a/electrum/gui/qt/channels_list.py
+++ b/electrum/gui/qt/channels_list.py
@@ -233,19 +233,8 @@ class ChannelsList(MyTreeView):
if not item:
return
channel_id = idx.sibling(idx.row(), self.Columns.NODE_ALIAS).data(ROLE_CHANNEL_ID)
- chan = self.lnworker.channel_backups.get(channel_id) or self.lnworker.channels[channel_id]
- if not chan.is_backup():
- menu.addAction(_("Details..."), lambda: self.parent.show_channel(channel_id))
- funding_tx = self.parent.wallet.db.get_transaction(chan.funding_outpoint.txid)
- if funding_tx:
- menu.addAction(_("View funding transaction"), lambda: self.parent.show_transaction(funding_tx))
- if chan.is_closed():
- item = chan.get_closing_height()
- if item:
- txid, height, timestamp = item
- closing_tx = self.parent.wallet.db.get_transaction(txid)
- if closing_tx:
- menu.addAction(_("View closing transaction"), lambda: self.parent.show_transaction(closing_tx))
+ chan = self.lnworker.channels.get(channel_id) or self.lnworker.channel_backups[channel_id]
+ menu.addAction(_("Details..."), lambda: self.parent.show_channel_details(chan))
menu.addSeparator()
cc = self.add_copy_menu(menu, idx)
cc.addAction(_("Node ID"), lambda: self.place_text_on_clipboard(
diff --git a/electrum/gui/qt/main_window.py b/electrum/gui/qt/main_window.py
index afc666015..a3e718af5 100644
--- a/electrum/gui/qt/main_window.py
+++ b/electrum/gui/qt/main_window.py
@@ -1059,9 +1059,9 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger, QtEventListener):
d = address_dialog.AddressDialog(self, addr)
d.exec_()
- def show_channel(self, channel_id):
- from . import channel_details
- channel_details.ChannelDetailsDialog(self, channel_id).show()
+ def show_channel_details(self, chan):
+ from .channel_details import ChannelDetailsDialog
+ ChannelDetailsDialog(self, chan).show()
def show_transaction(self, tx, *, tx_desc=None):
'''tx_desc is set only for txs created in the Send tab'''