mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-09-04 04:45:16 +00:00
dynamic fees: define fee levels using expected confirmation times
This commit is contained in:
parent
352cdd7f5a
commit
2cf4795250
5 changed files with 42 additions and 34 deletions
|
@ -34,14 +34,6 @@ Builder.load_string('''
|
||||||
CheckBox:
|
CheckBox:
|
||||||
id: dynfees
|
id: dynfees
|
||||||
on_active: root.on_checkbox(self.active)
|
on_active: root.on_checkbox(self.active)
|
||||||
BoxLayout:
|
|
||||||
orientation: 'horizontal'
|
|
||||||
size_hint: 1, None
|
|
||||||
Label:
|
|
||||||
id: reco
|
|
||||||
font_size: '6pt'
|
|
||||||
text_size: self.size
|
|
||||||
text: ''
|
|
||||||
Widget:
|
Widget:
|
||||||
size_hint: 1, 1
|
size_hint: 1, 1
|
||||||
BoxLayout:
|
BoxLayout:
|
||||||
|
@ -77,9 +69,6 @@ class FeeDialog(Factory.Popup):
|
||||||
self.update_slider()
|
self.update_slider()
|
||||||
self.update_text()
|
self.update_text()
|
||||||
|
|
||||||
if self.app.network and self.app.network.fee:
|
|
||||||
self.ids.reco.text = _('Recommended fee for inclusion in the next two blocks') + ': ' + self.app.format_amount_and_units(self.app.network.fee) +'/kb'
|
|
||||||
|
|
||||||
def update_text(self):
|
def update_text(self):
|
||||||
self.ids.fee_per_kb.text = self.get_fee_text()
|
self.ids.fee_per_kb.text = self.get_fee_text()
|
||||||
|
|
||||||
|
@ -96,7 +85,12 @@ class FeeDialog(Factory.Popup):
|
||||||
|
|
||||||
def get_fee_text(self):
|
def get_fee_text(self):
|
||||||
if self.ids.dynfees.active:
|
if self.ids.dynfees.active:
|
||||||
return fee_levels[self.fee_level] + ' (%d%%)'% (100 * (self.fee_level + 1)/3)
|
tooltip = fee_levels[self.fee_level]
|
||||||
|
if self.app.network:
|
||||||
|
dynfee = self.app.network.dynfee(self.fee_level)
|
||||||
|
if dynfee:
|
||||||
|
tooltip += '\n' + (self.app.format_amount_and_units(dynfee)) + '/kB'
|
||||||
|
return tooltip
|
||||||
else:
|
else:
|
||||||
return self.app.format_amount_and_units(self.static_fee) + '/kB'
|
return self.app.format_amount_and_units(self.static_fee) + '/kB'
|
||||||
|
|
||||||
|
|
|
@ -925,7 +925,10 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
|
||||||
def slider_moved():
|
def slider_moved():
|
||||||
from electrum.util import fee_levels
|
from electrum.util import fee_levels
|
||||||
i = self.fee_slider.sliderPosition()
|
i = self.fee_slider.sliderPosition()
|
||||||
tooltip = fee_levels[i] + ' (%d%%)'% (100 * (i + 1)/3)
|
tooltip = fee_levels[i]
|
||||||
|
dynfee = self.network.dynfee(i)
|
||||||
|
if dynfee:
|
||||||
|
tooltip += '\n' + self.format_amount(dynfee) + ' ' + self.base_unit() + '/kB'
|
||||||
QToolTip.showText(QCursor.pos(), tooltip, self.fee_slider)
|
QToolTip.showText(QCursor.pos(), tooltip, self.fee_slider)
|
||||||
def slider_released():
|
def slider_released():
|
||||||
self.config.set_key('fee_level', self.fee_slider.sliderPosition(), False)
|
self.config.set_key('fee_level', self.fee_slider.sliderPosition(), False)
|
||||||
|
@ -933,7 +936,6 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
|
||||||
self.spend_max()
|
self.spend_max()
|
||||||
else:
|
else:
|
||||||
self.update_fee()
|
self.update_fee()
|
||||||
|
|
||||||
self.fee_slider.valueChanged.connect(slider_moved)
|
self.fee_slider.valueChanged.connect(slider_moved)
|
||||||
self.fee_slider.sliderReleased.connect(slider_released)
|
self.fee_slider.sliderReleased.connect(slider_released)
|
||||||
self.fee_slider.setValue(self.config.get('fee_level', 2))
|
self.fee_slider.setValue(self.config.get('fee_level', 2))
|
||||||
|
@ -2376,12 +2378,11 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, PrintError):
|
||||||
dynfee_cb.setToolTip(_("Use a fee per kB value recommended by the server."))
|
dynfee_cb.setToolTip(_("Use a fee per kB value recommended by the server."))
|
||||||
fee_widgets.append((dynfee_cb, None))
|
fee_widgets.append((dynfee_cb, None))
|
||||||
def update_feeperkb():
|
def update_feeperkb():
|
||||||
fee_e.setAmount(self.wallet.fee_per_kb(self.config))
|
fee_e.setAmount(self.config.get('fee_per_kb', bitcoin.RECOMMENDED_FEE))
|
||||||
b = self.config.get('dynamic_fees', False)
|
b = self.config.get('dynamic_fees', False)
|
||||||
fee_e.setEnabled(not b)
|
fee_e.setEnabled(not b)
|
||||||
def on_dynfee(x):
|
def on_dynfee(x):
|
||||||
dynfee = x == Qt.Checked
|
self.config.set_key('dynamic_fees', x == Qt.Checked)
|
||||||
self.config.set_key('dynamic_fees', dynfee)
|
|
||||||
update_feeperkb()
|
update_feeperkb()
|
||||||
self.update_fee_edit()
|
self.update_fee_edit()
|
||||||
dynfee_cb.stateChanged.connect(on_dynfee)
|
dynfee_cb.stateChanged.connect(on_dynfee)
|
||||||
|
|
|
@ -42,6 +42,8 @@ from interface import Connection, Interface
|
||||||
from blockchain import Blockchain
|
from blockchain import Blockchain
|
||||||
from version import ELECTRUM_VERSION, PROTOCOL_VERSION
|
from version import ELECTRUM_VERSION, PROTOCOL_VERSION
|
||||||
|
|
||||||
|
FEE_TARGETS = [25, 10, 5, 2]
|
||||||
|
|
||||||
DEFAULT_PORTS = {'t':'50001', 's':'50002', 'h':'8081', 'g':'8082'}
|
DEFAULT_PORTS = {'t':'50001', 's':'50002', 'h':'8081', 'g':'8082'}
|
||||||
|
|
||||||
DEFAULT_SERVERS = {
|
DEFAULT_SERVERS = {
|
||||||
|
@ -190,7 +192,7 @@ class Network(util.DaemonThread):
|
||||||
|
|
||||||
self.banner = ''
|
self.banner = ''
|
||||||
self.donation_address = ''
|
self.donation_address = ''
|
||||||
self.fee = None
|
self.fee_estimates = {}
|
||||||
self.relay_fee = None
|
self.relay_fee = None
|
||||||
self.heights = {}
|
self.heights = {}
|
||||||
self.merkle_roots = {}
|
self.merkle_roots = {}
|
||||||
|
@ -314,7 +316,8 @@ class Network(util.DaemonThread):
|
||||||
self.queue_request('server.banner', [])
|
self.queue_request('server.banner', [])
|
||||||
self.queue_request('server.donation_address', [])
|
self.queue_request('server.donation_address', [])
|
||||||
self.queue_request('server.peers.subscribe', [])
|
self.queue_request('server.peers.subscribe', [])
|
||||||
self.queue_request('blockchain.estimatefee', [2])
|
for i in FEE_TARGETS:
|
||||||
|
self.queue_request('blockchain.estimatefee', [i])
|
||||||
self.queue_request('blockchain.relayfee', [])
|
self.queue_request('blockchain.relayfee', [])
|
||||||
|
|
||||||
def get_status_value(self, key):
|
def get_status_value(self, key):
|
||||||
|
@ -323,7 +326,7 @@ class Network(util.DaemonThread):
|
||||||
elif key == 'banner':
|
elif key == 'banner':
|
||||||
value = self.banner
|
value = self.banner
|
||||||
elif key == 'fee':
|
elif key == 'fee':
|
||||||
value = self.fee
|
value = self.fee_estimates
|
||||||
elif key == 'updated':
|
elif key == 'updated':
|
||||||
value = (self.get_local_height(), self.get_server_height())
|
value = (self.get_local_height(), self.get_server_height())
|
||||||
elif key == 'servers':
|
elif key == 'servers':
|
||||||
|
@ -332,6 +335,20 @@ class Network(util.DaemonThread):
|
||||||
value = self.get_interfaces()
|
value = self.get_interfaces()
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
def dynfee(self, i):
|
||||||
|
from bitcoin import RECOMMENDED_FEE
|
||||||
|
if i < 4:
|
||||||
|
j = FEE_TARGETS[i]
|
||||||
|
fee = self.fee_estimates.get(j)
|
||||||
|
else:
|
||||||
|
assert i == 4
|
||||||
|
fee = self.fee_estimates.get(2)
|
||||||
|
if fee is not None:
|
||||||
|
fee += fee/2
|
||||||
|
if fee is not None:
|
||||||
|
fee = min(10*RECOMMENDED_FEE, fee)
|
||||||
|
return fee
|
||||||
|
|
||||||
def notify(self, key):
|
def notify(self, key):
|
||||||
if key in ['status', 'updated']:
|
if key in ['status', 'updated']:
|
||||||
self.trigger_callback(key)
|
self.trigger_callback(key)
|
||||||
|
@ -514,8 +531,8 @@ class Network(util.DaemonThread):
|
||||||
self.donation_address = result
|
self.donation_address = result
|
||||||
elif method == 'blockchain.estimatefee':
|
elif method == 'blockchain.estimatefee':
|
||||||
if error is None:
|
if error is None:
|
||||||
self.fee = int(result * COIN)
|
i = params[0]
|
||||||
self.print_error("recommended fee", self.fee)
|
self.fee_estimates[i] = int(result * COIN)
|
||||||
self.notify('fee')
|
self.notify('fee')
|
||||||
elif method == 'blockchain.relayfee':
|
elif method == 'blockchain.relayfee':
|
||||||
if error is None:
|
if error is None:
|
||||||
|
|
|
@ -36,7 +36,7 @@ import threading
|
||||||
from i18n import _
|
from i18n import _
|
||||||
|
|
||||||
base_units = {'BTC':8, 'mBTC':5, 'uBTC':2}
|
base_units = {'BTC':8, 'mBTC':5, 'uBTC':2}
|
||||||
fee_levels = [_('Very low'), _('Low'), _('Normal'), _('High'), _('Very high')]
|
fee_levels = [_('Within 25 blocks'), _('Within 10 blocks'), _('Within 5 blocks'), _('Within 2 blocks'), _('In the next block')]
|
||||||
|
|
||||||
def normalize_version(v):
|
def normalize_version(v):
|
||||||
return [int(x) for x in re.sub(r'(\.0+)*$','', v).split(".")]
|
return [int(x) for x in re.sub(r'(\.0+)*$','', v).split(".")]
|
||||||
|
|
|
@ -909,15 +909,11 @@ class Abstract_Wallet(PrintError):
|
||||||
|
|
||||||
def fee_per_kb(self, config):
|
def fee_per_kb(self, config):
|
||||||
b = config.get('dynamic_fees')
|
b = config.get('dynamic_fees')
|
||||||
F = config.get('fee_per_kb', bitcoin.RECOMMENDED_FEE)
|
i = config.get('fee_level', 2)
|
||||||
if b and self.network and self.network.fee:
|
if b and self.network and self.network.dynfee(i):
|
||||||
i = config.get('fee_level', 2)
|
return self.network.dynfee(i)
|
||||||
fee = self.network.fee*(i+1)/3
|
|
||||||
fee = max(fee, self.relayfee())
|
|
||||||
fee = min(10*bitcoin.RECOMMENDED_FEE, fee)
|
|
||||||
return fee
|
|
||||||
else:
|
else:
|
||||||
return F
|
return config.get('fee_per_kb', bitcoin.RECOMMENDED_FEE)
|
||||||
|
|
||||||
def get_tx_status(self, tx_hash, height, conf, timestamp):
|
def get_tx_status(self, tx_hash, height, conf, timestamp):
|
||||||
from util import format_time
|
from util import format_time
|
||||||
|
@ -925,10 +921,10 @@ class Abstract_Wallet(PrintError):
|
||||||
tx = self.transactions.get(tx_hash)
|
tx = self.transactions.get(tx_hash)
|
||||||
is_final = tx and tx.is_final()
|
is_final = tx and tx.is_final()
|
||||||
fee = self.tx_fees.get(tx_hash)
|
fee = self.tx_fees.get(tx_hash)
|
||||||
if fee and self.network and self.network.fee:
|
if fee and self.network and self.network.dynfee(25):
|
||||||
size = len(tx.raw)/2
|
size = len(tx.raw)/2
|
||||||
network_fee = int(self.network.fee * size / 1000)
|
low_fee = int(self.network.dynfee(25)*size/1000)
|
||||||
is_lowfee = fee < network_fee * 0.25
|
is_lowfee = fee < low_fee * 0.5
|
||||||
else:
|
else:
|
||||||
is_lowfee = False
|
is_lowfee = False
|
||||||
if not is_final:
|
if not is_final:
|
||||||
|
|
Loading…
Add table
Reference in a new issue