diff --git a/src/main/kotlin/io/vincenzopalazzo/btcli4j/control/commands/btcprune/EstimateFeeBtc.kt b/src/main/kotlin/io/vincenzopalazzo/btcli4j/control/commands/btcprune/EstimateFeeBtc.kt index 7b9467f..eb4a88d 100644 --- a/src/main/kotlin/io/vincenzopalazzo/btcli4j/control/commands/btcprune/EstimateFeeBtc.kt +++ b/src/main/kotlin/io/vincenzopalazzo/btcli4j/control/commands/btcprune/EstimateFeeBtc.kt @@ -30,6 +30,67 @@ import jrpc.clightning.plugins.CLightningPlugin import jrpc.clightning.plugins.log.PluginLog import jrpc.service.converters.jsonwrapper.CLightningJsonObject +class EstimateFeeParams(val lnmode: String, val target: Int, val mode: String) + +class FeeManager { + private val feesEstimation: HashMap = HashMap() + private val params = listOf( + EstimateFeeParams("FEERATE_HIGHEST", 2, "CONSERVATIVE"), + EstimateFeeParams("FEERATE_URGENT", 6, "ECONOMICAL"), + EstimateFeeParams("FEERATE_NORMAL", 12, "ECONOMICAL"), + EstimateFeeParams("FEERATE_SLOW", 100, "ECONOMICAL") + ) + + private fun estimateFee(rpc: LiteBitcoinRPC, param: EstimateFeeParams): EstimateFeeBitcoin { + // TODO: try to use this transaction getmempoolinfo + // read this issue https://github.com/ElementsProject/lightning/issues/4473#issue-853325816 + val params = Parameters("estimatesmartfee") + params.addParameter("conf_target", param.target) + params.addParameter("estimate_mode", param.mode) + return rpc.makeBitcoinRequest(params, EstimateFeeBitcoin::class.java) + } + + fun estimate(rpc: LiteBitcoinRPC, plugin: CLightningPlugin): Boolean { + params.forEach { + val estimateFee = this.estimateFee(rpc, it) + if (estimateFee.errors?.isNotEmpty() == true) { + plugin.log(PluginLog.ERROR, "Error during the fee estimation") + for (error in estimateFee.errors!!) { + plugin.log(PluginLog.ERROR, "EstimateFeeBtc: %s".format(error)) + } + return false + } + estimateFee.convertBtcToSat() + plugin.log( + PluginLog.DEBUG, + "EstimateFeeBtc: Estimate fee (target: %d mode: %s) calculation from bitcoin core: %d".format( + it.target, + it.target, + estimateFee.feeRate!!.toInt() + ) + ) + feesEstimation[it.lnmode] = estimateFee + } + return true + } + + fun urgentFee(): EstimateFeeBitcoin { + return feesEstimation["FEERATE_URGENT"]!! + } + + fun highestFee(): EstimateFeeBitcoin { + return feesEstimation["FEERATE_HIGHEST"]!! + } + + fun normalFee(): EstimateFeeBitcoin { + return feesEstimation["FEERATE_NORMAL"]!! + } + + fun slowFee(): EstimateFeeBitcoin { + return feesEstimation["FEERATE_SLOW"]!! + } +} + /** * @author https://github.com/vincenzopalazzo */ @@ -44,39 +105,26 @@ class EstimateFeeBtc( return } try { - // TODO: try to use this transaction getmempoolinfo - // read this issue https://github.com/ElementsProject/lightning/issues/4473#issue-853325816 - val params = Parameters("estimatesmartfee") - params.addParameter("conf_target", 6) - // params.addParameter("estimate_mode", "CONSERVATIVE") - - val estimateFee = bitcoinRPC.makeBitcoinRequest(params, EstimateFeeBitcoin::class.java) - - if (estimateFee.errors?.isNotEmpty() == true) { - // TODO this can cause a loop? maybe - plugin.log(PluginLog.ERROR, "Error during the fee estimation") - for (error in estimateFee.errors!!) { - plugin.log(PluginLog.ERROR, "EstimateFeeBtc: %s".format(error)) - } - this.returnNullFeee(response) + val estimator = FeeManager() + if (!estimator.estimate(bitcoinRPC, plugin)) { + // FIXME this can cause a loop? maybe + this.returnNullFee(response) return } - estimateFee.convertBtcToSat() - plugin.log(PluginLog.DEBUG, "EstimateFeeBtc: Estimate fee calculation from bitcoin core: %d".format(estimateFee.feeRate!!.toInt())) response.apply { - add("opening", estimateFee.feeRate!!.toInt()) - add("mutual_close", estimateFee.feeRate!!.toInt()) - add("unilateral_close", estimateFee.feeRate!!.toInt()) - add("delayed_to_us", estimateFee.feeRate!!.toInt()) - add("htlc_resolution", estimateFee.feeRate!!.toInt()) - add("penalty", estimateFee.feeRate!!.toInt()) - add("min_acceptable", estimateFee.feeRate!!.toInt() / 2) - add("max_acceptable", estimateFee.feeRate!!.toInt() * 10) + add("opening", estimator.normalFee().feeRate!!.toInt()) + add("mutual_close", estimator.slowFee().feeRate!!.toInt()) + add("unilateral_close", estimator.urgentFee().feeRate!!.toInt()) + add("delayed_to_us", estimator.normalFee().feeRate!!.toInt()) + add("htlc_resolution", estimator.urgentFee().feeRate!!.toInt()) + add("penalty", estimator.normalFee().feeRate!!.toInt()) + add("min_acceptable", estimator.slowFee().feeRate!!.toInt() / 2) + add("max_acceptable", estimator.highestFee().feeRate!!.toInt() * 10) } } catch (bitcoinEx: BitcoinCoreException) { plugin.log(PluginLog.ERROR, "EstimateFeeBtc: terminate bitcoin core with error: %s".format(bitcoinEx.message)) - this.returnNullFeee(response) + this.returnNullFee(response) } catch (ex: LiteBitcoinRPCException) { plugin.log(PluginLog.ERROR, ex.stackTraceToString()) plugin.log(PluginLog.DEBUG, "EstimateFeeBtc: Share message to esplora") @@ -84,7 +132,7 @@ class EstimateFeeBtc( } } - private fun returnNullFeee(response: CLightningJsonObject) { + private fun returnNullFee(response: CLightningJsonObject) { response.apply { add("opening", null) add("mutual_close", null)