You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

182 lines
5.7 KiB

from decimal import Decimal
from typing import TYPE_CHECKING
from kivy.app import App
from kivy.factory import Factory
from kivy.properties import ObjectProperty
from kivy.lang import Builder
from kivy.uix.checkbox import CheckBox
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.clock import Clock
from electrum.gui.kivy.i18n import _
from electrum.plugin import run_hook
from electrum.util import NotEnoughFunds
from .fee_dialog import FeeSliderDialog
if TYPE_CHECKING:
from electrum.gui.kivy.main_window import ElectrumWindow
Builder.load_string('''
<ConfirmTxDialog@Popup>
id: popup
title: _('Confirm Payment')
message: ''
warning: ''
extra_fee: ''
show_final: False
size_hint: 0.8, 0.8
pos_hint: {'top':0.9}
method: 0
BoxLayout:
orientation: 'vertical'
BoxLayout:
orientation: 'horizontal'
size_hint: 1, 0.5
Label:
text: _('Amount to be sent:')
Label:
id: amount_label
text: ''
BoxLayout:
orientation: 'horizontal'
size_hint: 1, 0.5
Label:
text: _('Mining fee:')
Label:
id: fee_label
text: ''
BoxLayout:
orientation: 'horizontal'
size_hint: 1, (0.5 if root.extra_fee else 0.01)
Label:
text: _('Additional fees') if root.extra_fee else ''
Label:
text: root.extra_fee
BoxLayout:
orientation: 'horizontal'
size_hint: 1, 0.5
Label:
text: _('Fee rate:')
Label:
id: feerate_label
text: ''
BoxLayout:
orientation: 'horizontal'
size_hint: 1, 0.5
Label:
text: _('Target') + ' (%s):' % (_('mempool') if root.method == 2 else _('ETA') if root.method == 1 else _('static'))
Button:
id: fee_button
text: ''
background_color: (0,0,0,0)
bold: True
on_release:
root.method = (root.method + 1) % 3
root.update_slider()
root.on_slider(root.slider.value)
Slider:
id: slider
range: 0, 4
step: 1
on_value: root.on_slider(self.value)
BoxLayout:
orientation: 'horizontal'
size_hint: 1, 0.2
Label:
text: _('Final')
opacity: int(root.show_final)
CheckBox:
id: final_cb
opacity: int(root.show_final)
disabled: not root.show_final
on_release: root.update_tx()
Label:
text: root.warning
text_size: self.width, None
Widget:
size_hint: 1, 0.5
BoxLayout:
orientation: 'horizontal'
size_hint: 1, 0.5
Button:
text: _('Cancel')
size_hint: 0.5, None
height: '48dp'
on_release:
popup.dismiss()
Button:
id: ok_button
text: _('OK')
size_hint: 0.5, None
height: '48dp'
on_release:
root.on_pay(root.tx)
popup.dismiss()
''')
class ConfirmTxDialog(FeeSliderDialog, Factory.Popup):
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.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):
rbf = not bool(self.ids.final_cb.active) if self.show_final else False
try:
# make unsigned transaction
tx = self.make_tx(rbf)
except NotEnoughFunds:
self.warning = _("Not enough funds")
self.ids.ok_button.disabled = True
return
except Exception as e:
self.ids.ok_button.disabled = True
self.app.logger.exception('')
self.app.show_error(repr(e))
return
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()
self.ids.fee_label.text = self.app.format_amount_and_units(fee)
feerate = Decimal(fee) / tx_size # sat/byte
self.ids.feerate_label.text = f'{feerate:.1f} sat/B'
self.ids.amount_label.text = self.app.format_amount_and_units(amount)
x_fee = run_hook('get_tx_extra_fee', self.app.wallet, tx)
if x_fee:
x_fee_address, x_fee_amount = x_fee
self.extra_fee = self.app.format_amount_and_units(x_fee_amount)
else:
self.extra_fee = ''
fee_warning_tuple = self.app.wallet.get_tx_fee_warning(
invoice_amt=amount, tx_size=tx_size, fee=fee)
if fee_warning_tuple:
allow_send, long_warning, short_warning = fee_warning_tuple
self.warning = long_warning
else:
self.warning = ''
self.tx = tx
def on_slider(self, value):
self.save_config()
self.update_text()
Clock.schedule_once(lambda dt: self.update_tx())
def update_text(self):
target, tooltip, dyn = self.config.get_fee_target()
self.ids.fee_button.text = target