From 3e906505361173dbac1dce516176c192ad7d921c Mon Sep 17 00:00:00 2001 From: nymkappa Date: Tue, 3 May 2022 15:44:01 +0900 Subject: [PATCH] Add /api/v1/mining/blocks/sizes-weights/:interval API --- backend/src/api/mining.ts | 20 ++++++++ backend/src/index.ts | 1 + backend/src/repositories/BlocksRepository.ts | 50 ++++++++++++++++++++ backend/src/routes.ts | 18 +++++++ 4 files changed, 89 insertions(+) diff --git a/backend/src/api/mining.ts b/backend/src/api/mining.ts index 0909d6100..cbd412068 100644 --- a/backend/src/api/mining.ts +++ b/backend/src/api/mining.ts @@ -45,6 +45,26 @@ class Mining { ); } + /** + * Get historical block sizes + */ + public async $getHistoricalBlockSizes(interval: string | null = null): Promise { + return await BlocksRepository.$getHistoricalBlockSizes( + this.getTimeRange(interval), + Common.getSqlInterval(interval) + ); + } + + /** + * Get historical block weights + */ + public async $getHistoricalBlockWeights(interval: string | null = null): Promise { + return await BlocksRepository.$getHistoricalBlockWeights( + 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 8004e1ec9..8560064a9 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -323,6 +323,7 @@ class Server { .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) + .get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/sizes-weights/:interval', routes.$getHistoricalBlockSizeAndWeight) ; } diff --git a/backend/src/repositories/BlocksRepository.ts b/backend/src/repositories/BlocksRepository.ts index e04080a9c..0792f130f 100644 --- a/backend/src/repositories/BlocksRepository.ts +++ b/backend/src/repositories/BlocksRepository.ts @@ -509,6 +509,56 @@ class BlocksRepository { throw e; } } + + /** + * Get the historical averaged block sizes + */ + public async $getHistoricalBlockSizes(div: number, interval: string | null): Promise { + try { + let query = `SELECT + CAST(AVG(height) as INT) as avg_height, + CAST(AVG(UNIX_TIMESTAMP(blockTimestamp)) as INT) as timestamp, + CAST(AVG(size) as INT) as avg_size + 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 DB.query(query); + return rows; + } catch (e) { + logger.err('Cannot generate block size and weight history. Reason: ' + (e instanceof Error ? e.message : e)); + throw e; + } + } + + /** + * Get the historical averaged block weights + */ + public async $getHistoricalBlockWeights(div: number, interval: string | null): Promise { + try { + let query = `SELECT + CAST(AVG(height) as INT) as avg_height, + CAST(AVG(UNIX_TIMESTAMP(blockTimestamp)) as INT) as timestamp, + CAST(AVG(weight) as INT) as avg_weight + 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 DB.query(query); + return rows; + } catch (e) { + logger.err('Cannot generate block size and weight 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 d27fab683..83b71d19e 100644 --- a/backend/src/routes.ts +++ b/backend/src/routes.ts @@ -682,6 +682,24 @@ class Routes { } } + public async $getHistoricalBlockSizeAndWeight(req: Request, res: Response) { + try { + const blockSizes = await mining.$getHistoricalBlockSizes(req.params.interval ?? null); + const blockWeights = await mining.$getHistoricalBlockWeights(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, + sizes: blockSizes, + weigths: blockWeights + }); + } 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);