djboi
3 years ago
committed by
GitHub
2 changed files with 191 additions and 1 deletions
@ -0,0 +1,153 @@ |
|||
from typing import TYPE_CHECKING, Optional |
|||
|
|||
from kivy.app import App |
|||
from kivy.factory import Factory |
|||
from kivy.properties import ObjectProperty |
|||
from kivy.lang import Builder |
|||
|
|||
from electrum.gui.kivy.i18n import _ |
|||
|
|||
if TYPE_CHECKING: |
|||
from ...main_window import ElectrumWindow |
|||
|
|||
from .fee_dialog import FeeSliderDialog |
|||
from electrum.gui.qt.amountedit import BTCAmountEdit |
|||
from electrum.util import format_satoshis_plain |
|||
|
|||
Builder.load_string(''' |
|||
<CPFPDialog@Popup> |
|||
title: _('Child Pays for Parent') |
|||
size_hint: 0.8, 0.8 |
|||
pos_hint: {'top':0.9} |
|||
method: 0 |
|||
BoxLayout: |
|||
orientation: 'vertical' |
|||
padding: '10dp' |
|||
GridLayout: |
|||
height: self.minimum_height |
|||
size_hint_y: None |
|||
cols: 1 |
|||
spacing: '10dp' |
|||
TopLabel: |
|||
text: |
|||
_(\ |
|||
"A CPFP is a transaction that sends an unconfirmed output back to "\ |
|||
"yourself, with a high fee. The goal is to have miners confirm "\ |
|||
"the parent transaction in order to get the fee attached to the "\ |
|||
"child transaction.") |
|||
BoxLabel: |
|||
id: total_size |
|||
text: _('Total Size') |
|||
value: '' |
|||
BoxLabel: |
|||
id: input_amount |
|||
text: _('Input amount') |
|||
value: '' |
|||
BoxLabel: |
|||
id: output_amount |
|||
text: _('Output amount') |
|||
value: '' |
|||
BoxLabel: |
|||
id: fee_for_child |
|||
text: _('Fee for child') |
|||
value: '' |
|||
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_target |
|||
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) |
|||
GridLayout: |
|||
height: self.minimum_height |
|||
size_hint_y: None |
|||
cols: 1 |
|||
spacing: '10dp' |
|||
BoxLabel: |
|||
id: total_fee |
|||
text: _('Total fee') |
|||
value: '' |
|||
BoxLabel: |
|||
id: total_feerate |
|||
text: _('Total feerate') |
|||
value: '' |
|||
Widget: |
|||
size_hint: 1, 1 |
|||
BoxLayout: |
|||
orientation: 'horizontal' |
|||
size_hint: 1, 0.5 |
|||
Button: |
|||
text: 'Cancel' |
|||
size_hint: 0.5, None |
|||
height: '48dp' |
|||
on_release: root.dismiss() |
|||
Button: |
|||
text: 'OK' |
|||
size_hint: 0.5, None |
|||
height: '48dp' |
|||
on_release: |
|||
root.dismiss() |
|||
root.on_ok() |
|||
''') |
|||
|
|||
class CPFPDialog(FeeSliderDialog, Factory.Popup): |
|||
|
|||
def __init__(self, app: 'ElectrumWindow', parent_fee, total_size, new_tx, callback): |
|||
self.app = app |
|||
self.parent_fee = parent_fee |
|||
self.total_size = total_size |
|||
self.new_tx = new_tx |
|||
self.max_fee = self.new_tx.output_value() |
|||
Factory.Popup.__init__(self) |
|||
FeeSliderDialog.__init__(self, app.electrum_config, self.ids.slider) |
|||
self.callback = callback |
|||
self.config = app.electrum_config |
|||
self.ids.total_size.value = ('%d bytes'% self.total_size) |
|||
self.ids.input_amount.value = self.app.format_amount(self.max_fee) + ' ' + self.app._get_bu() |
|||
self.update_slider() |
|||
self.update_text() |
|||
|
|||
def get_child_fee_from_total_feerate(self, fee_per_kb: Optional[int]) -> Optional[int]: |
|||
if fee_per_kb is None: |
|||
return None |
|||
fee = fee_per_kb * self.total_size / 1000 - self.parent_fee |
|||
fee = round(fee) |
|||
fee = min(self.max_fee, fee) |
|||
fee = max(self.total_size, fee) # pay at least 1 sat/byte for combined size |
|||
return fee |
|||
|
|||
def update_text(self): |
|||
target, tooltip, dyn = self.config.get_fee_target() |
|||
self.ids.fee_target.text = target |
|||
fee_per_kb = self.config.fee_per_kb() |
|||
self.fee = self.get_child_fee_from_total_feerate(fee_per_kb) |
|||
if self.fee is None: |
|||
self.ids.fee_for_child.value = "unknown" |
|||
else: |
|||
comb_fee = self.fee + self.parent_fee |
|||
comb_feerate = 1000 * comb_fee / self.total_size |
|||
self.ids.fee_for_child.value = self.app.format_amount_and_units(self.fee) |
|||
self.ids.output_amount.value = self.app.format_amount_and_units(self.max_fee-self.fee) if self.max_fee > self.fee else '' |
|||
self.ids.total_fee.value = self.app.format_amount_and_units(self.fee+self.parent_fee) |
|||
self.ids.total_feerate.value = self.app.format_fee_rate(comb_feerate) |
|||
|
|||
def on_ok(self): |
|||
fee = self.fee |
|||
self.callback(fee, self.max_fee) |
|||
|
|||
def on_slider(self, value): |
|||
self.save_config() |
|||
self.update_text() |
Loading…
Reference in new issue