Merge pull request #4736 from mempool/mononaut/accelerator-audit-stats

Show accelerator audit total on block page
This commit is contained in:
wiz 2024-03-09 13:52:39 +09:00 committed by GitHub
commit c3d90d573f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 75 additions and 3 deletions

View File

@ -56,6 +56,9 @@ class AccelerationRepository {
}
public async $getAccelerationInfo(poolSlug: string | null = null, height: number | null = null, interval: string | null = null): Promise<PublicAcceleration[]> {
if (!interval || !['24h', '3d', '1w', '1m'].includes(interval)) {
interval = '1m';
}
interval = Common.getSqlInterval(interval);
if (!config.MEMPOOL_SERVICES.ACCELERATIONS || (interval == null && poolSlug == null && height == null)) {

View File

@ -433,6 +433,9 @@
<td i18n="block.total-fees|Total fees in a block">Total fees</td>
<td>
<app-amount [satoshis]="block.extras.totalFees" digitsInfo="1.2-3" [noFiat]="true"></app-amount>
<span *ngIf="oobFees" class="oobFees" i18n-ngbTooltip="Acceleration Fees" ngbTooltip="Acceleration fees paid out-of-band">
+<app-amount [satoshis]="oobFees" digitsInfo="1.2-4" [noFiat]="true"></app-amount>
</span>
<span *ngIf="blockAudit.feeDelta" class="difference" [class.positive]="blockAudit.feeDelta <= 0" [class.negative]="blockAudit.feeDelta > 0">
{{ blockAudit.feeDelta < 0 ? '+' : '' }}{{ (-blockAudit.feeDelta * 100) | amountShortener: 2 }}%
</span>

View File

@ -288,6 +288,10 @@ h1 {
@media (max-width: 767.98px) {
margin-top: 0.75rem;
}
.oobFees {
color: #653b9c;
}
}
.graph-col {

View File

@ -9,7 +9,7 @@ import { StateService } from '../../services/state.service';
import { SeoService } from '../../services/seo.service';
import { WebsocketService } from '../../services/websocket.service';
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
import { BlockAudit, BlockExtended, TransactionStripped } from '../../interfaces/node-api.interface';
import { AccelerationInfo, BlockAudit, BlockExtended, TransactionStripped } from '../../interfaces/node-api.interface';
import { ApiService } from '../../services/api.service';
import { BlockOverviewGraphComponent } from '../../components/block-overview-graph/block-overview-graph.component';
import { detectWebGL } from '../../shared/graphs.utils';
@ -43,6 +43,7 @@ export class BlockComponent implements OnInit, OnDestroy {
latestBlock: BlockExtended;
latestBlocks: BlockExtended[] = [];
transactions: Transaction[];
oobFees: number = 0;
isLoadingTransactions = true;
strippedTransactions: TransactionStripped[];
overviewTransitionDirection: string;
@ -85,6 +86,7 @@ export class BlockComponent implements OnInit, OnDestroy {
timeLtr: boolean;
childChangeSubscription: Subscription;
auditPrefSubscription: Subscription;
oobSubscription: Subscription;
priceSubscription: Subscription;
blockConversion: Price;
@ -168,6 +170,7 @@ export class BlockComponent implements OnInit, OnDestroy {
this.page = 1;
this.error = undefined;
this.fees = undefined;
this.oobFees = 0;
if (history.state.data && history.state.data.blockHeight) {
this.blockHeight = history.state.data.blockHeight;
@ -446,7 +449,7 @@ export class BlockComponent implements OnInit, OnDestroy {
inBlock[tx.txid] = true;
}
blockAudit.feeDelta = blockAudit.expectedFees > 0 ? (blockAudit.expectedFees - this.block.extras.totalFees) / blockAudit.expectedFees : 0;
blockAudit.feeDelta = blockAudit.expectedFees > 0 ? (blockAudit.expectedFees - (this.block.extras.totalFees + this.oobFees)) / blockAudit.expectedFees : 0;
blockAudit.weightDelta = blockAudit.expectedWeight > 0 ? (blockAudit.expectedWeight - this.block.weight) / blockAudit.expectedWeight : 0;
blockAudit.txDelta = blockAudit.template.length > 0 ? (blockAudit.template.length - this.block.tx_count) / blockAudit.template.length : 0;
this.blockAudit = blockAudit;
@ -462,6 +465,32 @@ export class BlockComponent implements OnInit, OnDestroy {
this.setupBlockGraphs();
});
this.oobSubscription = block$.pipe(
switchMap((block) => this.apiService.getAccelerationsByHeight$(block.height)
.pipe(
map(accelerations => {
return { block, accelerations };
}),
catchError((err) => {
return of({ block, accelerations: [] });
}))
),
).subscribe(({ block, accelerations}) => {
let totalFees = 0;
for (const acc of accelerations) {
totalFees += acc.boost_cost;
}
this.oobFees = totalFees;
if (block && this.block && this.blockAudit && block?.height === this.block?.height) {
this.blockAudit.feeDelta = this.blockAudit.expectedFees > 0 ? (this.blockAudit.expectedFees - (this.block.extras.totalFees + this.oobFees)) / this.blockAudit.expectedFees : 0;
}
},
(error) => {
this.error = error;
this.isLoadingBlock = false;
this.isLoadingOverview = false;
});
this.networkChangedSubscription = this.stateService.networkChanged$
.subscribe((network) => this.network = network);
@ -529,6 +558,7 @@ export class BlockComponent implements OnInit, OnDestroy {
this.unsubscribeNextBlockSubscriptions();
this.childChangeSubscription?.unsubscribe();
this.priceSubscription?.unsubscribe();
this.oobSubscription?.unsubscribe();
}
unsubscribeNextBlockSubscriptions() {

View File

@ -403,4 +403,18 @@ export interface AccelerationHistoryParams {
blockHeight?: number;
page?: number;
pageLength?: number;
}
export interface AccelerationInfo {
txid: string,
height: number,
pool: {
id: number,
slug: string,
name: string,
},
effective_vsize: number,
effective_fee: number,
boost_rate: number,
boost_cost: number,
}

View File

@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';
import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http';
import { CpfpInfo, OptimizedMempoolStats, AddressInformation, LiquidPegs, ITranslators,
PoolStat, BlockExtended, TransactionStripped, RewardStats, AuditScore, BlockSizesAndWeights, RbfTree, BlockAudit, Acceleration, AccelerationHistoryParams, CurrentPegs, AuditStatus, FederationAddress, FederationUtxo, RecentPeg, PegsVolume } from '../interfaces/node-api.interface';
PoolStat, BlockExtended, TransactionStripped, RewardStats, AuditScore, BlockSizesAndWeights, RbfTree, BlockAudit, Acceleration, AccelerationHistoryParams, CurrentPegs, AuditStatus, FederationAddress, FederationUtxo, RecentPeg, PegsVolume, AccelerationInfo } from '../interfaces/node-api.interface';
import { BehaviorSubject, Observable, catchError, filter, of, shareReplay, take, tap } from 'rxjs';
import { StateService } from './state.service';
import { Transaction } from '../interfaces/electrs.interface';
@ -424,4 +424,22 @@ export class ApiService {
(timestamp ? `?timestamp=${timestamp}` : '')
);
}
getAccelerationsByPool$(slug: string): Observable<AccelerationInfo[]> {
return this.httpClient.get<AccelerationInfo[]>(
this.apiBaseUrl + this.apiBasePath + `/api/v1/accelerations/pool/${slug}`
);
}
getAccelerationsByHeight$(height: number): Observable<AccelerationInfo[]> {
return this.httpClient.get<AccelerationInfo[]>(
this.apiBaseUrl + this.apiBasePath + `/api/v1/accelerations/block/${height}`
);
}
getRecentAccelerations$(interval: string | undefined): Observable<AccelerationInfo[]> {
return this.httpClient.get<AccelerationInfo[]>(
this.apiBaseUrl + this.apiBasePath + '/api/v1/accelerations/interval' + (interval !== undefined ? `/${interval}` : '')
);
}
}