mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-09-01 01:35:20 +00:00
getfeerate command: add optional parameters to specify custom fee level (#4264)
This commit is contained in:
parent
2cc15fca57
commit
a98e833897
3 changed files with 59 additions and 14 deletions
|
@ -657,10 +657,23 @@ class Commands:
|
||||||
return self.wallet.is_up_to_date()
|
return self.wallet.is_up_to_date()
|
||||||
|
|
||||||
@command('n')
|
@command('n')
|
||||||
def getfeerate(self):
|
def getfeerate(self, fee_method=None, fee_level=None):
|
||||||
"""Return current optimal fee rate per kilobyte, according
|
"""Return current suggested fee rate (in sat/kvByte), according to config
|
||||||
to config settings (static/dynamic)"""
|
settings or supplied parameters.
|
||||||
return self.config.fee_per_kb()
|
"""
|
||||||
|
if fee_method is None:
|
||||||
|
dyn, mempool = None, None
|
||||||
|
elif fee_method.lower() == 'static':
|
||||||
|
dyn, mempool = False, False
|
||||||
|
elif fee_method.lower() == 'eta':
|
||||||
|
dyn, mempool = True, False
|
||||||
|
elif fee_method.lower() == 'mempool':
|
||||||
|
dyn, mempool = True, True
|
||||||
|
else:
|
||||||
|
raise Exception('Invalid fee estimation method: {}'.format(fee_method))
|
||||||
|
if fee_level is not None:
|
||||||
|
fee_level = Decimal(fee_level)
|
||||||
|
return self.config.fee_per_kb(dyn=dyn, mempool=mempool, fee_level=fee_level)
|
||||||
|
|
||||||
@command('')
|
@command('')
|
||||||
def help(self):
|
def help(self):
|
||||||
|
@ -719,6 +732,8 @@ command_options = {
|
||||||
'show_addresses': (None, "Show input and output addresses"),
|
'show_addresses': (None, "Show input and output addresses"),
|
||||||
'show_fiat': (None, "Show fiat value of transactions"),
|
'show_fiat': (None, "Show fiat value of transactions"),
|
||||||
'year': (None, "Show history for a given year"),
|
'year': (None, "Show history for a given year"),
|
||||||
|
'fee_method': (None, "Fee estimation method to use"),
|
||||||
|
'fee_level': (None, "Float between 0.0 and 1.0, representing fee slider position")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -738,6 +753,8 @@ arg_types = {
|
||||||
'fee': lambda x: str(Decimal(x)) if x is not None else None,
|
'fee': lambda x: str(Decimal(x)) if x is not None else None,
|
||||||
'amount': lambda x: str(Decimal(x)) if x != '!' else '!',
|
'amount': lambda x: str(Decimal(x)) if x != '!' else '!',
|
||||||
'locktime': int,
|
'locktime': int,
|
||||||
|
'fee_method': str,
|
||||||
|
'fee_level': json_loads,
|
||||||
}
|
}
|
||||||
|
|
||||||
config_variables = {
|
config_variables = {
|
||||||
|
|
|
@ -260,7 +260,9 @@ class Daemon(DaemonThread):
|
||||||
password = config_options.get('password')
|
password = config_options.get('password')
|
||||||
new_password = config_options.get('new_password')
|
new_password = config_options.get('new_password')
|
||||||
config = SimpleConfig(config_options)
|
config = SimpleConfig(config_options)
|
||||||
|
# FIXME this is ugly...
|
||||||
config.fee_estimates = self.network.config.fee_estimates.copy()
|
config.fee_estimates = self.network.config.fee_estimates.copy()
|
||||||
|
config.mempool_fees = self.network.config.mempool_fees.copy()
|
||||||
cmdname = config.get('cmd')
|
cmdname = config.get('cmd')
|
||||||
cmd = known_commands[cmdname]
|
cmd = known_commands[cmdname]
|
||||||
if cmd.requires_wallet:
|
if cmd.requires_wallet:
|
||||||
|
|
|
@ -4,6 +4,7 @@ import time
|
||||||
import os
|
import os
|
||||||
import stat
|
import stat
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
|
||||||
|
@ -278,16 +279,18 @@ class SimpleConfig(PrintError):
|
||||||
return get_fee_within_limits
|
return get_fee_within_limits
|
||||||
|
|
||||||
@impose_hard_limits_on_fee
|
@impose_hard_limits_on_fee
|
||||||
def eta_to_fee(self, i):
|
def eta_to_fee(self, slider_pos) -> Union[int, None]:
|
||||||
"""Returns fee in sat/kbyte."""
|
"""Returns fee in sat/kbyte."""
|
||||||
if i < 4:
|
slider_pos = max(slider_pos, 0)
|
||||||
j = FEE_ETA_TARGETS[i]
|
slider_pos = min(slider_pos, len(FEE_ETA_TARGETS))
|
||||||
fee = self.fee_estimates.get(j)
|
if slider_pos < len(FEE_ETA_TARGETS):
|
||||||
|
target_blocks = FEE_ETA_TARGETS[slider_pos]
|
||||||
|
fee = self.fee_estimates.get(target_blocks)
|
||||||
else:
|
else:
|
||||||
assert i == 4
|
|
||||||
fee = self.fee_estimates.get(2)
|
fee = self.fee_estimates.get(2)
|
||||||
if fee is not None:
|
if fee is not None:
|
||||||
fee += fee/2
|
fee += fee/2
|
||||||
|
fee = int(fee)
|
||||||
return fee
|
return fee
|
||||||
|
|
||||||
def fee_to_depth(self, target_fee):
|
def fee_to_depth(self, target_fee):
|
||||||
|
@ -301,9 +304,9 @@ class SimpleConfig(PrintError):
|
||||||
return depth
|
return depth
|
||||||
|
|
||||||
@impose_hard_limits_on_fee
|
@impose_hard_limits_on_fee
|
||||||
def depth_to_fee(self, i):
|
def depth_to_fee(self, slider_pos) -> int:
|
||||||
"""Returns fee in sat/kbyte."""
|
"""Returns fee in sat/kbyte."""
|
||||||
target = self.depth_target(i)
|
target = self.depth_target(slider_pos)
|
||||||
depth = 0
|
depth = 0
|
||||||
for fee, s in self.mempool_fees:
|
for fee, s in self.mempool_fees:
|
||||||
depth += s
|
depth += s
|
||||||
|
@ -313,8 +316,10 @@ class SimpleConfig(PrintError):
|
||||||
return 0
|
return 0
|
||||||
return fee * 1000
|
return fee * 1000
|
||||||
|
|
||||||
def depth_target(self, i):
|
def depth_target(self, slider_pos):
|
||||||
return FEE_DEPTH_TARGETS[i]
|
slider_pos = max(slider_pos, 0)
|
||||||
|
slider_pos = min(slider_pos, len(FEE_DEPTH_TARGETS)-1)
|
||||||
|
return FEE_DEPTH_TARGETS[slider_pos]
|
||||||
|
|
||||||
def eta_target(self, i):
|
def eta_target(self, i):
|
||||||
if i == len(FEE_ETA_TARGETS):
|
if i == len(FEE_ETA_TARGETS):
|
||||||
|
@ -430,14 +435,35 @@ class SimpleConfig(PrintError):
|
||||||
def use_mempool_fees(self):
|
def use_mempool_fees(self):
|
||||||
return bool(self.get('mempool_fees', False))
|
return bool(self.get('mempool_fees', False))
|
||||||
|
|
||||||
def fee_per_kb(self, dyn=None, mempool=None):
|
def _feerate_from_fractional_slider_position(self, fee_level: float, dyn: bool,
|
||||||
|
mempool: bool) -> Union[int, None]:
|
||||||
|
fee_level = max(fee_level, 0)
|
||||||
|
fee_level = min(fee_level, 1)
|
||||||
|
if dyn:
|
||||||
|
max_pos = (len(FEE_DEPTH_TARGETS) - 1) if mempool else len(FEE_ETA_TARGETS)
|
||||||
|
slider_pos = round(fee_level * max_pos)
|
||||||
|
fee_rate = self.depth_to_fee(slider_pos) if mempool else self.eta_to_fee(slider_pos)
|
||||||
|
else:
|
||||||
|
max_pos = len(FEERATE_STATIC_VALUES) - 1
|
||||||
|
slider_pos = round(fee_level * max_pos)
|
||||||
|
fee_rate = FEERATE_STATIC_VALUES[slider_pos]
|
||||||
|
return fee_rate
|
||||||
|
|
||||||
|
def fee_per_kb(self, dyn: bool=None, mempool: bool=None, fee_level: float=None) -> Union[int, None]:
|
||||||
"""Returns sat/kvB fee to pay for a txn.
|
"""Returns sat/kvB fee to pay for a txn.
|
||||||
Note: might return None.
|
Note: might return None.
|
||||||
|
|
||||||
|
fee_level: float between 0.0 and 1.0, representing fee slider position
|
||||||
"""
|
"""
|
||||||
if dyn is None:
|
if dyn is None:
|
||||||
dyn = self.is_dynfee()
|
dyn = self.is_dynfee()
|
||||||
if mempool is None:
|
if mempool is None:
|
||||||
mempool = self.use_mempool_fees()
|
mempool = self.use_mempool_fees()
|
||||||
|
if fee_level is not None:
|
||||||
|
return self._feerate_from_fractional_slider_position(fee_level, dyn, mempool)
|
||||||
|
# there is no fee_level specified; will use config.
|
||||||
|
# note: 'depth_level' and 'fee_level' in config are integer slider positions,
|
||||||
|
# unlike fee_level here, which (when given) is a float in [0.0, 1.0]
|
||||||
if dyn:
|
if dyn:
|
||||||
if mempool:
|
if mempool:
|
||||||
fee_rate = self.depth_to_fee(self.get_depth_level())
|
fee_rate = self.depth_to_fee(self.get_depth_level())
|
||||||
|
|
Loading…
Add table
Reference in a new issue