Browse Source

Kivy: Show fee dialog before opening a new channel.

Remove fee and rbf from settings, as they are now always proposed
patch-4
ThomasV 4 years ago
parent
commit
2ad49bbc5b
  1. 28
      electrum/gui/kivy/uix/dialogs/confirm_tx_dialog.py
  2. 29
      electrum/gui/kivy/uix/dialogs/lightning_open_channel.py
  3. 15
      electrum/gui/kivy/uix/dialogs/settings.py
  4. 10
      electrum/gui/kivy/uix/screens.py
  5. 18
      electrum/gui/qt/main_window.py
  6. 34
      electrum/wallet.py

28
electrum/gui/kivy/uix/dialogs/confirm_tx_dialog.py

@ -97,11 +97,12 @@ Builder.load_string('''
on_release:
popup.dismiss()
Button:
id: ok_button
text: _('OK')
size_hint: 0.5, None
height: '48dp'
on_release:
root.pay()
root.on_pay(root.tx)
popup.dismiss()
''')
@ -110,33 +111,35 @@ Builder.load_string('''
class ConfirmTxDialog(FeeSliderDialog, Factory.Popup):
def __init__(self, app: 'ElectrumWindow', invoice):
def __init__(self, app: 'ElectrumWindow', amount, make_tx, on_pay, *, show_final=True):
Factory.Popup.__init__(self)
FeeSliderDialog.__init__(self, app.electrum_config, self.ids.slider)
self.app = app
self.show_final = bool(self.config.get('use_rbf'))
self.invoice = invoice
self.amount = amount
self.make_tx = make_tx
self.on_pay = on_pay
self.show_final = show_final
self.update_slider()
self.update_text()
self.update_tx()
def update_tx(self):
outputs = self.invoice.outputs
rbf = not bool(self.ids.final_cb.active) if self.show_final else False
try:
# make unsigned transaction
coins = self.app.wallet.get_spendable_coins(None)
tx = self.app.wallet.make_unsigned_transaction(coins=coins, outputs=outputs)
tx = self.make_tx(rbf)
except NotEnoughFunds:
self.warning = _("Not enough funds")
self.ids.ok_button.disabled = True
return
except Exception as e:
self.logger.exception('')
self.ids.ok_button.disabled = True
self.app.logger.exception('')
self.app.show_error(repr(e))
return
rbf = not bool(self.ids.final_cb.active) if self.show_final else False
tx.set_rbf(rbf)
amount = sum(map(lambda x: x.value, outputs)) if '!' not in [x.value for x in outputs] else tx.output_value()
self.ids.ok_button.disabled = False
amount = self.amount if self.amount != '!' else tx.output_value()
tx_size = tx.estimated_size()
fee = tx.get_fee()
feerate = Decimal(fee) / tx_size # sat/byte
@ -166,9 +169,6 @@ class ConfirmTxDialog(FeeSliderDialog, Factory.Popup):
target, tooltip, dyn = self.config.get_fee_target()
self.ids.fee_button.text = target
def pay(self):
self.app.protected(_('Send payment?'), self.app.send_screen.send_tx, (self.tx, self.invoice))
def on_fee_button(self):
fee_dialog = FeeDialog(self, self.config, self.after_fee_changed)
fee_dialog.open()

29
electrum/gui/kivy/uix/dialogs/lightning_open_channel.py

@ -12,6 +12,7 @@ from electrum.logging import Logger
from electrum.lnutil import ln_dummy_address
from .label_dialog import LabelDialog
from .confirm_tx_dialog import ConfirmTxDialog
if TYPE_CHECKING:
from ...main_window import ElectrumWindow
@ -174,20 +175,26 @@ class LightningOpenChannelDialog(Factory.Popup, Logger):
else:
conn_str = str(self.trampolines[self.pubkey])
amount = '!' if self.is_max else self.app.get_amount(self.amount)
self.app.protected('Create a new channel?', self.do_open_channel, (conn_str, amount))
self.dismiss()
def do_open_channel(self, conn_str, amount, password):
coins = self.app.wallet.get_spendable_coins(None, nonlocal_only=True)
lnworker = self.app.wallet.lnworker
try:
funding_tx = lnworker.mktx_for_open_channel(coins=coins, funding_sat=amount)
except Exception as e:
self.logger.exception("Problem opening channel")
self.app.show_error(_('Problem opening channel: ') + '\n' + repr(e))
return
coins = self.app.wallet.get_spendable_coins(None, nonlocal_only=True)
make_tx = lambda rbf: lnworker.mktx_for_open_channel(
coins=coins,
funding_sat=amount,
fee_est=None)
on_pay = lambda tx: self.app.protected('Create a new channel?', self.do_open_channel, (tx, conn_str))
d = ConfirmTxDialog(
self.app,
amount = amount,
make_tx=make_tx,
on_pay=on_pay,
show_final=False)
d.open()
def do_open_channel(self, funding_tx, conn_str, password):
# read funding_sat from tx; converts '!' to int value
funding_sat = funding_tx.output_value_for_address(ln_dummy_address())
lnworker = self.app.wallet.lnworker
try:
chan, funding_tx = lnworker.open_channel(
connect_str=conn_str,
@ -196,7 +203,7 @@ class LightningOpenChannelDialog(Factory.Popup, Logger):
push_amt_sat=0,
password=password)
except Exception as e:
self.logger.exception("Problem opening channel")
self.app.logger.exception("Problem opening channel")
self.app.show_error(_('Problem opening channel: ') + '\n' + repr(e))
return
n = chan.constraints.funding_txn_minimum_depth

15
electrum/gui/kivy/uix/dialogs/settings.py

@ -49,11 +49,6 @@ Builder.load_string('''
description: _("Base unit for Bitcoin amounts.")
action: partial(root.unit_dialog, self)
CardSeparator
SettingsItem:
title: _('Onchain fees') + ': ' + app.fee_status
description: _('Choose how transaction fees are estimated')
action: lambda dt: app.fee_dialog()
CardSeparator
SettingsItem:
status: root.fx_status()
title: _('Fiat Currency') + ': ' + self.status
@ -66,16 +61,6 @@ Builder.load_string('''
description: _("Save and synchronize your labels.")
action: partial(root.plugin_dialog, 'labels', self)
CardSeparator
SettingsItem:
status: 'ON' if app.use_rbf else 'OFF'
title: _('Replace-by-fee') + ': ' + self.status
description: _("Create replaceable transactions.")
message:
_('If you check this box, your transactions will be marked as non-final,') \
+ ' ' + _('and you will have the possibility, while they are unconfirmed, to replace them with transactions that pays higher fees.') \
+ ' ' + _('Note that some merchants do not accept non-final transactions until they are confirmed.')
action: partial(root.boolean_dialog, 'use_rbf', _('Replace by fee'), self.message)
CardSeparator
SettingsItem:
status: _('Yes') if app.use_unconfirmed else _('No')
title: _('Spend unconfirmed') + ': ' + self.status

10
electrum/gui/kivy/uix/screens.py

@ -36,7 +36,7 @@ from electrum.lnutil import RECEIVED, SENT, PaymentFailure
from electrum.logging import Logger
from .dialogs.question import Question
from .dialogs.lightning_open_channel import LightningOpenChannelDialog
from .dialogs.confirm_tx_dialog import ConfirmTxDialog
from electrum.gui.kivy import KIVY_GUI_PATH
from electrum.gui.kivy.i18n import _
@ -372,8 +372,12 @@ class SendScreen(CScreen, Logger):
threading.Thread(target=pay_thread).start()
def _do_pay_onchain(self, invoice: OnchainInvoice) -> None:
from .dialogs.confirm_tx_dialog import ConfirmTxDialog
d = ConfirmTxDialog(self.app, invoice)
outputs = invoice.outputs
amount = sum(map(lambda x: x.value, outputs)) if '!' not in [x.value for x in outputs] else '!'
coins = self.app.wallet.get_spendable_coins(None)
make_tx = lambda rbf: self.app.wallet.make_unsigned_transaction(coins=coins, outputs=outputs, rbf=rbf)
on_pay = lambda tx: self.app.protected(_('Send payment?'), self.send_tx, (tx, invoice))
d = ConfirmTxDialog(self.app, amount=amount, make_tx=make_tx, on_pay=on_pay)
d.open()
def send_tx(self, tx, invoice, password):

18
electrum/gui/qt/main_window.py

@ -1796,9 +1796,10 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
def mktx_for_open_channel(self, funding_sat):
coins = self.get_coins(nonlocal_only=True)
make_tx = lambda fee_est: self.wallet.lnworker.mktx_for_open_channel(coins=coins,
funding_sat=funding_sat,
fee_est=fee_est)
make_tx = lambda fee_est: self.wallet.lnworker.mktx_for_open_channel(
coins=coins,
funding_sat=funding_sat,
fee_est=fee_est)
return make_tx
def open_channel(self, connect_str, funding_sat, push_amt):
@ -1821,11 +1822,12 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger):
# read funding_sat from tx; converts '!' to int value
funding_sat = funding_tx.output_value_for_address(ln_dummy_address())
def task():
return self.wallet.lnworker.open_channel(connect_str=connect_str,
funding_tx=funding_tx,
funding_sat=funding_sat,
push_amt_sat=push_amt,
password=password)
return self.wallet.lnworker.open_channel(
connect_str=connect_str,
funding_tx=funding_tx,
funding_sat=funding_sat,
push_amt_sat=push_amt,
password=password)
def on_success(args):
chan, funding_tx = args
n = chan.constraints.funding_txn_minimum_depth

34
electrum/wallet.py

@ -183,8 +183,8 @@ async def sweep(
fee: int = None,
imax=100,
locktime=None,
tx_version=None
) -> PartialTransaction:
tx_version=None) -> PartialTransaction:
inputs, keypairs = await sweep_preparations(privkeys, network, imax)
total = sum(txin.value_sats() for txin in inputs)
if fee is None:
@ -1236,9 +1236,14 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
assert is_address(selected_addr), f"not valid bitcoin address: {selected_addr}"
return selected_addr
def make_unsigned_transaction(self, *, coins: Sequence[PartialTxInput],
outputs: List[PartialTxOutput], fee=None,
change_addr: str = None, is_sweep=False) -> PartialTransaction:
def make_unsigned_transaction(
self, *,
coins: Sequence[PartialTxInput],
outputs: List[PartialTxOutput],
fee=None,
change_addr: str = None,
is_sweep=False,
rbf=False) -> PartialTransaction:
if any([c.already_has_some_signatures() for c in coins]):
raise Exception("Some inputs already contain signatures!")
@ -1298,12 +1303,13 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
old_change_addrs = []
# change address. if empty, coin_chooser will set it
change_addrs = self.get_change_addresses_for_new_transaction(change_addr or old_change_addrs)
tx = coin_chooser.make_tx(coins=coins,
inputs=txi,
outputs=list(outputs) + txo,
change_addrs=change_addrs,
fee_estimator_vb=fee_estimator,
dust_threshold=self.dust_threshold())
tx = coin_chooser.make_tx(
coins=coins,
inputs=txi,
outputs=list(outputs) + txo,
change_addrs=change_addrs,
fee_estimator_vb=fee_estimator,
dust_threshold=self.dust_threshold())
else:
# "spend max" branch
# note: This *will* spend inputs with negative effective value (if there are any).
@ -1325,7 +1331,7 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
# Timelock tx to current height.
tx.locktime = get_locktime_for_new_transaction(self.network)
tx.set_rbf(False) # caller can set RBF manually later
tx.set_rbf(rbf)
tx.add_info_from_wallet(self)
run_hook('make_unsigned_transaction', self, tx)
return tx
@ -1340,8 +1346,8 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
coins=coins,
outputs=outputs,
fee=fee,
change_addr=change_addr)
tx.set_rbf(rbf)
change_addr=change_addr,
rbf=rbf)
if tx_version is not None:
tx.version = tx_version
if sign:

Loading…
Cancel
Save