swaps: add type hints to gui swap suggestion flow
Adds type more type hints and clearer variable names to the swap suggestion flow.
This commit is contained in:
@@ -107,6 +107,7 @@ from electrum.gui.common_qt.util import TaskThread
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from . import ElectrumGui
|
from . import ElectrumGui
|
||||||
from electrum.submarine_swaps import SwapOffer
|
from electrum.submarine_swaps import SwapOffer
|
||||||
|
from electrum.lnchannel import Channel
|
||||||
|
|
||||||
|
|
||||||
class StatusBarButton(QToolButton):
|
class StatusBarButton(QToolButton):
|
||||||
@@ -1258,32 +1259,43 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger, QtEventListener):
|
|||||||
def protect(self, func, args, password):
|
def protect(self, func, args, password):
|
||||||
return func(*args, password)
|
return func(*args, password)
|
||||||
|
|
||||||
def run_swap_dialog(self, is_reverse=None, recv_amount_sat=None, channels=None):
|
def run_swap_dialog(
|
||||||
|
self,
|
||||||
|
is_reverse: Optional[bool] = None,
|
||||||
|
recv_amount_sat_or_max: Optional[Union[int, str]] = None,
|
||||||
|
channels: Optional[Sequence['Channel']] = None,
|
||||||
|
) -> bool:
|
||||||
if not self.network:
|
if not self.network:
|
||||||
self.show_error(_("You are offline."))
|
self.show_error(_("You are offline."))
|
||||||
return
|
return False
|
||||||
if not self.wallet.lnworker:
|
if not self.wallet.lnworker:
|
||||||
self.show_error(_('Lightning is disabled'))
|
self.show_error(_('Lightning is disabled'))
|
||||||
return
|
return False
|
||||||
if not self.wallet.lnworker.num_sats_can_send() and not self.wallet.lnworker.num_sats_can_receive():
|
if not self.wallet.lnworker.num_sats_can_send() and not self.wallet.lnworker.num_sats_can_receive():
|
||||||
self.show_error(_("You do not have liquidity in your active channels."))
|
self.show_error(_("You do not have liquidity in your active channels."))
|
||||||
return
|
return False
|
||||||
|
|
||||||
transport = self.create_sm_transport()
|
transport = self.create_sm_transport()
|
||||||
if not transport:
|
if not transport:
|
||||||
return
|
return False
|
||||||
|
|
||||||
with transport:
|
with transport:
|
||||||
if not self.initialize_swap_manager(transport):
|
if not self.initialize_swap_manager(transport):
|
||||||
return
|
return False
|
||||||
d = SwapDialog(self, transport, is_reverse=is_reverse, recv_amount_sat=recv_amount_sat, channels=channels)
|
d = SwapDialog(
|
||||||
|
self,
|
||||||
|
transport,
|
||||||
|
is_reverse=is_reverse,
|
||||||
|
recv_amount_sat_or_max=recv_amount_sat_or_max,
|
||||||
|
channels=channels
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
return d.run(transport)
|
return d.run(transport)
|
||||||
except InvalidSwapParameters as e:
|
except InvalidSwapParameters as e:
|
||||||
self.show_error(str(e))
|
self.show_error(str(e))
|
||||||
return
|
return False
|
||||||
except UserCancelled:
|
except UserCancelled:
|
||||||
return
|
return False
|
||||||
|
|
||||||
def create_sm_transport(self) -> Optional['SwapServerTransport']:
|
def create_sm_transport(self) -> Optional['SwapServerTransport']:
|
||||||
sm = self.wallet.lnworker.swap_manager
|
sm = self.wallet.lnworker.swap_manager
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ class ReceiveTab(QWidget, MessageBoxMixin, Logger):
|
|||||||
def on_receive_swap():
|
def on_receive_swap():
|
||||||
if self.receive_swap_button.suggestion:
|
if self.receive_swap_button.suggestion:
|
||||||
chan, swap_recv_amount_sat = self.receive_swap_button.suggestion
|
chan, swap_recv_amount_sat = self.receive_swap_button.suggestion
|
||||||
self.window.run_swap_dialog(is_reverse=True, recv_amount_sat=swap_recv_amount_sat, channels=[chan])
|
self.window.run_swap_dialog(is_reverse=True, recv_amount_sat_or_max=swap_recv_amount_sat, channels=[chan])
|
||||||
self.receive_swap_button.clicked.connect(on_receive_swap)
|
self.receive_swap_button.clicked.connect(on_receive_swap)
|
||||||
buttons = QHBoxLayout()
|
buttons = QHBoxLayout()
|
||||||
buttons.addWidget(self.receive_rebalance_button)
|
buttons.addWidget(self.receive_rebalance_button)
|
||||||
|
|||||||
@@ -712,7 +712,7 @@ class SendTab(QWidget, MessageBoxMixin, Logger):
|
|||||||
self.window.new_channel_dialog(amount_sat=amount_sat, min_amount_sat=min_amount_sat)
|
self.window.new_channel_dialog(amount_sat=amount_sat, min_amount_sat=min_amount_sat)
|
||||||
elif r == 'swap':
|
elif r == 'swap':
|
||||||
chan, swap_recv_amount_sat = can_pay_with_swap
|
chan, swap_recv_amount_sat = can_pay_with_swap
|
||||||
self.window.run_swap_dialog(is_reverse=False, recv_amount_sat=swap_recv_amount_sat, channels=[chan])
|
self.window.run_swap_dialog(is_reverse=False, recv_amount_sat_or_max=swap_recv_amount_sat, channels=[chan])
|
||||||
elif r == 'onchain':
|
elif r == 'onchain':
|
||||||
self.pay_onchain_dialog(invoice.get_outputs(), nonlocal_only=True, invoice=invoice)
|
self.pay_onchain_dialog(invoice.get_outputs(), nonlocal_only=True, invoice=invoice)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ from .my_treeview import create_toolbar_with_menu, MyTreeView
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .main_window import ElectrumWindow
|
from .main_window import ElectrumWindow
|
||||||
from electrum.submarine_swaps import SwapServerTransport, SwapOffer
|
from electrum.submarine_swaps import SwapServerTransport, SwapOffer
|
||||||
|
from electrum.lnchannel import Channel
|
||||||
|
|
||||||
CANNOT_RECEIVE_WARNING = _(
|
CANNOT_RECEIVE_WARNING = _(
|
||||||
"""The requested amount is higher than what you can receive in your currently open channels.
|
"""The requested amount is higher than what you can receive in your currently open channels.
|
||||||
@@ -43,7 +44,14 @@ class InvalidSwapParameters(Exception): pass
|
|||||||
|
|
||||||
class SwapDialog(WindowModalDialog, QtEventListener):
|
class SwapDialog(WindowModalDialog, QtEventListener):
|
||||||
|
|
||||||
def __init__(self, window: 'ElectrumWindow', transport: 'SwapServerTransport', is_reverse=None, recv_amount_sat=None, channels=None):
|
def __init__(
|
||||||
|
self,
|
||||||
|
window: 'ElectrumWindow',
|
||||||
|
transport: 'SwapServerTransport',
|
||||||
|
is_reverse: Optional[bool] = None,
|
||||||
|
recv_amount_sat_or_max: Optional[Union[int, str]] = None, # sat or '!'
|
||||||
|
channels: Optional[Sequence['Channel']] = None,
|
||||||
|
):
|
||||||
WindowModalDialog.__init__(self, window, _('Submarine Swap'))
|
WindowModalDialog.__init__(self, window, _('Submarine Swap'))
|
||||||
self.window = window
|
self.window = window
|
||||||
self.config = window.config
|
self.config = window.config
|
||||||
@@ -120,8 +128,9 @@ class SwapDialog(WindowModalDialog, QtEventListener):
|
|||||||
buttons = Buttons(CancelButton(self), self.ok_button)
|
buttons = Buttons(CancelButton(self), self.ok_button)
|
||||||
vbox.addLayout(buttons)
|
vbox.addLayout(buttons)
|
||||||
buttons.insertWidget(0, self.server_button)
|
buttons.insertWidget(0, self.server_button)
|
||||||
if recv_amount_sat:
|
if recv_amount_sat_or_max:
|
||||||
self.init_recv_amount(recv_amount_sat)
|
assert isinstance(recv_amount_sat_or_max, (int, str)), f"invalid {type(recv_amount_sat_or_max)=}"
|
||||||
|
self.init_recv_amount(recv_amount_sat_or_max)
|
||||||
self.update()
|
self.update()
|
||||||
self.needs_tx_update = True
|
self.needs_tx_update = True
|
||||||
|
|
||||||
@@ -321,15 +330,15 @@ class SwapDialog(WindowModalDialog, QtEventListener):
|
|||||||
self.fee_label.setText(fee_text)
|
self.fee_label.setText(fee_text)
|
||||||
self.fee_label.repaint() # macOS hack for #6269
|
self.fee_label.repaint() # macOS hack for #6269
|
||||||
|
|
||||||
def run(self, transport):
|
def run(self, transport: 'SwapServerTransport') -> bool:
|
||||||
"""Can raise InvalidSwapParameters."""
|
"""Can raise InvalidSwapParameters."""
|
||||||
if not self.exec():
|
if not self.exec():
|
||||||
return
|
return False
|
||||||
if self.is_reverse:
|
if self.is_reverse:
|
||||||
lightning_amount = self.send_amount_e.get_amount()
|
lightning_amount = self.send_amount_e.get_amount()
|
||||||
onchain_amount = self.recv_amount_e.get_amount()
|
onchain_amount = self.recv_amount_e.get_amount()
|
||||||
if lightning_amount is None or onchain_amount is None:
|
if lightning_amount is None or onchain_amount is None:
|
||||||
return
|
return False
|
||||||
sm = self.swap_manager
|
sm = self.swap_manager
|
||||||
coro = sm.reverse_swap(
|
coro = sm.reverse_swap(
|
||||||
transport=transport,
|
transport=transport,
|
||||||
@@ -342,17 +351,17 @@ class SwapDialog(WindowModalDialog, QtEventListener):
|
|||||||
funding_txid = self.window.run_coroutine_dialog(coro, _('Initiating swap...'))
|
funding_txid = self.window.run_coroutine_dialog(coro, _('Initiating swap...'))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.window.show_error(f"Reverse swap failed: {str(e)}")
|
self.window.show_error(f"Reverse swap failed: {str(e)}")
|
||||||
return
|
return False
|
||||||
self.window.on_swap_result(funding_txid, is_reverse=True)
|
self.window.on_swap_result(funding_txid, is_reverse=True)
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
lightning_amount = self.recv_amount_e.get_amount()
|
lightning_amount = self.recv_amount_e.get_amount()
|
||||||
onchain_amount = self.send_amount_e.get_amount()
|
onchain_amount = self.send_amount_e.get_amount()
|
||||||
if lightning_amount is None or onchain_amount is None:
|
if lightning_amount is None or onchain_amount is None:
|
||||||
return
|
return False
|
||||||
if lightning_amount > self.lnworker.num_sats_can_receive():
|
if lightning_amount > self.lnworker.num_sats_can_receive():
|
||||||
if not self.window.question(CANNOT_RECEIVE_WARNING):
|
if not self.window.question(CANNOT_RECEIVE_WARNING):
|
||||||
return
|
return False
|
||||||
self.window.protect(self.do_normal_swap, (transport, lightning_amount, onchain_amount))
|
self.window.protect(self.do_normal_swap, (transport, lightning_amount, onchain_amount))
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ class UTXOList(MyTreeView):
|
|||||||
def swap_coins(self, coins):
|
def swap_coins(self, coins):
|
||||||
#self.clear_coincontrol()
|
#self.clear_coincontrol()
|
||||||
self.add_to_coincontrol(coins)
|
self.add_to_coincontrol(coins)
|
||||||
self.main_window.run_swap_dialog(is_reverse=False, recv_amount_sat='!')
|
self.main_window.run_swap_dialog(is_reverse=False, recv_amount_sat_or_max='!')
|
||||||
self.clear_coincontrol()
|
self.clear_coincontrol()
|
||||||
|
|
||||||
def can_open_channel(self, coins):
|
def can_open_channel(self, coins):
|
||||||
|
|||||||
@@ -2925,10 +2925,10 @@ class LNWallet(LNWorker):
|
|||||||
# add safety margin
|
# add safety margin
|
||||||
delta += delta // 100 + 1
|
delta += delta // 100 + 1
|
||||||
if func(deltas={chan:delta}) >= amount_sat:
|
if func(deltas={chan:delta}) >= amount_sat:
|
||||||
suggestions.append((chan, delta))
|
suggestions.append((chan, int(delta)))
|
||||||
elif direction == RECEIVED and func(deltas={chan:2*delta}) >= amount_sat:
|
elif direction == RECEIVED and func(deltas={chan:2*delta}) >= amount_sat:
|
||||||
# MPP heuristics has a 0.5 slope
|
# MPP heuristics has a 0.5 slope
|
||||||
suggestions.append((chan, 2*delta))
|
suggestions.append((chan, int(2*delta)))
|
||||||
if not suggestions:
|
if not suggestions:
|
||||||
raise NotEnoughFunds
|
raise NotEnoughFunds
|
||||||
return suggestions
|
return suggestions
|
||||||
@@ -3002,7 +3002,7 @@ class LNWallet(LNWorker):
|
|||||||
return chan, swap_recv_amount
|
return chan, swap_recv_amount
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def suggest_swap_to_receive(self, amount_sat):
|
def suggest_swap_to_receive(self, amount_sat: int):
|
||||||
assert amount_sat > self.num_sats_can_receive(), f"{amount_sat=} | {self.num_sats_can_receive()=}"
|
assert amount_sat > self.num_sats_can_receive(), f"{amount_sat=} | {self.num_sats_can_receive()=}"
|
||||||
try:
|
try:
|
||||||
suggestions = self._suggest_channels_for_rebalance(RECEIVED, amount_sat)
|
suggestions = self._suggest_channels_for_rebalance(RECEIVED, amount_sat)
|
||||||
|
|||||||
Reference in New Issue
Block a user