From 078c7ac22861b83252fb54dc61dd00f02aa8314b Mon Sep 17 00:00:00 2001 From: nymkappa Date: Thu, 14 Apr 2022 15:37:03 +0900 Subject: [PATCH] Add /api/v1/mining/blocks/fee-rates/{interval} API --- backend/src/api/mining.ts | 12 ++++++- backend/src/index.ts | 1 + backend/src/repositories/BlocksRepository.ts | 35 ++++++++++++++++++++ backend/src/routes.ts | 16 +++++++++ 4 files changed, 63 insertions(+), 1 deletion(-) diff --git a/backend/src/api/mining.ts b/backend/src/api/mining.ts index 201813899..94191a09f 100644 --- a/backend/src/api/mining.ts +++ b/backend/src/api/mining.ts @@ -15,7 +15,7 @@ class Mining { } /** - * Get historical block reward and total fee + * Get historical block total fee */ public async $getHistoricalBlockFees(interval: string | null = null): Promise { return await BlocksRepository.$getHistoricalBlockFees( @@ -34,6 +34,16 @@ class Mining { ); } + /** + * Get historical block fee rates percentiles + */ + public async $getHistoricalBlockFeeRates(interval: string | null = null): Promise { + return await BlocksRepository.$getHistoricalBlockFeeRates( + this.getTimeRange(interval), + Common.getSqlInterval(interval) + ); + } + /** * Generate high level overview of the pool ranks and general stats */ diff --git a/backend/src/index.ts b/backend/src/index.ts index 943448e3a..89131aed8 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -326,6 +326,7 @@ class Server { .get(config.MEMPOOL.API_URL_PREFIX + 'mining/reward-stats/:blockCount', routes.$getRewardStats) .get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/fees/:interval', routes.$getHistoricalBlockFees) .get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/rewards/:interval', routes.$getHistoricalBlockRewards) + .get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/fee-rates/:interval', routes.$getHistoricalBlockFeeRates) ; } diff --git a/backend/src/repositories/BlocksRepository.ts b/backend/src/repositories/BlocksRepository.ts index 8e96a0c38..e495f1f94 100644 --- a/backend/src/repositories/BlocksRepository.ts +++ b/backend/src/repositories/BlocksRepository.ts @@ -427,6 +427,41 @@ class BlocksRepository { throw e; } } + + /** + * Get the historical averaged block fee rate percentiles + */ + public async $getHistoricalBlockFeeRates(div: number, interval: string | null): Promise { + let connection; + try { + connection = await DB.getConnection(); + + let query = `SELECT CAST(AVG(UNIX_TIMESTAMP(blockTimestamp)) as INT) as timestamp, + CAST(AVG(JSON_EXTRACT(fee_span, '$[0]')) as INT) as avg_fee_0, + CAST(AVG(JSON_EXTRACT(fee_span, '$[1]')) as INT) as avg_fee_10, + CAST(AVG(JSON_EXTRACT(fee_span, '$[2]')) as INT) as avg_fee_25, + CAST(AVG(JSON_EXTRACT(fee_span, '$[3]')) as INT) as avg_fee_50, + CAST(AVG(JSON_EXTRACT(fee_span, '$[4]')) as INT) as avg_fee_75, + CAST(AVG(JSON_EXTRACT(fee_span, '$[5]')) as INT) as avg_fee_90, + CAST(AVG(JSON_EXTRACT(fee_span, '$[6]')) as INT) as avg_fee_100 + FROM blocks`; + + if (interval !== null) { + query += ` WHERE blockTimestamp BETWEEN DATE_SUB(NOW(), INTERVAL ${interval}) AND NOW()`; + } + + query += ` GROUP BY UNIX_TIMESTAMP(blockTimestamp) DIV ${div}`; + + const [rows]: any = await connection.query(query); + connection.release(); + + return rows; + } catch (e) { + connection.release(); + logger.err('Cannot generate block fee rates history. Reason: ' + (e instanceof Error ? e.message : e)); + throw e; + } + } } export default new BlocksRepository(); diff --git a/backend/src/routes.ts b/backend/src/routes.ts index 9d4adb796..2b56fd8b3 100644 --- a/backend/src/routes.ts +++ b/backend/src/routes.ts @@ -670,6 +670,22 @@ class Routes { } } + public async $getHistoricalBlockFeeRates(req: Request, res: Response) { + try { + const blockFees = await mining.$getHistoricalBlockFeeRates(req.params.interval ?? null); + const oldestIndexedBlockTimestamp = await BlocksRepository.$oldestBlockTimestamp(); + res.header('Pragma', 'public'); + res.header('Cache-control', 'public'); + res.setHeader('Expires', new Date(Date.now() + 1000 * 300).toUTCString()); + res.json({ + oldestIndexedBlockTimestamp: oldestIndexedBlockTimestamp, + blockFees: blockFees, + }); + } catch (e) { + res.status(500).send(e instanceof Error ? e.message : e); + } + } + public async getBlock(req: Request, res: Response) { try { const result = await bitcoinApi.$getBlock(req.params.hash);