Browse Source

Qt swaps_dialog: do not use side effects to update tx.

Use the app timer instead, so that the tx is not recomputed
on every slider move (like in ConfirmTxDialog).

A similar modification is needed for QML. I started with
Qt in order to get a sense of how it should be done.
master
ThomasV 3 years ago
parent
commit
c3a0f9c078
  1. 85
      electrum/gui/qt/swap_dialog.py

85
electrum/gui/qt/swap_dialog.py

@ -38,7 +38,6 @@ class SwapDialog(WindowModalDialog):
self.lnworker = self.window.wallet.lnworker self.lnworker = self.window.wallet.lnworker
self.swap_manager = self.lnworker.swap_manager self.swap_manager = self.lnworker.swap_manager
self.network = window.network self.network = window.network
self.tx = None # for the forward-swap only
self.channels = channels self.channels = channels
self.is_reverse = is_reverse if is_reverse is not None else True self.is_reverse = is_reverse if is_reverse is not None else True
vbox = QVBoxLayout(self) vbox = QVBoxLayout(self)
@ -102,6 +101,14 @@ class SwapDialog(WindowModalDialog):
if recv_amount_sat: if recv_amount_sat:
self.init_recv_amount(recv_amount_sat) self.init_recv_amount(recv_amount_sat)
self.update() self.update()
self.needs_tx_update = True
self.window.gui_object.timer.timeout.connect(self.timer_actions)
def timer_actions(self):
if self.needs_tx_update:
self.update_tx()
self.update_ok_button()
self.needs_tx_update = False
def init_recv_amount(self, recv_amount_sat): def init_recv_amount(self, recv_amount_sat):
if recv_amount_sat == '!': if recv_amount_sat == '!':
@ -137,32 +144,23 @@ class SwapDialog(WindowModalDialog):
if self.is_reverse: if self.is_reverse:
self._spend_max_reverse_swap() self._spend_max_reverse_swap()
else: else:
self._spend_max_forward_swap() # spend_max_forward_swap will be called in update_tx
pass
else: else:
self.send_amount_e.setAmount(None) self.send_amount_e.setAmount(None)
self.update_fee() self.needs_tx_update = True
self.update_ok_button()
def uncheck_max(self): def uncheck_max(self):
self.max_button.setChecked(False) self.max_button.setChecked(False)
self.update() self.update()
def _spend_max_forward_swap(self): def _spend_max_forward_swap(self, tx):
self._update_tx('!') if tx:
if self.tx: amount = tx.output_value_for_address(ln_dummy_address())
amount = self.tx.output_value_for_address(ln_dummy_address()) self.send_amount_e.setAmount(amount)
max_amt = self.swap_manager.max_amount_forward_swap() else:
if max_amt is None: self.send_amount_e.setAmount(None)
self.send_amount_e.setAmount(None) self.max_button.setChecked(False)
self.max_button.setChecked(False)
return
if amount > max_amt:
amount = max_amt
self._update_tx(amount)
if self.tx:
amount = self.tx.output_value_for_address(ln_dummy_address())
assert amount <= max_amt
self.send_amount_e.setAmount(amount)
def _spend_max_reverse_swap(self): def _spend_max_reverse_swap(self):
amount = min(self.lnworker.num_sats_can_send(), self.swap_manager.get_max_amount()) amount = min(self.lnworker.num_sats_can_send(), self.swap_manager.get_max_amount())
@ -185,9 +183,7 @@ class SwapDialog(WindowModalDialog):
self.recv_amount_e.setStyleSheet(ColorScheme.BLUE.as_stylesheet()) self.recv_amount_e.setStyleSheet(ColorScheme.BLUE.as_stylesheet())
self.recv_amount_e.follows = False self.recv_amount_e.follows = False
self.send_follows = False self.send_follows = False
self._update_tx(send_amount) self.needs_tx_update = True
self.update_fee()
self.update_ok_button()
def on_recv_edited(self): def on_recv_edited(self):
if self.recv_amount_e.follows: if self.recv_amount_e.follows:
@ -202,9 +198,7 @@ class SwapDialog(WindowModalDialog):
self.send_amount_e.setStyleSheet(ColorScheme.BLUE.as_stylesheet()) self.send_amount_e.setStyleSheet(ColorScheme.BLUE.as_stylesheet())
self.send_amount_e.follows = False self.send_amount_e.follows = False
self.send_follows = True self.send_follows = True
self._update_tx(send_amount) self.needs_tx_update = True
self.update_fee()
self.update_ok_button()
def update(self): def update(self):
from .util import IconLabel from .util import IconLabel
@ -219,17 +213,15 @@ class SwapDialog(WindowModalDialog):
server_fee_str = '%.2f'%sm.percentage + '% + ' + self.window.format_amount(server_mining_fee) + ' ' + self.window.base_unit() server_fee_str = '%.2f'%sm.percentage + '% + ' + self.window.format_amount(server_mining_fee) + ' ' + self.window.base_unit()
self.server_fee_label.setText(server_fee_str) self.server_fee_label.setText(server_fee_str)
self.server_fee_label.repaint() # macOS hack for #6269 self.server_fee_label.repaint() # macOS hack for #6269
self.update_tx() self.needs_tx_update = True
self.update_fee()
self.update_ok_button()
def update_fee(self): def update_fee(self, tx):
"""Updates self.fee_label. No other side-effects.""" """Updates self.fee_label. No other side-effects."""
if self.is_reverse: if self.is_reverse:
sm = self.swap_manager sm = self.swap_manager
fee = sm.get_claim_fee() fee = sm.get_claim_fee()
else: else:
fee = self.tx.get_fee() if self.tx else None fee = tx.get_fee() if tx else None
fee_text = self.window.format_amount(fee) + ' ' + self.window.base_unit() if fee else '' fee_text = self.window.format_amount(fee) + ' ' + self.window.base_unit() if fee else ''
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
@ -261,42 +253,45 @@ class SwapDialog(WindowModalDialog):
def update_tx(self): def update_tx(self):
if self.is_reverse: if self.is_reverse:
self.update_fee(None)
return return
is_max = self.max_button.isChecked() is_max = self.max_button.isChecked()
if is_max: if is_max:
self._spend_max_forward_swap() tx = self._create_tx('!')
self._spend_max_forward_swap(tx)
else: else:
onchain_amount = self.send_amount_e.get_amount() onchain_amount = self.send_amount_e.get_amount()
self._update_tx(onchain_amount) tx = self._create_tx(onchain_amount)
self.update_fee(tx)
def _update_tx(self, onchain_amount): def _create_tx(self, onchain_amount):
"""Updates self.tx. No other side-effects."""
if self.is_reverse: if self.is_reverse:
return return
if onchain_amount is None: if onchain_amount is None:
self.tx = None
return return
outputs = [PartialTxOutput.from_address_and_value(ln_dummy_address(), onchain_amount)]
coins = self.window.get_coins() coins = self.window.get_coins()
if onchain_amount == '!':
max_amount = sum(c.value_sats() for c in coins)
max_swap_amount = self.swap_manager.max_amount_forward_swap()
if max_amount > max_swap_amount:
onchain_amount = max_swap_amount
outputs = [PartialTxOutput.from_address_and_value(ln_dummy_address(), onchain_amount)]
try: try:
self.tx = self.window.wallet.make_unsigned_transaction( tx = self.window.wallet.make_unsigned_transaction(
coins=coins, coins=coins,
outputs=outputs) outputs=outputs)
except (NotEnoughFunds, NoDynamicFeeEstimates) as e: except (NotEnoughFunds, NoDynamicFeeEstimates) as e:
self.tx = None return
return tx
def update_ok_button(self): def update_ok_button(self):
"""Updates self.ok_button. No other side-effects.""" """Updates self.ok_button. No other side-effects."""
send_amount = self.send_amount_e.get_amount() send_amount = self.send_amount_e.get_amount()
recv_amount = self.recv_amount_e.get_amount() recv_amount = self.recv_amount_e.get_amount()
self.ok_button.setEnabled( self.ok_button.setEnabled(bool(send_amount) and bool(recv_amount))
(send_amount is not None)
and (recv_amount is not None)
and (self.tx is not None or self.is_reverse)
)
def do_normal_swap(self, lightning_amount, onchain_amount, password): def do_normal_swap(self, lightning_amount, onchain_amount, password):
tx = self.tx tx = self._create_tx(onchain_amount)
assert tx assert tx
coro = self.swap_manager.normal_swap( coro = self.swap_manager.normal_swap(
lightning_amount_sat=lightning_amount, lightning_amount_sat=lightning_amount,

Loading…
Cancel
Save