Merge pull request #10528 from f321x/qt_swapserver_list_resize

swaps: improve SwapServerDialog, provider CLI, bugfixes
This commit is contained in:
ThomasV
2026-03-19 09:42:05 +01:00
committed by GitHub
7 changed files with 30 additions and 22 deletions
+1 -1
View File
@@ -2016,7 +2016,7 @@ class Commands(Logger):
result = {} result = {}
for offer in offers: for offer in offers:
result[offer.server_npub] = { result[offer.server_npub] = {
"percentage_fee": offer.pairs.percentage, "percentage_fee": float(offer.pairs.percentage),
"max_forward_sat": offer.pairs.max_forward, "max_forward_sat": offer.pairs.max_forward,
"max_reverse_sat": offer.pairs.max_reverse, "max_reverse_sat": offer.pairs.max_reverse,
"min_amount_sat": offer.pairs.min_amount, "min_amount_sat": offer.pairs.min_amount,
+1 -1
View File
@@ -75,7 +75,7 @@ class QESwapServerNPubListModel(QAbstractListModel):
return { return {
'npub': x.server_npub, 'npub': x.server_npub,
'server_pubkey': x.server_pubkey, 'server_pubkey': x.server_pubkey,
'percentage_fee': x.pairs.percentage, 'percentage_fee': float(x.pairs.percentage),
'mining_fee': x.pairs.mining_fee, 'mining_fee': x.pairs.mining_fee,
'min_amount': x.pairs.min_amount, 'min_amount': x.pairs.min_amount,
'max_forward_amount': x.pairs.max_forward, 'max_forward_amount': x.pairs.max_forward,
+2 -2
View File
@@ -534,8 +534,8 @@ class SwapServerDialog(WindowModalDialog, QtEventListener):
vbox = QVBoxLayout() vbox = QVBoxLayout()
self.setLayout(vbox) self.setLayout(vbox)
vbox.addWidget(WWLabel(msg)) vbox.addWidget(WWLabel(msg))
vbox.addWidget(self.servers_list) vbox.addWidget(self.servers_list, stretch=1)
vbox.addStretch() vbox.addSpacing(10)
self.ok_button = OkButton(self) self.ok_button = OkButton(self)
vbox.addLayout(Buttons(CancelButton(self), self.ok_button)) vbox.addLayout(Buttons(CancelButton(self), self.ok_button))
self.setMinimumWidth(650) self.setMinimumWidth(650)
+15 -6
View File
@@ -2,6 +2,7 @@ from typing import TYPE_CHECKING, List
from electrum.simple_config import ConfigVar, SimpleConfig from electrum.simple_config import ConfigVar, SimpleConfig
from electrum.commands import plugin_command from electrum.commands import plugin_command
from electrum.address_synchronizer import TX_HEIGHT_UNCONFIRMED
if TYPE_CHECKING: if TYPE_CHECKING:
from electrum.commands import Commands from electrum.commands import Commands
@@ -19,7 +20,7 @@ SimpleConfig.SWAPSERVER_ANN_POW_NONCE = ConfigVar('plugins.swapserver.ann_pow_no
@plugin_command('wl', plugin_name) @plugin_command('wl', plugin_name)
async def get_history(self: 'Commands', wallet: 'Abstract_Wallet' = None, plugin = None) -> List[dict]: async def get_history(self: 'Commands', wallet: 'Abstract_Wallet' = None, plugin = None) -> List[dict]:
""" """
Get a list of all swaps provided by this swapserver. Get a list of all confirmed swaps provided by this swapserver.
Single elements can potentially cover multiple swaps if transactions have been batched. Single elements can potentially cover multiple swaps if transactions have been batched.
Example result: Example result:
@@ -42,12 +43,20 @@ async def get_history(self: 'Commands', wallet: 'Abstract_Wallet' = None, plugin
assert wallet.lnworker, "lightning not available" assert wallet.lnworker, "lightning not available"
assert wallet.lnworker.swap_manager, "swap manager not available" assert wallet.lnworker.swap_manager, "swap manager not available"
full_history = wallet.get_full_history() sm = wallet.lnworker.swap_manager
swap_group_ids = set( swap_group_ids = set()
x['group_id'] for x in wallet.lnworker.swap_manager.get_groups_for_onchain_history().values() for swap in sm._swaps.values():
) group_id = swap.spending_txid if swap.is_reverse else swap.funding_txid
if group_id is None:
continue
if swap.spending_txid is None \
or wallet.adb.get_tx_height(swap.spending_txid).height() <= TX_HEIGHT_UNCONFIRMED:
# get only final swaps so the history is stable and doesn't include pending swaps
continue
swap_group_ids.add(group_id)
swap_history_items = [] swap_history_items = []
full_history = wallet.get_full_history()
for swap_group_id in swap_group_ids: for swap_group_id in swap_group_ids:
if swap_history_item := full_history.get('group:' + swap_group_id): if swap_history_item := full_history.get('group:' + swap_group_id):
swap_history_items.append(swap_history_item) swap_history_items.append(swap_history_item)
@@ -66,7 +75,7 @@ async def get_history(self: 'Commands', wallet: 'Abstract_Wallet' = None, plugin
@plugin_command('wl', plugin_name) @plugin_command('wl', plugin_name)
async def get_summary(self: 'Commands', wallet: 'Abstract_Wallet' = None, plugin = None) -> dict: async def get_summary(self: 'Commands', wallet: 'Abstract_Wallet' = None, plugin = None) -> dict:
"""Get a summary of all swaps provided by this swapserver. """Get a summary of all confirmed swaps provided by this swapserver.
Can become incorrect if closed lightning channels have been deleted in this wallet. Can become incorrect if closed lightning channels have been deleted in this wallet.
Example result: Example result:
+1 -1
View File
@@ -95,7 +95,7 @@ class HttpSwapServer(Logger, EventListener):
"minimal": sm._min_amount, "minimal": sm._min_amount,
}, },
"fees": { "fees": {
"percentage": sm.percentage, "percentage": float(sm.percentage), # cast to float for <= 4.7.1 backwards compatibility
"minerFees": { "minerFees": {
"baseAsset": { "baseAsset": {
"normal": sm.mining_fee, "normal": sm.mining_fee,
+8 -9
View File
@@ -168,7 +168,7 @@ def now():
@attr.s(frozen=True) @attr.s(frozen=True)
class SwapFees: class SwapFees:
percentage = attr.ib(type=int) percentage = attr.ib(type=Decimal)
mining_fee = attr.ib(type=int) mining_fee = attr.ib(type=int)
min_amount = attr.ib(type=int) min_amount = attr.ib(type=int)
max_forward = attr.ib(type=int) max_forward = attr.ib(type=int)
@@ -235,7 +235,7 @@ class SwapManager(Logger):
def __init__(self, *, wallet: 'Abstract_Wallet', lnworker: 'LNWallet'): def __init__(self, *, wallet: 'Abstract_Wallet', lnworker: 'LNWallet'):
Logger.__init__(self) Logger.__init__(self)
self.mining_fee = None self.mining_fee = None
self.percentage = None self.percentage = None # type: Optional[Decimal]
self._min_amount = None self._min_amount = None
self._max_forward = None self._max_forward = None
self._max_reverse = None self._max_reverse = None
@@ -1193,7 +1193,7 @@ class SwapManager(Logger):
def server_update_pairs(self) -> None: def server_update_pairs(self) -> None:
""" for server """ """ for server """
self.percentage = float(self.config.SWAPSERVER_FEE_MILLIONTHS) / 10000 # type: ignore self.percentage = Decimal(self.config.SWAPSERVER_FEE_MILLIONTHS) / 10000 # type: ignore
self._min_amount = MIN_SWAP_AMOUNT_SAT self._min_amount = MIN_SWAP_AMOUNT_SAT
oc_balance_sat: int = self.wallet.get_spendable_balance_sat() oc_balance_sat: int = self.wallet.get_spendable_balance_sat()
max_forward: int = min(int(self.lnworker.num_sats_can_receive()), oc_balance_sat, 10000000) max_forward: int = min(int(self.lnworker.num_sats_can_receive()), oc_balance_sat, 10000000)
@@ -1259,7 +1259,7 @@ class SwapManager(Logger):
if send_amount is None: if send_amount is None:
return None return None
x = Decimal(send_amount) x = Decimal(send_amount)
percentage = Decimal(self.percentage) percentage = self.percentage
if is_reverse: if is_reverse:
if not self.check_invoice_amount(x, is_reverse): if not self.check_invoice_amount(x, is_reverse):
return None return None
@@ -1289,7 +1289,7 @@ class SwapManager(Logger):
if not recv_amount: if not recv_amount:
return None return None
x = Decimal(recv_amount) x = Decimal(recv_amount)
percentage = Decimal(self.percentage) percentage = self.percentage
if is_reverse: if is_reverse:
# see/ref: # see/ref:
# https://github.com/BoltzExchange/boltz-backend/blob/e7e2d30f42a5bea3665b164feb85f84c64d86658/lib/service/Service.ts#L928 # https://github.com/BoltzExchange/boltz-backend/blob/e7e2d30f42a5bea3665b164feb85f84c64d86658/lib/service/Service.ts#L928
@@ -1638,7 +1638,7 @@ class HttpTransport(SwapServerTransport):
fees = response['pairs']['BTC/BTC']['fees'] fees = response['pairs']['BTC/BTC']['fees']
limits = response['pairs']['BTC/BTC']['limits'] limits = response['pairs']['BTC/BTC']['limits']
pairs = SwapFees( pairs = SwapFees(
percentage=fees['percentage'], percentage=Decimal(str(fees['percentage'])),
mining_fee=fees['minerFees']['baseAsset']['mining_fee'], mining_fee=fees['minerFees']['baseAsset']['mining_fee'],
min_amount=limits['minimal'], min_amount=limits['minimal'],
max_forward=limits['max_forward_amount'], max_forward=limits['max_forward_amount'],
@@ -1777,7 +1777,7 @@ class NostrTransport(SwapServerTransport):
self.logger.warning(f"not publishing swap offer, no liquidity available: {sm._max_forward=}, {sm._max_reverse=}") self.logger.warning(f"not publishing swap offer, no liquidity available: {sm._max_forward=}, {sm._max_reverse=}")
return return
offer = { offer = {
'percentage_fee': sm.percentage, 'percentage_fee': float(sm.percentage), # cast to float for <= 4.7.1 backwards compatibility
'mining_fee': sm.mining_fee, 'mining_fee': sm.mining_fee,
'min_amount': sm._min_amount, 'min_amount': sm._min_amount,
'max_forward_amount': sm._max_forward, 'max_forward_amount': sm._max_forward,
@@ -1847,7 +1847,6 @@ class NostrTransport(SwapServerTransport):
"#d": [f"electrum-swapserver-{self.NOSTR_EVENT_VERSION}"], "#d": [f"electrum-swapserver-{self.NOSTR_EVENT_VERSION}"],
"#r": [f"net:{constants.net.NET_NAME}"], "#r": [f"net:{constants.net.NET_NAME}"],
"since": int(time.time()) - 60 * 60, "since": int(time.time()) - 60 * 60,
"until": int(time.time()) + 60 * 60,
} }
async for event in self.relay_manager.get_events(query, single_event=False, only_stored=False): async for event in self.relay_manager.get_events(query, single_event=False, only_stored=False):
try: try:
@@ -1884,7 +1883,7 @@ class NostrTransport(SwapServerTransport):
continue continue
try: try:
pairs = SwapFees( pairs = SwapFees(
percentage=content['percentage_fee'], percentage=Decimal(str(content['percentage_fee'])),
mining_fee=content['mining_fee'], mining_fee=content['mining_fee'],
min_amount=content['min_amount'], min_amount=content['min_amount'],
max_forward=content['max_forward_amount'], max_forward=content['max_forward_amount'],
+2 -2
View File
@@ -678,7 +678,7 @@ class TestCommandsTestnet(ElectrumTestCase):
offer1 = SwapOffer( offer1 = SwapOffer(
pairs=SwapFees( pairs=SwapFees(
percentage=0.5, percentage=Decimal('0.5'),
mining_fee=2000, mining_fee=2000,
min_amount=10000, min_amount=10000,
max_forward=1000000, max_forward=1000000,
@@ -692,7 +692,7 @@ class TestCommandsTestnet(ElectrumTestCase):
offer2 = SwapOffer( offer2 = SwapOffer(
pairs=SwapFees( pairs=SwapFees(
percentage=1.0, percentage=Decimal('1.0'),
mining_fee=3000, mining_fee=3000,
min_amount=20000, min_amount=20000,
max_forward=2000000, max_forward=2000000,