diff --git a/electrum/commands.py b/electrum/commands.py index de5398d38..ff925d68d 100644 --- a/electrum/commands.py +++ b/electrum/commands.py @@ -71,7 +71,7 @@ from .lnutil import channel_id_from_funding_tx, LnFeatures, SENT, MIN_FINAL_CLTV from .plugin import run_hook, DeviceMgr, Plugins from .version import ELECTRUM_VERSION from .simple_config import SimpleConfig -from .fee_policy import FeePolicy +from .fee_policy import FeePolicy, FEE_ETA_TARGETS, FEERATE_DEFAULT_RELAY from . import GuiImportError from . import crypto from . import constants @@ -1576,6 +1576,27 @@ class Commands(Logger): 'tooltip': tooltip, } + @command('n') + async def test_inject_fee_etas(self, fee_est): + """ + Inject fee estimates into the network object, as if they were coming from connected servers. + Useful on regtest. + + arg:str:fee_est:dict of ETA-based fee estimates, encoded as str + """ + if not isinstance(fee_est, dict): + fee_est = ast.literal_eval(fee_est) + assert isinstance(fee_est, dict), f"unexpected type for fee_est. got {repr(fee_est)}" + # populate missing high-block-number estimates using default relay fee. + # e.g. {"25": 2222} -> {"25": 2222, "144": 1000, "1008": 1000} + furthest_estimate = max(fee_est.keys()) if fee_est else 0 + further_fee_est = { + eta_target: FEERATE_DEFAULT_RELAY for eta_target in FEE_ETA_TARGETS + if eta_target > furthest_estimate + } + fee_est.update(further_fee_est) + self.network.update_fee_estimates(fee_est=fee_est) + @command('w') async def removelocaltx(self, txid, wallet: Abstract_Wallet = None): """Remove a 'local' transaction from the wallet, and its dependent diff --git a/electrum/fee_policy.py b/electrum/fee_policy.py index 958c35854..33b7eb384 100644 --- a/electrum/fee_policy.py +++ b/electrum/fee_policy.py @@ -375,8 +375,9 @@ class FeeTimeEstimates: just try to do the estimate and handle a potential None result. That way, estimation works for targets we have, even if some targets are missing. """ - # we do not request estimate for next block fee, hence -1 - return len(self.data) == len(FEE_ETA_TARGETS) - 1 + targets = set(FEE_ETA_TARGETS) + targets.discard(1) # rm "next block" target + return all(target in self.data for target in targets) def set_data(self, nblock_target: int, fee_per_kb: int): assert isinstance(nblock_target, int), f"expected int, got {nblock_target!r}"