mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-09-20 01:19:49 +00:00
submarine_swaps: add fee slider, improve gui
This commit is contained in:
parent
ac3ec19d2d
commit
6b36c59ab0
2 changed files with 71 additions and 20 deletions
|
@ -14,7 +14,8 @@ from electrum.lnworker import LNWallet
|
||||||
from .util import (MyTreeView, WindowModalDialog, Buttons, OkButton, CancelButton,
|
from .util import (MyTreeView, WindowModalDialog, Buttons, OkButton, CancelButton,
|
||||||
EnterButton, WaitingDialog, MONOSPACE_FONT, ColorScheme)
|
EnterButton, WaitingDialog, MONOSPACE_FONT, ColorScheme)
|
||||||
from .amountedit import BTCAmountEdit, FreezableLineEdit
|
from .amountedit import BTCAmountEdit, FreezableLineEdit
|
||||||
|
from .util import WWLabel
|
||||||
|
from .fee_slider import FeeSlider
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from .util import read_QIcon
|
from .util import read_QIcon
|
||||||
|
@ -25,19 +26,22 @@ class SwapDialog(WindowModalDialog):
|
||||||
def __init__(self, window):
|
def __init__(self, window):
|
||||||
WindowModalDialog.__init__(self, window, _('Submarine Swap'))
|
WindowModalDialog.__init__(self, window, _('Submarine Swap'))
|
||||||
self.window = window
|
self.window = window
|
||||||
|
self.config = window.config
|
||||||
self.swap_manager = self.window.wallet.lnworker.swap_manager
|
self.swap_manager = self.window.wallet.lnworker.swap_manager
|
||||||
self.network = window.network
|
self.network = window.network
|
||||||
self.normal_fee = 0
|
self.normal_fee = 0
|
||||||
self.lockup_fee = 0
|
self.lockup_fee = 0
|
||||||
self.claim_fee = 0
|
self.claim_fee = self.swap_manager.get_tx_fee()
|
||||||
self.percentage = 0
|
self.percentage = 0
|
||||||
|
self.min_amount = 0
|
||||||
|
self.max_amount = 0
|
||||||
vbox = QVBoxLayout(self)
|
vbox = QVBoxLayout(self)
|
||||||
|
vbox.addWidget(WWLabel('Swap lightning funds for on-chain funds if you need to increase your receiving capacity. This service is powered by the Boltz backend.'))
|
||||||
self.send_amount_e = BTCAmountEdit(self.window.get_decimal_point)
|
self.send_amount_e = BTCAmountEdit(self.window.get_decimal_point)
|
||||||
self.recv_amount_e = BTCAmountEdit(self.window.get_decimal_point)
|
self.recv_amount_e = BTCAmountEdit(self.window.get_decimal_point)
|
||||||
self.send_button = QPushButton('')
|
self.send_button = QPushButton('')
|
||||||
self.recv_button = QPushButton('')
|
self.recv_button = QPushButton('')
|
||||||
self.is_reverse = False
|
self.is_reverse = True
|
||||||
self.toggle_direction()
|
|
||||||
self.send_amount_e.follows = False
|
self.send_amount_e.follows = False
|
||||||
self.recv_amount_e.follows = False
|
self.recv_amount_e.follows = False
|
||||||
self.send_button.clicked.connect(self.toggle_direction)
|
self.send_button.clicked.connect(self.toggle_direction)
|
||||||
|
@ -51,22 +55,47 @@ class SwapDialog(WindowModalDialog):
|
||||||
h.addWidget(QLabel(_('You receive')+':'), 3, 0)
|
h.addWidget(QLabel(_('You receive')+':'), 3, 0)
|
||||||
h.addWidget(self.recv_amount_e, 3, 1)
|
h.addWidget(self.recv_amount_e, 3, 1)
|
||||||
h.addWidget(self.recv_button, 3, 2)
|
h.addWidget(self.recv_button, 3, 2)
|
||||||
self.normal_fee_label = QLabel()
|
self.min_label = QLabel('')
|
||||||
self.lockup_fee_label = QLabel()
|
self.max_label = QLabel('')
|
||||||
self.claim_fee_label = QLabel()
|
self.fee_label = QLabel()
|
||||||
h.addWidget(self.normal_fee_label, 4, 0, 1, 2)
|
self.percentage_label = QLabel()
|
||||||
h.addWidget(self.lockup_fee_label, 5, 0, 1, 2)
|
h.addWidget(QLabel(_('Min amount')+':'), 4, 0)
|
||||||
h.addWidget(self.claim_fee_label, 6, 0, 1, 2)
|
h.addWidget(self.min_label, 4, 1)
|
||||||
|
h.addWidget(QLabel(_('Max amount')+':'), 5, 0)
|
||||||
|
h.addWidget(self.max_label, 5, 1)
|
||||||
|
h.addWidget(QLabel(_('Mining fee')+':'), 4, 2)
|
||||||
|
h.addWidget(self.fee_label, 4, 3)
|
||||||
|
h.addWidget(QLabel(_('Swap fee')+':'), 5, 2)
|
||||||
|
h.addWidget(self.percentage_label, 5, 3)
|
||||||
vbox.addLayout(h)
|
vbox.addLayout(h)
|
||||||
|
fee_slider = FeeSlider(self.window, self.config, self.fee_slider_callback)
|
||||||
|
fee_slider.update()
|
||||||
|
h.addWidget(fee_slider, 6, 1)
|
||||||
|
vbox.addStretch(1)
|
||||||
ok_button = OkButton(self)
|
ok_button = OkButton(self)
|
||||||
ok_button.setDefault(True)
|
ok_button.setDefault(True)
|
||||||
vbox.addLayout(Buttons(CancelButton(self), ok_button))
|
vbox.addLayout(Buttons(CancelButton(self), ok_button))
|
||||||
# todo: add a fee slider for the claim tx
|
self.update()
|
||||||
|
|
||||||
|
def fee_slider_callback(self, dyn, pos, fee_rate):
|
||||||
|
if dyn:
|
||||||
|
if self.config.use_mempool_fees():
|
||||||
|
self.config.set_key('depth_level', pos, False)
|
||||||
|
else:
|
||||||
|
self.config.set_key('fee_level', pos, False)
|
||||||
|
else:
|
||||||
|
self.config.set_key('fee_per_kb', fee_rate, False)
|
||||||
|
# read claim_fee from config
|
||||||
|
self.claim_fee = self.swap_manager.get_tx_fee()
|
||||||
|
self.on_send_edited()
|
||||||
|
#self.on_recv_edited()
|
||||||
|
self.update()
|
||||||
|
|
||||||
def toggle_direction(self):
|
def toggle_direction(self):
|
||||||
self.is_reverse = not self.is_reverse
|
self.is_reverse = not self.is_reverse
|
||||||
self.send_button.setIcon(read_QIcon("lightning.png" if self.is_reverse else "bitcoin.png"))
|
self.send_amount_e.setAmount(None)
|
||||||
self.recv_button.setIcon(read_QIcon("lightning.png" if not self.is_reverse else "bitcoin.png"))
|
self.recv_amount_e.setAmount(None)
|
||||||
|
self.update()
|
||||||
|
|
||||||
def on_send_edited(self):
|
def on_send_edited(self):
|
||||||
if self.send_amount_e.follows:
|
if self.send_amount_e.follows:
|
||||||
|
@ -92,20 +121,40 @@ class SwapDialog(WindowModalDialog):
|
||||||
self.percentage = fees['percentage']
|
self.percentage = fees['percentage']
|
||||||
self.normal_fee = fees['minerFees']['baseAsset']['normal']
|
self.normal_fee = fees['minerFees']['baseAsset']['normal']
|
||||||
self.lockup_fee = fees['minerFees']['baseAsset']['reverse']['lockup']
|
self.lockup_fee = fees['minerFees']['baseAsset']['reverse']['lockup']
|
||||||
self.claim_fee = fees['minerFees']['baseAsset']['reverse']['claim']
|
#self.claim_fee = fees['minerFees']['baseAsset']['reverse']['claim']
|
||||||
self.normal_fee_label.setText(f'normal fee: {self.normal_fee}')
|
limits = pairs['pairs']['BTC/BTC']['limits']
|
||||||
self.lockup_fee_label.setText(f'lockup fee: {self.lockup_fee}')
|
self.min_amount = limits['minimal']
|
||||||
self.claim_fee_label.setText(f'claim fee: {self.claim_fee}')
|
self.max_amount = limits['maximal']
|
||||||
|
self.update()
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
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"))
|
||||||
|
fee = self.lockup_fee + self.claim_fee if self.is_reverse else self.normal_fee
|
||||||
|
self.fee_label.setText(self.window.format_amount(fee) + ' ' + self.window.base_unit())
|
||||||
|
self.percentage_label.setText('%.2f'%self.percentage + '%')
|
||||||
|
self.min_label.setText(self.window.format_amount(self.min_amount) + ' ' + self.window.base_unit())
|
||||||
|
self.max_label.setText(self.window.format_amount(self.max_amount) + ' ' + self.window.base_unit())
|
||||||
|
|
||||||
|
def set_minimum(self):
|
||||||
|
self.send_amount_e.setAmount(self.min_amount)
|
||||||
|
|
||||||
|
def set_maximum(self):
|
||||||
|
self.send_amount_e.setAmount(self.max_amount)
|
||||||
|
|
||||||
def get_recv_amount(self, send_amount):
|
def get_recv_amount(self, send_amount):
|
||||||
if send_amount is None:
|
if send_amount is None:
|
||||||
return
|
return
|
||||||
|
if send_amount < self.min_amount or send_amount > self.max_amount:
|
||||||
|
return
|
||||||
x = send_amount * (100 - self.percentage) / 100
|
x = send_amount * (100 - self.percentage) / 100
|
||||||
if self.is_reverse:
|
if self.is_reverse:
|
||||||
x -= self.lockup_fee
|
x -= self.lockup_fee
|
||||||
x -= self.claim_fee
|
x -= self.claim_fee
|
||||||
else:
|
else:
|
||||||
x -= self.normal_fee
|
x -= self.normal_fee
|
||||||
|
if x < 0:
|
||||||
|
return
|
||||||
return x
|
return x
|
||||||
|
|
||||||
def get_send_amount(self, recv_amount):
|
def get_send_amount(self, recv_amount):
|
||||||
|
|
|
@ -65,7 +65,7 @@ def create_claim_tx(txin, witness_script, preimage, privkey:bytes, address, amou
|
||||||
txin.script_sig = bytes.fromhex(push_script(txin.redeem_script.hex()))
|
txin.script_sig = bytes.fromhex(push_script(txin.redeem_script.hex()))
|
||||||
txin.witness_script = witness_script
|
txin.witness_script = witness_script
|
||||||
txout = PartialTxOutput(scriptpubkey=bytes.fromhex(address_to_script(address)), value=amount_sat)
|
txout = PartialTxOutput(scriptpubkey=bytes.fromhex(address_to_script(address)), value=amount_sat)
|
||||||
tx = PartialTransaction.from_io([txin], [txout], version=2, locktime=locktime)
|
tx = PartialTransaction.from_io([txin], [txout], version=2, locktime=(None if preimage else locktime))
|
||||||
tx.set_rbf(True)
|
tx.set_rbf(True)
|
||||||
sig = bytes.fromhex(tx.sign_txin(0, privkey))
|
sig = bytes.fromhex(tx.sign_txin(0, privkey))
|
||||||
witness = [sig, preimage, witness_script]
|
witness = [sig, preimage, witness_script]
|
||||||
|
@ -87,8 +87,7 @@ class SwapManager(Logger):
|
||||||
self.logger.info(f'height not reached for refund {lockup_address} {delta}, {locktime}')
|
self.logger.info(f'height not reached for refund {lockup_address} {delta}, {locktime}')
|
||||||
return
|
return
|
||||||
for txin in list(utxos.values()):
|
for txin in list(utxos.values()):
|
||||||
fee = self.lnwatcher.config.estimate_fee(136, allow_fallback_to_static_rates=True)
|
amount_sat = txin._trusted_value_sats - self.get_tx_fee()
|
||||||
amount_sat = txin._trusted_value_sats - fee
|
|
||||||
if amount_sat < dust_threshold():
|
if amount_sat < dust_threshold():
|
||||||
self.logger.info('utxo value below dust threshold')
|
self.logger.info('utxo value below dust threshold')
|
||||||
continue
|
continue
|
||||||
|
@ -96,6 +95,9 @@ class SwapManager(Logger):
|
||||||
tx = create_claim_tx(txin, redeem_script, preimage, privkey, address, amount_sat, locktime)
|
tx = create_claim_tx(txin, redeem_script, preimage, privkey, address, amount_sat, locktime)
|
||||||
await self.network.broadcast_transaction(tx)
|
await self.network.broadcast_transaction(tx)
|
||||||
|
|
||||||
|
def get_tx_fee(self):
|
||||||
|
return self.lnwatcher.config.estimate_fee(136, allow_fallback_to_static_rates=True)
|
||||||
|
|
||||||
def __init__(self, wallet: 'Abstract_Wallet', network:'Network'):
|
def __init__(self, wallet: 'Abstract_Wallet', network:'Network'):
|
||||||
Logger.__init__(self)
|
Logger.__init__(self)
|
||||||
self.network = network
|
self.network = network
|
||||||
|
|
Loading…
Add table
Reference in a new issue