From 455167136d907fe43e059f29f7707d636072ffb6 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Sun, 8 Oct 2023 17:43:42 +0200 Subject: [PATCH] CLI: new getfeerate/setfeerate API --- electrum/commands.py | 36 +++++++++++++----------------- electrum/simple_config.py | 47 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 23 deletions(-) diff --git a/electrum/commands.py b/electrum/commands.py index 4e9dc3c13..b9d7df860 100644 --- a/electrum/commands.py +++ b/electrum/commands.py @@ -1069,24 +1069,22 @@ class Commands: """ return wallet synchronization status """ return wallet.is_up_to_date() - @command('n') - async def getfeerate(self, fee_method=None, fee_level=None): - """Return current suggested fee rate (in sat/kvByte), according to config - settings or supplied parameters. + @command('') + async def getfeerate(self): + """Return current fee rate settings and current estimate (in sat/kvByte). """ - 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 = to_decimal(fee_level) - return self.config.fee_per_kb(dyn=dyn, mempool=mempool, fee_level=fee_level) + method, value, feerate, tooltip = self.config.getfeerate() + return { + 'method': method, + 'value': value, + 'sat/kvB': feerate, + 'tooltip': tooltip, + } + + @command('') + async def setfeerate(self, method, value): + """Set fee rate estimation method and value""" + self.config.setfeerate(method, value) @command('w') async def removelocaltx(self, txid, wallet: Abstract_Wallet = None): @@ -1453,8 +1451,6 @@ command_options = { 'show_fiat': (None, "Show fiat value of transactions"), 'show_fees': (None, "Show miner fees paid by transactions"), '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"), 'from_height': (None, "Only show transactions that confirmed after given block height"), 'to_height': (None, "Only show transactions that confirmed before given block height"), 'iknowwhatimdoing': (None, "Acknowledge that I understand the full implications of what I am about to do"), @@ -1487,8 +1483,6 @@ arg_types = { 'amount': lambda x: str(to_decimal(x)) if not parse_max_spend(x) else x, 'locktime': int, 'addtransaction': eval_bool, - 'fee_method': str, - 'fee_level': json_loads, 'encrypt_file': eval_bool, 'rbf': eval_bool, 'timeout': float, diff --git a/electrum/simple_config.py b/electrum/simple_config.py index 9add08d78..3a7a2c4a5 100644 --- a/electrum/simple_config.py +++ b/electrum/simple_config.py @@ -744,11 +744,54 @@ class SimpleConfig(Logger): else: fee_rate = self.eta_to_fee(self.get_fee_level()) else: - fee_rate = self.FEE_EST_STATIC_FEERATE_FALLBACK + fee_rate = self.FEE_EST_STATIC_FEERATE if fee_rate is not None: fee_rate = int(fee_rate) return fee_rate + def getfeerate(self) -> Tuple[str, int, int]: + dyn = self.is_dynfee() + mempool = self.use_mempool_fees() + if dyn: + if mempool: + method = 'mempool' + fee_level = self.get_depth_level() + value = self.depth_target(fee_level) + fee_rate = self.depth_to_fee(fee_level) + tooltip = self.depth_tooltip(value) + else: + method = 'ETA' + fee_level = self.get_fee_level() + value = self.eta_target(fee_level) + fee_rate = self.eta_to_fee(fee_level) + tooltip = self.eta_tooltip(value) + else: + method = 'static' + value = self.FEE_EST_STATIC_FEERATE + fee_rate = value + tooltip = 'static feerate' + + return method, value, fee_rate, tooltip + + def setfeerate(self, fee_method: str, value: int): + if fee_method == 'mempool': + if fee_level not in FEE_DEPTH_TARGETS: + raise Exception(f"Error: fee_level must be in {FEE_DEPTH_TARGETS}") + self.FEE_EST_USE_MEMPOOL = True + self.FEE_EST_DYNAMIC = True + self.FEE_EST_DYNAMIC_MEMPOOL_SLIDERPOS = FEE_DEPTH_TARGETS.index(value) + elif fee_method == 'ETA': + if value not in FEE_ETA_TARGETS: + raise Exception(f"Error: fee_level must be in {FEE_ETA_TARGETS}") + self.FEE_EST_USE_MEMPOOL = False + self.FEE_EST_DYNAMIC = True + self.FEE_EST_DYNAMIC_ETA_SLIDERPOS = FEE_ETA_TARGETS.index(value) + elif fee_method == 'static': + self.FEE_EST_DYNAMIC = False + self.FEE_EST_STATIC_FEERATE = value + else: + raise Exception(f"Invalid parameter: {fee_method}. Valid methods are: ETA, mempool, static.") + def fee_per_byte(self): """Returns sat/vB fee to pay for a txn. Note: might return None. @@ -993,7 +1036,7 @@ This will result in longer routes; it might increase your fees and decrease the FEE_EST_DYNAMIC = ConfigVar('dynamic_fees', default=True, type_=bool) FEE_EST_USE_MEMPOOL = ConfigVar('mempool_fees', default=False, type_=bool) - FEE_EST_STATIC_FEERATE_FALLBACK = ConfigVar('fee_per_kb', default=FEERATE_FALLBACK_STATIC_FEE, type_=int) + FEE_EST_STATIC_FEERATE = ConfigVar('fee_per_kb', default=FEERATE_FALLBACK_STATIC_FEE, type_=int) FEE_EST_DYNAMIC_ETA_SLIDERPOS = ConfigVar('fee_level', default=2, type_=int) FEE_EST_DYNAMIC_MEMPOOL_SLIDERPOS = ConfigVar('depth_level', default=2, type_=int)