From cc25048e29c600da94e641cfa625741b25102dc0 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Sun, 18 May 2025 19:51:55 +0200 Subject: [PATCH] swap providers dialog with liquidity info --- electrum/gui/qt/main_window.py | 19 ++---------- electrum/gui/qt/swap_dialog.py | 56 ++++++++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 18 deletions(-) diff --git a/electrum/gui/qt/main_window.py b/electrum/gui/qt/main_window.py index 26e2a5562..9dfd24327 100644 --- a/electrum/gui/qt/main_window.py +++ b/electrum/gui/qt/main_window.py @@ -1327,22 +1327,9 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger, QtEventListener): ])) return False sm = self.wallet.lnworker.swap_manager - def descr(x): - last_seen = util.age(x['timestamp']) - return (f"pubkey={x['pubkey'][0:10]}, " - f"fee={x['percentage_fee']}% + {x['mining_fee']} sats, " - f"last_seen: {last_seen}") - server_keys = [ChoiceItem(key=x['pubkey'], label=descr(x)) for x in recent_offers] - msg = '\n'.join([ - _("Please choose a server from this list."), - _("Note that fees may be updated frequently.") - ]) - choice = self.query_choice( - msg=msg, - choices=server_keys, - title=_("Choose Swap Server"), - default_key=self.config.SWAPSERVER_NPUB, - ) + from .swap_dialog import SwapServerDialog + d = SwapServerDialog(self, recent_offers) + choice = d.run() if choice is None: return False self.config.SWAPSERVER_NPUB = choice diff --git a/electrum/gui/qt/swap_dialog.py b/electrum/gui/qt/swap_dialog.py index a636b082c..651eac9a2 100644 --- a/electrum/gui/qt/swap_dialog.py +++ b/electrum/gui/qt/swap_dialog.py @@ -1,7 +1,8 @@ from typing import TYPE_CHECKING, Optional, Union, Tuple -from PyQt6.QtCore import pyqtSignal +from PyQt6.QtCore import pyqtSignal, Qt from PyQt6.QtWidgets import QLabel, QVBoxLayout, QGridLayout, QPushButton +from PyQt6.QtWidgets import QTreeWidget, QTreeWidgetItem, QHeaderView from electrum.i18n import _ from electrum.util import NotEnoughFunds, NoDynamicFeeEstimates, UserCancelled @@ -30,6 +31,8 @@ Do you want to continue?""" ) +ROLE_PUBKEY = Qt.ItemDataRole.UserRole + 1000 + class InvalidSwapParameters(Exception): pass @@ -47,7 +50,7 @@ class SwapDialog(WindowModalDialog, QtEventListener): vbox = QVBoxLayout(self) toolbar, menu = create_toolbar_with_menu(self.config, '') menu.addAction( - _('Choose swap server'), + _('Choose swap provider'), lambda: self.window.choose_swapserver_dialog(transport), ).setEnabled(not self.config.SWAPSERVER_URL) vbox.addLayout(toolbar) @@ -391,3 +394,52 @@ class SwapDialog(WindowModalDialog, QtEventListener): toType=onchain_funds if self.is_reverse else lightning_funds, capacityType="receiving" if self.is_reverse else "sending", ) + + +class SwapServerDialog(WindowModalDialog, QtEventListener): + + def __init__(self, window, servers): + WindowModalDialog.__init__(self, window, _('Choose Swap Provider')) + self.window = window + self.config = window.config + msg = '\n'.join([ + _("Please choose a provider from this list."), + _("Note that fees and liquidity may be updated frequently.") + ]) + self.servers_list = QTreeWidget() + self.servers_list.setColumnCount(5) + self.servers_list.setHeaderLabels([_("Pubkey"), _("Fee"), _('Max Forward'), _('Max Reverse'), _("Last seen")]) + self.servers_list.header().setStretchLastSection(False) + for col_idx in range(5): + sm = QHeaderView.ResizeMode.Stretch if col_idx == 0 else QHeaderView.ResizeMode.ResizeToContents + self.servers_list.header().setSectionResizeMode(col_idx, sm) + self.update_servers_list(servers) + vbox = QVBoxLayout() + self.setLayout(vbox) + vbox.addWidget(WWLabel(msg)) + vbox.addWidget(self.servers_list) + vbox.addStretch() + self.ok_button = OkButton(self) + vbox.addLayout(Buttons(CancelButton(self), self.ok_button)) + self.setMinimumWidth(650) + + def run(self): + if self.exec() != 1: + return + if item := self.servers_list.currentItem(): + return item.data(0, ROLE_PUBKEY) + + def update_servers_list(self, servers): + self.servers_list.clear() + from electrum.util import age + items = [] + for x in servers: + # fixme: these fields have not been sanitized yet + last_seen = age(x['timestamp']) + fee = f"{x['percentage_fee']}% + {x['mining_fee']} sats" + max_forward = self.window.format_amount(x['max_forward_amount']) + ' ' + self.window.base_unit() + max_reverse = self.window.format_amount(x['max_reverse_amount']) + ' ' + self.window.base_unit() + item = QTreeWidgetItem([x['pubkey'][0:10], fee, max_forward, max_reverse, last_seen]) + item.setData(0, ROLE_PUBKEY, x['pubkey']) + items.append(item) + self.servers_list.insertTopLevelItems(0, items)