From b2e3729c39be6dcd6f391d203ef5854e7409b790 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Wed, 29 Oct 2025 08:50:51 +0000 Subject: [PATCH 1/7] Add support for subsat & fractional fee recommendations --- backend/src/api/bitcoin/bitcoin.routes.ts | 11 +++++ backend/src/api/fee-api.ts | 56 +++++++++++++++-------- backend/src/config.ts | 2 + 3 files changed, 50 insertions(+), 19 deletions(-) diff --git a/backend/src/api/bitcoin/bitcoin.routes.ts b/backend/src/api/bitcoin/bitcoin.routes.ts index bdc4445f9..e6075ffa2 100644 --- a/backend/src/api/bitcoin/bitcoin.routes.ts +++ b/backend/src/api/bitcoin/bitcoin.routes.ts @@ -36,6 +36,7 @@ class BitcoinRoutes { .get(config.MEMPOOL.API_URL_PREFIX + 'cpfp/:txId', this.$getCpfpInfo) .get(config.MEMPOOL.API_URL_PREFIX + 'difficulty-adjustment', this.getDifficultyChange) .get(config.MEMPOOL.API_URL_PREFIX + 'fees/recommended', this.getRecommendedFees) + .get(config.MEMPOOL.API_URL_PREFIX + 'fees/precise', this.getPreciseRecommendedFees) .get(config.MEMPOOL.API_URL_PREFIX + 'fees/mempool-blocks', this.getMempoolBlocks) .get(config.MEMPOOL.API_URL_PREFIX + 'backend-info', this.getBackendInfo) .get(config.MEMPOOL.API_URL_PREFIX + 'init-data', this.getInitData) @@ -122,6 +123,16 @@ class BitcoinRoutes { res.json(result); } + private getPreciseRecommendedFees(req: Request, res: Response) { + if (!mempool.isInSync()) { + res.statusCode = 503; + res.send('Service Unavailable'); + return; + } + const result = feeApi.getPreciseRecommendedFee(); + res.json(result); + } + private getMempoolBlocks(req: Request, res: Response) { try { const result = mempoolBlocks.getMempoolBlocks(); diff --git a/backend/src/api/fee-api.ts b/backend/src/api/fee-api.ts index 8efb8f605..12b56595e 100644 --- a/backend/src/api/fee-api.ts +++ b/backend/src/api/fee-api.ts @@ -17,7 +17,7 @@ interface RecommendedFees { class FeeApi { constructor() { } - defaultFee = isLiquid ? 0.1 : 1; + defaultFee = isLiquid ? 0.1 : config.MEMPOOL.MIN_RECOMMENDED_FEE; minimumIncrement = isLiquid ? 0.1 : 1; public getRecommendedFee(): RecommendedFees { @@ -27,24 +27,36 @@ class FeeApi { return this.calculateRecommendedFee(pBlocks, mPool); } - public calculateRecommendedFee(pBlocks: MempoolBlock[], mPool: IBitcoinApi.MempoolInfo): RecommendedFees { - const minimumFee = this.roundUpToNearest(mPool.mempoolminfee * 100000, this.minimumIncrement); - const defaultMinFee = Math.max(minimumFee, this.defaultFee); + public getPreciseRecommendedFee(): RecommendedFees { + const pBlocks = projectedBlocks.getMempoolBlocks(); + const mPool = mempool.getMempoolInfo(); + + // minimum non-zero minrelaytxfee / incrementalrelayfee is 1 sat/kvB = 0.001 sat/vB + return this.calculateRecommendedFee(pBlocks, mPool, 0.001); + } + + public calculateRecommendedFee(pBlocks: MempoolBlock[], mPool: IBitcoinApi.MempoolInfo, minIncrement: number = this.minimumIncrement): RecommendedFees { + const purgeRate = this.roundUpToNearest(mPool.mempoolminfee * 100000, minIncrement); + const minimumFee = Math.max(purgeRate, config.MEMPOOL.MIN_RECOMMENDED_FEE, minIncrement); if (!pBlocks.length) { return { - 'fastestFee': defaultMinFee, - 'halfHourFee': defaultMinFee, - 'hourFee': defaultMinFee, + 'fastestFee': minimumFee, + 'halfHourFee': minimumFee, + 'hourFee': minimumFee, 'economyFee': minimumFee, 'minimumFee': minimumFee, }; } - const firstMedianFee = this.optimizeMedianFee(pBlocks[0], pBlocks[1]); - const secondMedianFee = pBlocks[1] ? this.optimizeMedianFee(pBlocks[1], pBlocks[2], firstMedianFee) : this.defaultFee; - const thirdMedianFee = pBlocks[2] ? this.optimizeMedianFee(pBlocks[2], pBlocks[3], secondMedianFee) : this.defaultFee; + const firstMedianFee = this.optimizeMedianFee(pBlocks[0], pBlocks[1], undefined, minimumFee, minIncrement); + const secondMedianFee = pBlocks[1] ? this.optimizeMedianFee(pBlocks[1], pBlocks[2], firstMedianFee, minimumFee, minIncrement) : minimumFee; + const thirdMedianFee = pBlocks[2] ? this.optimizeMedianFee(pBlocks[2], pBlocks[3], secondMedianFee, minimumFee, minIncrement) : minimumFee; + // explicitly enforce a minimum of ceil(mempoolminfee) on all recommendations. + // simply rounding up recommended rates is insufficient, as the purging rate + // can exceed the median rate of projected blocks in some extreme scenarios + // (see https://bitcoin.stackexchange.com/a/120024) let fastestFee = Math.max(minimumFee, firstMedianFee); let halfHourFee = Math.max(minimumFee, secondMedianFee); let hourFee = Math.max(minimumFee, thirdMedianFee); @@ -55,10 +67,6 @@ class FeeApi { halfHourFee = Math.max(halfHourFee, hourFee, economyFee); hourFee = Math.max(hourFee, economyFee); - // explicitly enforce a minimum of ceil(mempoolminfee) on all recommendations. - // simply rounding up recommended rates is insufficient, as the purging rate - // can exceed the median rate of projected blocks in some extreme scenarios - // (see https://bitcoin.stackexchange.com/a/120024) return { 'fastestFee': fastestFee, 'halfHourFee': halfHourFee, @@ -68,20 +76,30 @@ class FeeApi { }; } - private optimizeMedianFee(pBlock: MempoolBlock, nextBlock: MempoolBlock | undefined, previousFee?: number): number { + private optimizeMedianFee(pBlock: MempoolBlock, nextBlock: MempoolBlock | undefined, previousFee?: number, minFee: number = this.defaultFee, minIncrement: number = this.minimumIncrement): number { const useFee = previousFee ? (pBlock.medianFee + previousFee) / 2 : pBlock.medianFee; if (pBlock.blockVSize <= 500000 || pBlock.medianFee < 1) { - return this.defaultFee; + return minFee; } if (pBlock.blockVSize <= 950000 && !nextBlock) { const multiplier = (pBlock.blockVSize - 500000) / 500000; - return Math.max(Math.round(useFee * multiplier), this.defaultFee); + return Math.max(this.roundToNearest(useFee * multiplier, minIncrement), minFee); } - return this.roundUpToNearest(useFee, this.minimumIncrement); + return Math.max(this.roundUpToNearest(useFee, minIncrement), minFee); } private roundUpToNearest(value: number, nearest: number): number { - return Math.ceil(value / nearest) * nearest; + if (nearest !== 0) { + return Math.ceil(value / nearest) * nearest; + } + return value; + } + + private roundToNearest(value: number, nearest: number): number { + if (nearest !== 0) { + return Math.round(value / nearest) * nearest; + } + return value; } } diff --git a/backend/src/config.ts b/backend/src/config.ts index 3fe3db2ee..f3260e788 100644 --- a/backend/src/config.ts +++ b/backend/src/config.ts @@ -43,6 +43,7 @@ interface IConfig { ALLOW_UNREACHABLE: boolean; PRICE_UPDATES_PER_HOUR: number; MAX_TRACKED_ADDRESSES: number; + MIN_RECOMMENDED_FEE: number; }; ESPLORA: { REST_API_URL: string; @@ -214,6 +215,7 @@ const defaults: IConfig = { 'ALLOW_UNREACHABLE': true, 'PRICE_UPDATES_PER_HOUR': 1, 'MAX_TRACKED_ADDRESSES': 1, + 'MIN_RECOMMENDED_FEE': 1, }, 'ESPLORA': { 'REST_API_URL': 'http://127.0.0.1:3000', From 5f051c7d0da61586b575d615024b3e947fdac69a Mon Sep 17 00:00:00 2001 From: Mononaut Date: Wed, 29 Oct 2025 08:52:01 +0000 Subject: [PATCH 2/7] Enable subsat fee recommendations in prod --- production/mempool-config.mainnet.json | 3 ++- production/mempool-config.signet.json | 3 ++- production/mempool-config.testnet.json | 3 ++- production/mempool-config.testnet4.json | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/production/mempool-config.mainnet.json b/production/mempool-config.mainnet.json index 87f58f916..301bd0f3f 100644 --- a/production/mempool-config.mainnet.json +++ b/production/mempool-config.mainnet.json @@ -23,7 +23,8 @@ "MAX_PUSH_TX_SIZE_WEIGHT": 4000000, "ALLOW_UNREACHABLE": true, "PRICE_UPDATES_PER_HOUR": 12, - "MAX_TRACKED_ADDRESSES": 10 + "MAX_TRACKED_ADDRESSES": 10, + "MIN_RECOMMENDED_TX_FEE": 0.1 }, "SYSLOG" : { "MIN_PRIORITY": "debug" diff --git a/production/mempool-config.signet.json b/production/mempool-config.signet.json index 952845ae9..d4c45d133 100644 --- a/production/mempool-config.signet.json +++ b/production/mempool-config.signet.json @@ -16,7 +16,8 @@ "DISK_CACHE_BLOCK_INTERVAL": 1, "MAX_PUSH_TX_SIZE_WEIGHT": 4000000, "ALLOW_UNREACHABLE": true, - "MAX_TRACKED_ADDRESSES": 10 + "MAX_TRACKED_ADDRESSES": 10, + "MIN_RECOMMENDED_TX_FEE": 0.1 }, "SYSLOG" : { "MIN_PRIORITY": "debug" diff --git a/production/mempool-config.testnet.json b/production/mempool-config.testnet.json index 5f9f3abb9..54be5c20e 100644 --- a/production/mempool-config.testnet.json +++ b/production/mempool-config.testnet.json @@ -16,7 +16,8 @@ "DISK_CACHE_BLOCK_INTERVAL": 1, "MAX_PUSH_TX_SIZE_WEIGHT": 4000000, "ALLOW_UNREACHABLE": true, - "MAX_TRACKED_ADDRESSES": 10 + "MAX_TRACKED_ADDRESSES": 10, + "MIN_RECOMMENDED_TX_FEE": 0.1 }, "SYSLOG" : { "MIN_PRIORITY": "debug" diff --git a/production/mempool-config.testnet4.json b/production/mempool-config.testnet4.json index 2e79309ed..98f255c68 100644 --- a/production/mempool-config.testnet4.json +++ b/production/mempool-config.testnet4.json @@ -16,7 +16,8 @@ "DISK_CACHE_BLOCK_INTERVAL": 1, "MAX_PUSH_TX_SIZE_WEIGHT": 4000000, "ALLOW_UNREACHABLE": true, - "MAX_TRACKED_ADDRESSES": 10 + "MAX_TRACKED_ADDRESSES": 10, + "MIN_RECOMMENDED_FEE": 0.1 }, "SYSLOG" : { "MIN_PRIORITY": "debug" From fd60913f540102dfacbcc5e6b78ae11547720055 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Wed, 29 Oct 2025 10:12:28 +0000 Subject: [PATCH 3/7] Add min fee query param to precise fee API --- backend/src/api/bitcoin/bitcoin.routes.ts | 12 +++++++++++- backend/src/api/fee-api.ts | 10 +++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/backend/src/api/bitcoin/bitcoin.routes.ts b/backend/src/api/bitcoin/bitcoin.routes.ts index e6075ffa2..9e6de5dd1 100644 --- a/backend/src/api/bitcoin/bitcoin.routes.ts +++ b/backend/src/api/bitcoin/bitcoin.routes.ts @@ -129,7 +129,17 @@ class BitcoinRoutes { res.send('Service Unavailable'); return; } - const result = feeApi.getPreciseRecommendedFee(); + let minFee = 1; + if (req.query.min) { + try { + minFee = parseFloat(req.query.min as string); + } catch (e) { + res.statusCode = 400; + res.send('Invalid minimum fee'); + return; + } + } + const result = feeApi.getPreciseRecommendedFee(minFee); res.json(result); } diff --git a/backend/src/api/fee-api.ts b/backend/src/api/fee-api.ts index 12b56595e..489f6a067 100644 --- a/backend/src/api/fee-api.ts +++ b/backend/src/api/fee-api.ts @@ -27,17 +27,17 @@ class FeeApi { return this.calculateRecommendedFee(pBlocks, mPool); } - public getPreciseRecommendedFee(): RecommendedFees { + public getPreciseRecommendedFee(minimum: number = 0): RecommendedFees { const pBlocks = projectedBlocks.getMempoolBlocks(); const mPool = mempool.getMempoolInfo(); // minimum non-zero minrelaytxfee / incrementalrelayfee is 1 sat/kvB = 0.001 sat/vB - return this.calculateRecommendedFee(pBlocks, mPool, 0.001); + return this.calculateRecommendedFee(pBlocks, mPool, minimum, 0.001); } - public calculateRecommendedFee(pBlocks: MempoolBlock[], mPool: IBitcoinApi.MempoolInfo, minIncrement: number = this.minimumIncrement): RecommendedFees { + public calculateRecommendedFee(pBlocks: MempoolBlock[], mPool: IBitcoinApi.MempoolInfo, minimumRecommendation: number = this.defaultFee, minIncrement: number = this.minimumIncrement): RecommendedFees { const purgeRate = this.roundUpToNearest(mPool.mempoolminfee * 100000, minIncrement); - const minimumFee = Math.max(purgeRate, config.MEMPOOL.MIN_RECOMMENDED_FEE, minIncrement); + const minimumFee = Math.max(purgeRate, minimumRecommendation, config.MEMPOOL.MIN_RECOMMENDED_FEE, minIncrement); if (!pBlocks.length) { return { @@ -78,7 +78,7 @@ class FeeApi { private optimizeMedianFee(pBlock: MempoolBlock, nextBlock: MempoolBlock | undefined, previousFee?: number, minFee: number = this.defaultFee, minIncrement: number = this.minimumIncrement): number { const useFee = previousFee ? (pBlock.medianFee + previousFee) / 2 : pBlock.medianFee; - if (pBlock.blockVSize <= 500000 || pBlock.medianFee < 1) { + if (pBlock.blockVSize <= 500000 || pBlock.medianFee < minFee) { return minFee; } if (pBlock.blockVSize <= 950000 && !nextBlock) { From ee1a4ae6e250587e9314e30e20d4f9aeb475b1de Mon Sep 17 00:00:00 2001 From: Mononaut Date: Wed, 29 Oct 2025 11:24:13 +0000 Subject: [PATCH 4/7] fix fee config --- backend/src/__fixtures__/mempool-config.template.json | 3 ++- backend/src/__tests__/config.test.ts | 1 + docker/backend/mempool-config.json | 3 ++- docker/backend/start.sh | 2 ++ 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/backend/src/__fixtures__/mempool-config.template.json b/backend/src/__fixtures__/mempool-config.template.json index 0ca5654a5..93f66ca12 100644 --- a/backend/src/__fixtures__/mempool-config.template.json +++ b/backend/src/__fixtures__/mempool-config.template.json @@ -38,7 +38,8 @@ "MAX_PUSH_TX_SIZE_WEIGHT": 4000000, "ALLOW_UNREACHABLE": true, "PRICE_UPDATES_PER_HOUR": 1, - "MAX_TRACKED_ADDRESSES": 1 + "MAX_TRACKED_ADDRESSES": 1, + "MIN_RECOMMENDED_FEE": 1 }, "CORE_RPC": { "HOST": "__CORE_RPC_HOST__", diff --git a/backend/src/__tests__/config.test.ts b/backend/src/__tests__/config.test.ts index e0437941f..bb21e8509 100644 --- a/backend/src/__tests__/config.test.ts +++ b/backend/src/__tests__/config.test.ts @@ -52,6 +52,7 @@ describe('Mempool Backend Config', () => { ALLOW_UNREACHABLE: true, PRICE_UPDATES_PER_HOUR: 1, MAX_TRACKED_ADDRESSES: 1, + MIN_RECOMMENDED_FEE: 1, }); expect(config.ELECTRUM).toStrictEqual({ HOST: '127.0.0.1', PORT: 3306, TLS_ENABLED: true }); diff --git a/docker/backend/mempool-config.json b/docker/backend/mempool-config.json index ee8e329a6..08b684f82 100644 --- a/docker/backend/mempool-config.json +++ b/docker/backend/mempool-config.json @@ -38,7 +38,8 @@ "POOLS_JSON_URL": "__MEMPOOL_POOLS_JSON_URL__", "POOLS_UPDATE_DELAY": __MEMPOOL_POOLS_UPDATE_DELAY__, "PRICE_UPDATES_PER_HOUR": __MEMPOOL_PRICE_UPDATES_PER_HOUR__, - "MAX_TRACKED_ADDRESSES": __MEMPOOL_MAX_TRACKED_ADDRESSES__ + "MAX_TRACKED_ADDRESSES": __MEMPOOL_MAX_TRACKED_ADDRESSES__, + "MIN_RECOMMENDED_FEE": __MEMPOOL_MIN_RECOMMENDED_FEE__ }, "CORE_RPC": { "HOST": "__CORE_RPC_HOST__", diff --git a/docker/backend/start.sh b/docker/backend/start.sh index ae0bc616f..88f4b3161 100755 --- a/docker/backend/start.sh +++ b/docker/backend/start.sh @@ -40,6 +40,7 @@ __MEMPOOL_MAX_PUSH_TX_SIZE_WEIGHT__=${MEMPOOL_MAX_PUSH_TX_SIZE_WEIGHT:=4000000} __MEMPOOL_ALLOW_UNREACHABLE__=${MEMPOOL_ALLOW_UNREACHABLE:=true} __MEMPOOL_PRICE_UPDATES_PER_HOUR__=${MEMPOOL_PRICE_UPDATES_PER_HOUR:=1} __MEMPOOL_MAX_TRACKED_ADDRESSES__=${MEMPOOL_MAX_TRACKED_ADDRESSES:=1} +__MEMPOOL_MIN_RECOMMENDED_FEE__=${MEMPOOL_MIN_RECOMMENDED_FEE:=1} # CORE_RPC __CORE_RPC_HOST__=${CORE_RPC_HOST:=127.0.0.1} @@ -204,6 +205,7 @@ sed -i "s!__MEMPOOL_MAX_PUSH_TX_SIZE_WEIGHT__!${__MEMPOOL_MAX_PUSH_TX_SIZE_WEIGH sed -i "s!__MEMPOOL_ALLOW_UNREACHABLE__!${__MEMPOOL_ALLOW_UNREACHABLE__}!g" mempool-config.json sed -i "s!__MEMPOOL_PRICE_UPDATES_PER_HOUR__!${__MEMPOOL_PRICE_UPDATES_PER_HOUR__}!g" mempool-config.json sed -i "s!__MEMPOOL_MAX_TRACKED_ADDRESSES__!${__MEMPOOL_MAX_TRACKED_ADDRESSES__}!g" mempool-config.json +sed -i "s!__MEMPOOL_MIN_RECOMMENDED_FEE__!${__MEMPOOL_MIN_RECOMMENDED_FEE__}!g" mempool-config.json sed -i "s!__CORE_RPC_HOST__!${__CORE_RPC_HOST__}!g" mempool-config.json sed -i "s!__CORE_RPC_PORT__!${__CORE_RPC_PORT__}!g" mempool-config.json From 38c192405708e05c80c0681becc2ec052d5750b7 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Thu, 30 Oct 2025 10:36:08 +0000 Subject: [PATCH 5/7] round precise fee recommendations to 3.d.p --- backend/src/api/fee-api.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/src/api/fee-api.ts b/backend/src/api/fee-api.ts index 489f6a067..2a1a26efe 100644 --- a/backend/src/api/fee-api.ts +++ b/backend/src/api/fee-api.ts @@ -68,11 +68,11 @@ class FeeApi { hourFee = Math.max(hourFee, economyFee); return { - 'fastestFee': fastestFee, - 'halfHourFee': halfHourFee, - 'hourFee': hourFee, - 'economyFee': economyFee, - 'minimumFee': minimumFee, + 'fastestFee': this.roundToNearest(fastestFee, minIncrement), + 'halfHourFee': this.roundToNearest(halfHourFee, minIncrement), + 'hourFee': this.roundToNearest(hourFee, minIncrement), + 'economyFee': this.roundToNearest(economyFee, minIncrement), + 'minimumFee': this.roundToNearest(minimumFee, minIncrement), }; } From 89ff47eaa92ec1229c001c65ff364dd3f981de1e Mon Sep 17 00:00:00 2001 From: Mononaut Date: Thu, 30 Oct 2025 10:43:55 +0000 Subject: [PATCH 6/7] remove default value for ?min fee recommendation query param --- backend/src/api/bitcoin/bitcoin.routes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/api/bitcoin/bitcoin.routes.ts b/backend/src/api/bitcoin/bitcoin.routes.ts index 9e6de5dd1..69d42f570 100644 --- a/backend/src/api/bitcoin/bitcoin.routes.ts +++ b/backend/src/api/bitcoin/bitcoin.routes.ts @@ -129,7 +129,7 @@ class BitcoinRoutes { res.send('Service Unavailable'); return; } - let minFee = 1; + let minFee = 0; if (req.query.min) { try { minFee = parseFloat(req.query.min as string); From 416f7b45654669f815714b3672c8a44a5d0131ba Mon Sep 17 00:00:00 2001 From: Mononaut Date: Thu, 30 Oct 2025 10:32:51 +0000 Subject: [PATCH 7/7] remove config.MEMPOOL.MIN_RECOMMENDED_FEE --- backend/src/__fixtures__/mempool-config.template.json | 3 +-- backend/src/__tests__/config.test.ts | 3 +-- backend/src/api/fee-api.ts | 7 +++---- backend/src/config.ts | 2 -- docker/backend/mempool-config.json | 3 +-- docker/backend/start.sh | 2 -- production/mempool-config.mainnet.json | 3 +-- production/mempool-config.signet.json | 3 +-- production/mempool-config.testnet.json | 3 +-- production/mempool-config.testnet4.json | 3 +-- 10 files changed, 10 insertions(+), 22 deletions(-) diff --git a/backend/src/__fixtures__/mempool-config.template.json b/backend/src/__fixtures__/mempool-config.template.json index 93f66ca12..0ca5654a5 100644 --- a/backend/src/__fixtures__/mempool-config.template.json +++ b/backend/src/__fixtures__/mempool-config.template.json @@ -38,8 +38,7 @@ "MAX_PUSH_TX_SIZE_WEIGHT": 4000000, "ALLOW_UNREACHABLE": true, "PRICE_UPDATES_PER_HOUR": 1, - "MAX_TRACKED_ADDRESSES": 1, - "MIN_RECOMMENDED_FEE": 1 + "MAX_TRACKED_ADDRESSES": 1 }, "CORE_RPC": { "HOST": "__CORE_RPC_HOST__", diff --git a/backend/src/__tests__/config.test.ts b/backend/src/__tests__/config.test.ts index bb21e8509..23b3dd346 100644 --- a/backend/src/__tests__/config.test.ts +++ b/backend/src/__tests__/config.test.ts @@ -51,8 +51,7 @@ describe('Mempool Backend Config', () => { MAX_PUSH_TX_SIZE_WEIGHT: 400000, ALLOW_UNREACHABLE: true, PRICE_UPDATES_PER_HOUR: 1, - MAX_TRACKED_ADDRESSES: 1, - MIN_RECOMMENDED_FEE: 1, + MAX_TRACKED_ADDRESSES: 1 }); expect(config.ELECTRUM).toStrictEqual({ HOST: '127.0.0.1', PORT: 3306, TLS_ENABLED: true }); diff --git a/backend/src/api/fee-api.ts b/backend/src/api/fee-api.ts index 2a1a26efe..2edb8c0e4 100644 --- a/backend/src/api/fee-api.ts +++ b/backend/src/api/fee-api.ts @@ -17,7 +17,6 @@ interface RecommendedFees { class FeeApi { constructor() { } - defaultFee = isLiquid ? 0.1 : config.MEMPOOL.MIN_RECOMMENDED_FEE; minimumIncrement = isLiquid ? 0.1 : 1; public getRecommendedFee(): RecommendedFees { @@ -35,9 +34,9 @@ class FeeApi { return this.calculateRecommendedFee(pBlocks, mPool, minimum, 0.001); } - public calculateRecommendedFee(pBlocks: MempoolBlock[], mPool: IBitcoinApi.MempoolInfo, minimumRecommendation: number = this.defaultFee, minIncrement: number = this.minimumIncrement): RecommendedFees { + public calculateRecommendedFee(pBlocks: MempoolBlock[], mPool: IBitcoinApi.MempoolInfo, minimumRecommendation: number = 0, minIncrement: number = this.minimumIncrement): RecommendedFees { const purgeRate = this.roundUpToNearest(mPool.mempoolminfee * 100000, minIncrement); - const minimumFee = Math.max(purgeRate, minimumRecommendation, config.MEMPOOL.MIN_RECOMMENDED_FEE, minIncrement); + const minimumFee = Math.max(purgeRate, minimumRecommendation, minIncrement); if (!pBlocks.length) { return { @@ -76,7 +75,7 @@ class FeeApi { }; } - private optimizeMedianFee(pBlock: MempoolBlock, nextBlock: MempoolBlock | undefined, previousFee?: number, minFee: number = this.defaultFee, minIncrement: number = this.minimumIncrement): number { + private optimizeMedianFee(pBlock: MempoolBlock, nextBlock: MempoolBlock | undefined, previousFee: number | undefined, minFee: number, minIncrement: number = this.minimumIncrement): number { const useFee = previousFee ? (pBlock.medianFee + previousFee) / 2 : pBlock.medianFee; if (pBlock.blockVSize <= 500000 || pBlock.medianFee < minFee) { return minFee; diff --git a/backend/src/config.ts b/backend/src/config.ts index f3260e788..3fe3db2ee 100644 --- a/backend/src/config.ts +++ b/backend/src/config.ts @@ -43,7 +43,6 @@ interface IConfig { ALLOW_UNREACHABLE: boolean; PRICE_UPDATES_PER_HOUR: number; MAX_TRACKED_ADDRESSES: number; - MIN_RECOMMENDED_FEE: number; }; ESPLORA: { REST_API_URL: string; @@ -215,7 +214,6 @@ const defaults: IConfig = { 'ALLOW_UNREACHABLE': true, 'PRICE_UPDATES_PER_HOUR': 1, 'MAX_TRACKED_ADDRESSES': 1, - 'MIN_RECOMMENDED_FEE': 1, }, 'ESPLORA': { 'REST_API_URL': 'http://127.0.0.1:3000', diff --git a/docker/backend/mempool-config.json b/docker/backend/mempool-config.json index 08b684f82..ee8e329a6 100644 --- a/docker/backend/mempool-config.json +++ b/docker/backend/mempool-config.json @@ -38,8 +38,7 @@ "POOLS_JSON_URL": "__MEMPOOL_POOLS_JSON_URL__", "POOLS_UPDATE_DELAY": __MEMPOOL_POOLS_UPDATE_DELAY__, "PRICE_UPDATES_PER_HOUR": __MEMPOOL_PRICE_UPDATES_PER_HOUR__, - "MAX_TRACKED_ADDRESSES": __MEMPOOL_MAX_TRACKED_ADDRESSES__, - "MIN_RECOMMENDED_FEE": __MEMPOOL_MIN_RECOMMENDED_FEE__ + "MAX_TRACKED_ADDRESSES": __MEMPOOL_MAX_TRACKED_ADDRESSES__ }, "CORE_RPC": { "HOST": "__CORE_RPC_HOST__", diff --git a/docker/backend/start.sh b/docker/backend/start.sh index 88f4b3161..ae0bc616f 100755 --- a/docker/backend/start.sh +++ b/docker/backend/start.sh @@ -40,7 +40,6 @@ __MEMPOOL_MAX_PUSH_TX_SIZE_WEIGHT__=${MEMPOOL_MAX_PUSH_TX_SIZE_WEIGHT:=4000000} __MEMPOOL_ALLOW_UNREACHABLE__=${MEMPOOL_ALLOW_UNREACHABLE:=true} __MEMPOOL_PRICE_UPDATES_PER_HOUR__=${MEMPOOL_PRICE_UPDATES_PER_HOUR:=1} __MEMPOOL_MAX_TRACKED_ADDRESSES__=${MEMPOOL_MAX_TRACKED_ADDRESSES:=1} -__MEMPOOL_MIN_RECOMMENDED_FEE__=${MEMPOOL_MIN_RECOMMENDED_FEE:=1} # CORE_RPC __CORE_RPC_HOST__=${CORE_RPC_HOST:=127.0.0.1} @@ -205,7 +204,6 @@ sed -i "s!__MEMPOOL_MAX_PUSH_TX_SIZE_WEIGHT__!${__MEMPOOL_MAX_PUSH_TX_SIZE_WEIGH sed -i "s!__MEMPOOL_ALLOW_UNREACHABLE__!${__MEMPOOL_ALLOW_UNREACHABLE__}!g" mempool-config.json sed -i "s!__MEMPOOL_PRICE_UPDATES_PER_HOUR__!${__MEMPOOL_PRICE_UPDATES_PER_HOUR__}!g" mempool-config.json sed -i "s!__MEMPOOL_MAX_TRACKED_ADDRESSES__!${__MEMPOOL_MAX_TRACKED_ADDRESSES__}!g" mempool-config.json -sed -i "s!__MEMPOOL_MIN_RECOMMENDED_FEE__!${__MEMPOOL_MIN_RECOMMENDED_FEE__}!g" mempool-config.json sed -i "s!__CORE_RPC_HOST__!${__CORE_RPC_HOST__}!g" mempool-config.json sed -i "s!__CORE_RPC_PORT__!${__CORE_RPC_PORT__}!g" mempool-config.json diff --git a/production/mempool-config.mainnet.json b/production/mempool-config.mainnet.json index 301bd0f3f..87f58f916 100644 --- a/production/mempool-config.mainnet.json +++ b/production/mempool-config.mainnet.json @@ -23,8 +23,7 @@ "MAX_PUSH_TX_SIZE_WEIGHT": 4000000, "ALLOW_UNREACHABLE": true, "PRICE_UPDATES_PER_HOUR": 12, - "MAX_TRACKED_ADDRESSES": 10, - "MIN_RECOMMENDED_TX_FEE": 0.1 + "MAX_TRACKED_ADDRESSES": 10 }, "SYSLOG" : { "MIN_PRIORITY": "debug" diff --git a/production/mempool-config.signet.json b/production/mempool-config.signet.json index d4c45d133..952845ae9 100644 --- a/production/mempool-config.signet.json +++ b/production/mempool-config.signet.json @@ -16,8 +16,7 @@ "DISK_CACHE_BLOCK_INTERVAL": 1, "MAX_PUSH_TX_SIZE_WEIGHT": 4000000, "ALLOW_UNREACHABLE": true, - "MAX_TRACKED_ADDRESSES": 10, - "MIN_RECOMMENDED_TX_FEE": 0.1 + "MAX_TRACKED_ADDRESSES": 10 }, "SYSLOG" : { "MIN_PRIORITY": "debug" diff --git a/production/mempool-config.testnet.json b/production/mempool-config.testnet.json index 54be5c20e..5f9f3abb9 100644 --- a/production/mempool-config.testnet.json +++ b/production/mempool-config.testnet.json @@ -16,8 +16,7 @@ "DISK_CACHE_BLOCK_INTERVAL": 1, "MAX_PUSH_TX_SIZE_WEIGHT": 4000000, "ALLOW_UNREACHABLE": true, - "MAX_TRACKED_ADDRESSES": 10, - "MIN_RECOMMENDED_TX_FEE": 0.1 + "MAX_TRACKED_ADDRESSES": 10 }, "SYSLOG" : { "MIN_PRIORITY": "debug" diff --git a/production/mempool-config.testnet4.json b/production/mempool-config.testnet4.json index 98f255c68..2e79309ed 100644 --- a/production/mempool-config.testnet4.json +++ b/production/mempool-config.testnet4.json @@ -16,8 +16,7 @@ "DISK_CACHE_BLOCK_INTERVAL": 1, "MAX_PUSH_TX_SIZE_WEIGHT": 4000000, "ALLOW_UNREACHABLE": true, - "MAX_TRACKED_ADDRESSES": 10, - "MIN_RECOMMENDED_FEE": 0.1 + "MAX_TRACKED_ADDRESSES": 10 }, "SYSLOG" : { "MIN_PRIORITY": "debug"