commit 10fa11267d9e317431ea7cb1226776580b3230a8
parent 1b1c7d1f9e836acef8b8ee3db53cde12deacc756
Author: ThomasV <thomasv@electrum.org>
Date: Fri, 22 May 2020 12:49:41 +0200
qt: separate module for swap_dialog
Diffstat:
2 files changed, 134 insertions(+), 18 deletions(-)
diff --git a/electrum/gui/qt/channels_list.py b/electrum/gui/qt/channels_list.py
@@ -369,21 +369,6 @@ class ChannelsList(MyTreeView):
self.parent.open_channel(connect_str, funding_sat, 0)
def swap_dialog(self):
- lnworker = self.parent.wallet.lnworker
- d = WindowModalDialog(self.parent, _('Reverse Submarine Swap'))
- vbox = QVBoxLayout(d)
- amount_e = BTCAmountEdit(self.parent.get_decimal_point)
- h = QGridLayout()
- h.addWidget(QLabel('Amount'), 3, 0)
- h.addWidget(amount_e, 3, 1)
- vbox.addLayout(h)
- ok_button = OkButton(d)
- ok_button.setDefault(True)
- vbox.addLayout(Buttons(CancelButton(d), ok_button))
- if not d.exec_():
- return
- from electrum.submarine_swaps import reverse_swap
- import asyncio
- amount_sat = amount_e.get_amount()
- coro = reverse_swap(amount_sat, self.parent.wallet, self.parent.network)
- fut = asyncio.run_coroutine_threadsafe(coro, self.parent.network.asyncio_loop)
+ from .swap_dialog import SwapDialog
+ d = SwapDialog(self.parent)
+ d.run()
diff --git a/electrum/gui/qt/swap_dialog.py b/electrum/gui/qt/swap_dialog.py
@@ -0,0 +1,131 @@
+from PyQt5 import QtCore, QtGui
+from PyQt5.QtCore import Qt
+from PyQt5.QtWidgets import (QMenu, QHBoxLayout, QLabel, QVBoxLayout, QGridLayout, QLineEdit,
+ QPushButton, QAbstractItemView, QComboBox)
+from PyQt5.QtGui import QFont, QStandardItem, QBrush
+
+from electrum.util import bh2u, NotEnoughFunds, NoDynamicFeeEstimates
+from electrum.i18n import _
+from electrum.lnchannel import AbstractChannel, PeerState
+from electrum.wallet import Abstract_Wallet
+from electrum.lnutil import LOCAL, REMOTE, format_short_channel_id, LN_MAX_FUNDING_SAT
+from electrum.lnworker import LNWallet
+
+from .util import (MyTreeView, WindowModalDialog, Buttons, OkButton, CancelButton,
+ EnterButton, WaitingDialog, MONOSPACE_FONT, ColorScheme)
+from .amountedit import BTCAmountEdit, FreezableLineEdit
+
+
+from electrum import submarine_swaps as ss
+import asyncio
+from .util import read_QIcon
+
+
+class SwapDialog(WindowModalDialog):
+
+ def __init__(self, window):
+ WindowModalDialog.__init__(self, window, _('Submarine Swap'))
+ self.window = window
+ self.network = window.network
+ self.normal_fee = 0
+ self.lockup_fee = 0
+ self.claim_fee = 0
+ self.percentage = 0
+ vbox = QVBoxLayout(self)
+ self.send_amount_e = BTCAmountEdit(self.window.get_decimal_point)
+ self.recv_amount_e = BTCAmountEdit(self.window.get_decimal_point)
+ self.send_button = QPushButton('')
+ self.recv_button = QPushButton('')
+ self.is_reverse = False
+ self.toggle_direction()
+ self.send_amount_e.follows = False
+ self.recv_amount_e.follows = False
+ self.send_button.clicked.connect(self.toggle_direction)
+ self.recv_button.clicked.connect(self.toggle_direction)
+ self.send_amount_e.textChanged.connect(self.on_send_edited)
+ self.recv_amount_e.textChanged.connect(self.on_recv_edited)
+ h = QGridLayout()
+ h.addWidget(QLabel(_('You send')+':'), 2, 0)
+ h.addWidget(self.send_amount_e, 2, 1)
+ h.addWidget(self.send_button, 2, 2)
+ h.addWidget(QLabel(_('You receive')+':'), 3, 0)
+ h.addWidget(self.recv_amount_e, 3, 1)
+ h.addWidget(self.recv_button, 3, 2)
+ self.normal_fee_label = QLabel()
+ self.lockup_fee_label = QLabel()
+ self.claim_fee_label = QLabel()
+ h.addWidget(self.normal_fee_label, 4, 0, 1, 2)
+ h.addWidget(self.lockup_fee_label, 5, 0, 1, 2)
+ h.addWidget(self.claim_fee_label, 6, 0, 1, 2)
+ vbox.addLayout(h)
+ ok_button = OkButton(self)
+ ok_button.setDefault(True)
+ vbox.addLayout(Buttons(CancelButton(self), ok_button))
+ # todo: add a fee slider for the claim tx
+
+ def toggle_direction(self):
+ self.is_reverse = not self.is_reverse
+ self.send_button.setIcon(read_QIcon("lightning.png" if self.is_reverse else "bitcoin.png"))
+ self.recv_button.setIcon(read_QIcon("lightning.png" if not self.is_reverse else "bitcoin.png"))
+
+ def on_send_edited(self):
+ if self.send_amount_e.follows:
+ return
+ amount = self.send_amount_e.get_amount()
+ self.recv_amount_e.follows = True
+ self.recv_amount_e.setAmount(self.get_recv_amount(amount))
+ self.recv_amount_e.follows = False
+
+ def on_recv_edited(self):
+ if self.recv_amount_e.follows:
+ return
+ amount = self.recv_amount_e.get_amount()
+ self.send_amount_e.follows = True
+ self.send_amount_e.setAmount(self.get_send_amount(amount))
+ self.send_amount_e.follows = False
+
+ def get_pairs(self):
+ fut = asyncio.run_coroutine_threadsafe(ss.get_pairs(self.network), self.network.asyncio_loop)
+ pairs = fut.result()
+ print(pairs)
+ fees = pairs['pairs']['BTC/BTC']['fees']
+ self.percentage = fees['percentage']
+ self.normal_fee = fees['minerFees']['baseAsset']['normal']
+ self.lockup_fee = fees['minerFees']['baseAsset']['reverse']['lockup']
+ self.claim_fee = fees['minerFees']['baseAsset']['reverse']['claim']
+ self.normal_fee_label.setText(f'normal fee: {self.normal_fee}')
+ self.lockup_fee_label.setText(f'lockup fee: {self.lockup_fee}')
+ self.claim_fee_label.setText(f'claim fee: {self.claim_fee}')
+
+ def get_recv_amount(self, send_amount):
+ if send_amount is None:
+ return
+ x = send_amount * (100 - self.percentage) / 100
+ if self.is_reverse:
+ x -= self.lockup_fee
+ x -= self.claim_fee
+ else:
+ x -= self.normal_fee
+ return x
+
+ def get_send_amount(self, recv_amount):
+ if not recv_amount:
+ return
+ x = recv_amount * (100 + self.percentage) / 100
+ if self.is_reverse:
+ x += self.lockup_fee
+ x += self.claim_fee
+ else:
+ x += self.normal_fee
+ return x
+
+ def run(self):
+ self.get_pairs()
+ if not self.exec_():
+ return
+ amount_sat = self.send_amount_e.get_amount()
+ if self.is_reverse:
+ coro = ss.reverse_swap(amount_sat, self.window.wallet, self.network)
+ asyncio.run_coroutine_threadsafe(coro, self.network.asyncio_loop)
+ else:
+ pass