diff --git a/backend/src/api/mining/mining-routes.ts b/backend/src/api/mining/mining-routes.ts index abf2fd2d5..3492114b5 100644 --- a/backend/src/api/mining/mining-routes.ts +++ b/backend/src/api/mining/mining-routes.ts @@ -39,6 +39,7 @@ class MiningRoutes { .get(config.MEMPOOL.API_URL_PREFIX + 'accelerations/pool/:slug', this.$getAccelerationsByPool) .get(config.MEMPOOL.API_URL_PREFIX + 'accelerations/block/:height', this.$getAccelerationsByHeight) .get(config.MEMPOOL.API_URL_PREFIX + 'accelerations/recent/:interval', this.$getRecentAccelerations) + .get(config.MEMPOOL.API_URL_PREFIX + 'accelerations/total', this.$getAccelerationTotals) ; } @@ -410,6 +411,21 @@ class MiningRoutes { res.status(500).send(e instanceof Error ? e.message : e); } } + + private async $getAccelerationTotals(req: Request, res: Response): Promise { + try { + res.header('Pragma', 'public'); + res.header('Cache-control', 'public'); + res.setHeader('Expires', new Date(Date.now() + 1000 * 60).toUTCString()); + if (!config.MEMPOOL_SERVICES.ACCELERATIONS || ['testnet', 'signet', 'liquidtestnet', 'liquid'].includes(config.MEMPOOL.NETWORK)) { + res.status(400).send('Acceleration data is not available.'); + return; + } + res.status(200).send(await AccelerationRepository.$getAccelerationTotals(req.query.pool, req.query.interval)); + } catch (e) { + res.status(500).send(e instanceof Error ? e.message : e); + } + } } export default new MiningRoutes(); diff --git a/backend/src/repositories/AccelerationRepository.ts b/backend/src/repositories/AccelerationRepository.ts index 4a3ee3c89..1c91df050 100644 --- a/backend/src/repositories/AccelerationRepository.ts +++ b/backend/src/repositories/AccelerationRepository.ts @@ -118,6 +118,45 @@ class AccelerationRepository { } } + public async $getAccelerationTotals(poolSlug: string | null = null, interval: string | null = null): Promise<{ cost: number, count: number }> { + interval = Common.getSqlInterval(interval); + + if (!config.MEMPOOL_SERVICES.ACCELERATIONS) { + return { cost: 0, count: 0 }; + } + + let query = ` + SELECT SUM(boost_cost) as total_cost, COUNT(txid) as count FROM accelerations + JOIN pools on pools.unique_id = accelerations.pool + `; + let params: any[] = []; + let hasFilter = false; + + if (interval) { + query += ` WHERE accelerations.added BETWEEN DATE_SUB(NOW(), INTERVAL ${interval}) AND NOW() `; + hasFilter = true; + } + if (poolSlug != null) { + if (hasFilter) { + query += ` AND pools.slug = ? `; + } else { + query += ` WHERE pools.slug = ? `; + } + params.push(poolSlug); + } + + try { + const [rows] = await DB.query(query, params) as RowDataPacket[][]; + return { + cost: rows[0]?.total_cost || 0, + count: rows[0]?.count || 0, + }; + } catch (e) { + logger.err(`Cannot query acceleration totals. Reason: ` + (e instanceof Error ? e.message : e)); + throw e; + } + } + public async $getLastSyncedHeight(): Promise { try { const [rows] = await DB.query(` diff --git a/frontend/src/app/components/pool/pool.component.html b/frontend/src/app/components/pool/pool.component.html index 98d1d937b..257df8280 100644 --- a/frontend/src/app/components/pool/pool.component.html +++ b/frontend/src/app/components/pool/pool.component.html @@ -85,10 +85,9 @@
- - - - + - - - - - - - - - - - +
+ +
@@ -111,57 +110,10 @@
- - - - - - - - - - - - - -
RewardHashrate (24h)Avg Health
{{ poolStats.estimatedHashrate | amountShortener : 1 : 'H/s' }}{{ poolStats.avgBlockHealth }}% - - Unknown - -
-
- - - - - - - - - - - - - -
Blocks (24h)1wAll
{{ formatNumber(poolStats.blockCount['24h'], this.locale, '1.0-0') }} ({{ formatNumber(100 * - poolStats.blockShare['24h'], this.locale, '1.0-0') }}%){{ formatNumber(poolStats.blockCount['1w'], this.locale, '1.0-0') }} ({{ formatNumber(100 * - poolStats.blockShare['1w'], this.locale, '1.0-0') }}%){{ formatNumber(poolStats.blockCount['all'], this.locale, '1.0-0') }} ({{ formatNumber(100 * - poolStats.blockShare['all'], this.locale, '1.0-0') }}%)
-
+ +
diff --git a/frontend/src/app/components/pool/pool.component.ts b/frontend/src/app/components/pool/pool.component.ts index 4457814c3..27a705054 100644 --- a/frontend/src/app/components/pool/pool.component.ts +++ b/frontend/src/app/components/pool/pool.component.ts @@ -1,8 +1,8 @@ import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { echarts, EChartsOption } from '../../graphs/echarts'; -import { BehaviorSubject, Observable, of, timer } from 'rxjs'; -import { catchError, distinctUntilChanged, map, share, switchMap, tap } from 'rxjs/operators'; +import { BehaviorSubject, Observable, combineLatest, of, timer } from 'rxjs'; +import { catchError, distinctUntilChanged, filter, map, share, switchMap, tap } from 'rxjs/operators'; import { BlockExtended, PoolStat } from '../../interfaces/node-api.interface'; import { ApiService } from '../../services/api.service'; import { StateService } from '../../services/state.service'; @@ -10,6 +10,11 @@ import { selectPowerOfTen } from '../../bitcoin.utils'; import { formatNumber } from '@angular/common'; import { SeoService } from '../../services/seo.service'; +interface AccelerationTotal { + cost: number, + count: number, +} + @Component({ selector: 'app-pool', templateUrl: './pool.component.html', @@ -25,6 +30,7 @@ export class PoolComponent implements OnInit { formatNumber = formatNumber; poolStats$: Observable; blocks$: Observable; + oobFees$: Observable; isLoading = true; chartOptions: EChartsOption = {}; @@ -111,6 +117,17 @@ export class PoolComponent implements OnInit { map(() => this.blocks), share(), ); + + this.oobFees$ = this.route.params.pipe(map((params) => params.slug)).pipe( + switchMap(slug => { + return combineLatest([ + this.apiService.getAccelerationTotals$(this.slug, '1w'), + this.apiService.getAccelerationTotals$(this.slug, '1m'), + this.apiService.getAccelerationTotals$(this.slug), + ]); + }), + filter(oob => oob.length === 3 && oob[2].count > 0) + ); } prepareChartOptions(data) { diff --git a/frontend/src/app/services/api.service.ts b/frontend/src/app/services/api.service.ts index f393c4d57..8b3b693f3 100644 --- a/frontend/src/app/services/api.service.ts +++ b/frontend/src/app/services/api.service.ts @@ -477,4 +477,18 @@ export class ApiService { this.apiBaseUrl + this.apiBasePath + '/api/v1/accelerations/interval' + (interval !== undefined ? `/${interval}` : '') ); } + + getAccelerationTotals$(pool?: string, interval?: string): Observable<{ cost: number, count: number }> { + const queryParams = new URLSearchParams(); + if (pool) { + queryParams.append('pool', pool); + } + if (interval) { + queryParams.append('interval', interval); + } + const queryString = queryParams.toString(); + return this.httpClient.get<{ cost: number, count: number }>( + this.apiBaseUrl + this.apiBasePath + '/api/v1/accelerations/total' + (queryString?.length ? '?' + queryString : '') + ); + } }