diff --git a/backend/src/api/mining/mining-routes.ts b/backend/src/api/mining/mining-routes.ts index 8f8bbac82..98ac2a0fc 100644 --- a/backend/src/api/mining/mining-routes.ts +++ b/backend/src/api/mining/mining-routes.ts @@ -30,6 +30,7 @@ class MiningRoutes { .get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/fee-rates/:interval', this.$getHistoricalBlockFeeRates) .get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/sizes-weights/:interval', this.$getHistoricalBlockSizeAndWeight) .get(config.MEMPOOL.API_URL_PREFIX + 'mining/difficulty-adjustments/:interval', this.$getDifficultyAdjustments) + .get(config.MEMPOOL.API_URL_PREFIX + 'mining/difficulty-adjustment/:height', this.$getDifficultyAdjustment) .get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/predictions/:interval', this.$getHistoricalBlocksHealth) .get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/audit/scores', this.$getBlockAuditScores) .get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/audit/scores/:height', this.$getBlockAuditScores) @@ -297,6 +298,18 @@ class MiningRoutes { } } + private async $getDifficultyAdjustment(req: Request, res: Response) { + try { + const adjustment = await DifficultyAdjustmentsRepository.$getAdjustmentAtHeight(parseInt(req.params.height, 10)); + res.header('Pragma', 'public'); + res.header('Cache-control', 'public'); + res.setHeader('Expires', new Date(Date.now() + 1000 * 300).toUTCString()); + res.json(adjustment); + } catch (e) { + res.status(e instanceof Error && e.message === 'not found' ? 204 : 500).send(e instanceof Error ? e.message : e); + } + } + private async $getRewardStats(req: Request, res: Response) { try { const response = await mining.$getRewardStats(parseInt(req.params.blockCount, 10)); diff --git a/backend/src/repositories/DifficultyAdjustmentsRepository.ts b/backend/src/repositories/DifficultyAdjustmentsRepository.ts index 0b19cc640..5ad0e3f76 100644 --- a/backend/src/repositories/DifficultyAdjustmentsRepository.ts +++ b/backend/src/repositories/DifficultyAdjustmentsRepository.ts @@ -88,6 +88,22 @@ class DifficultyAdjustmentsRepository { } } + public async $getAdjustmentAtHeight(height: number): Promise { + try { + if (isNaN(height)) { + throw new Error(`argument must be a number`); + } + const [rows] = await DB.query(`SELECT * FROM difficulty_adjustments WHERE height = ?`, [height]); + if (!rows[0]) { + throw new Error(`not found`); + } + return rows[0] as IndexedDifficultyAdjustment; + } catch (e: any) { + logger.err(`Cannot get difficulty adjustment from the database. Reason: ${e instanceof Error ? e.message : e}`, logger.tags.mining); + throw e; + } + } + public async $getAdjustmentsHeights(): Promise { try { const [rows]: any[] = await DB.query(`SELECT height FROM difficulty_adjustments`); diff --git a/frontend/src/app/services/api.service.ts b/frontend/src/app/services/api.service.ts index fa52ec707..d1b600cd3 100644 --- a/frontend/src/app/services/api.service.ts +++ b/frontend/src/app/services/api.service.ts @@ -315,6 +315,12 @@ export class ApiService { ); } + getDifficultyAdjustmentByHeight$(height: number): Observable { + return this.httpClient.get( + this.apiBaseUrl + this.apiBasePath + `/api/v1/mining/difficulty-adjustment/${height}` + ); + } + getHistoricalHashrate$(interval: string | undefined): Observable { return this.httpClient.get( this.apiBaseUrl + this.apiBasePath + `/api/v1/mining/hashrate` +