From e3c06eb93bbc14f66801db539c59a32e0781c2da Mon Sep 17 00:00:00 2001 From: natsoni Date: Fri, 23 Aug 2024 15:46:30 +0200 Subject: [PATCH] Add V2 API endpoint for decimal recommended fees --- backend/src/api/bitcoin/bitcoin.routes.ts | 13 +++++++++++++ backend/src/api/fee-api.ts | 22 +++++++++++++++------- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/backend/src/api/bitcoin/bitcoin.routes.ts b/backend/src/api/bitcoin/bitcoin.routes.ts index 6225a9c1d..c4a98010b 100644 --- a/backend/src/api/bitcoin/bitcoin.routes.ts +++ b/backend/src/api/bitcoin/bitcoin.routes.ts @@ -47,6 +47,9 @@ class BitcoinRoutes { .post(config.MEMPOOL.API_URL_PREFIX + 'psbt/addparents', this.postPsbtCompletion) .get(config.MEMPOOL.API_URL_PREFIX + 'blocks-bulk/:from', this.getBlocksByBulk.bind(this)) .get(config.MEMPOOL.API_URL_PREFIX + 'blocks-bulk/:from/:to', this.getBlocksByBulk.bind(this)) + + // V2 API + .get(config.MEMPOOL.API_V2_URL_PREFIX + 'fees/recommended', this.getRecommendedFeesDecimal) ; if (config.MEMPOOL.BACKEND !== 'esplora') { @@ -100,6 +103,16 @@ class BitcoinRoutes { res.json(result); } + private getRecommendedFeesDecimal(req: Request, res: Response) { + if (!mempool.isInSync()) { + res.statusCode = 503; + res.send('Service Unavailable'); + return; + } + const result = feeApi.getRecommendedFee(true); + 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 24fd25a4b..be42b2fa5 100644 --- a/backend/src/api/fee-api.ts +++ b/backend/src/api/fee-api.ts @@ -19,10 +19,12 @@ class FeeApi { defaultFee = isLiquid ? 0.1 : 1; minimumIncrement = isLiquid ? 0.1 : 1; - public getRecommendedFee(): RecommendedFees { + public getRecommendedFee(decimal: boolean = false): RecommendedFees { const pBlocks = projectedBlocks.getMempoolBlocks(); const mPool = mempool.getMempoolInfo(); - const minimumFee = this.roundUpToNearest(mPool.mempoolminfee * 100000, this.minimumIncrement); + const minimumFee = decimal ? + this.roundUpToNearestDecimal(mPool.mempoolminfee * 100000) : + this.roundUpToNearest(mPool.mempoolminfee * 100000, this.minimumIncrement); const defaultMinFee = Math.max(minimumFee, this.defaultFee); if (!pBlocks.length) { @@ -35,9 +37,9 @@ class FeeApi { }; } - 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, decimal); + const secondMedianFee = pBlocks[1] ? this.optimizeMedianFee(pBlocks[1], pBlocks[2], firstMedianFee, decimal) : this.defaultFee; + const thirdMedianFee = pBlocks[2] ? this.optimizeMedianFee(pBlocks[2], pBlocks[3], secondMedianFee, decimal) : this.defaultFee; let fastestFee = Math.max(minimumFee, firstMedianFee); let halfHourFee = Math.max(minimumFee, secondMedianFee); @@ -62,7 +64,7 @@ class FeeApi { }; } - private optimizeMedianFee(pBlock: MempoolBlock, nextBlock: MempoolBlock | undefined, previousFee?: number): number { + private optimizeMedianFee(pBlock: MempoolBlock, nextBlock: MempoolBlock | undefined, previousFee?: number, decimal: boolean = false): number { const useFee = previousFee ? (pBlock.medianFee + previousFee) / 2 : pBlock.medianFee; if (pBlock.blockVSize <= 500000) { return this.defaultFee; @@ -71,12 +73,18 @@ class FeeApi { const multiplier = (pBlock.blockVSize - 500000) / 500000; return Math.max(Math.round(useFee * multiplier), this.defaultFee); } - return this.roundUpToNearest(useFee, this.minimumIncrement); + return decimal ? + this.roundUpToNearestDecimal(useFee) : + this.roundUpToNearest(useFee, this.minimumIncrement); } private roundUpToNearest(value: number, nearest: number): number { return Math.ceil(value / nearest) * nearest; } + + private roundUpToNearestDecimal(value: number): number { + return Number(this.roundUpToNearest(value, 0.1).toFixed(1)); // avoid floating point errors + } } export default new FeeApi();