From 966adf5963621f787076721ef509c83013f11be6 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Tue, 5 Dec 2023 13:40:17 +0000 Subject: [PATCH] Show accelerated fee rates on mined tx pages --- .../transaction/transaction.component.html | 24 +++++++++++++---- .../transaction/transaction.component.scss | 5 ++++ .../transaction/transaction.component.ts | 27 ++++++++++++++++++- .../src/app/interfaces/node-api.interface.ts | 23 ++++++++++++++++ frontend/src/app/services/api.service.ts | 10 ++++++- 5 files changed, 82 insertions(+), 7 deletions(-) diff --git a/frontend/src/app/components/transaction/transaction.component.html b/frontend/src/app/components/transaction/transaction.component.html index 2d1b31a5a..b496ec6d1 100644 --- a/frontend/src/app/components/transaction/transaction.component.html +++ b/frontend/src/app/components/transaction/transaction.component.html @@ -512,18 +512,32 @@   - + - - Accelerated fee rate - Effective fee rate + + Accelerated fee rate + +
+ +   + Accelerated +
+ + + + Accelerated fee rate + Effective fee rate
- + + +   + Accelerated +
diff --git a/frontend/src/app/components/transaction/transaction.component.scss b/frontend/src/app/components/transaction/transaction.component.scss index 542c2601d..d78edf85b 100644 --- a/frontend/src/app/components/transaction/transaction.component.scss +++ b/frontend/src/app/components/transaction/transaction.component.scss @@ -60,6 +60,11 @@ top: -1px; } +.badge.badge-accelerated { + background-color: #653b9c; + color: white; +} + .btn-small-height { line-height: 1; } diff --git a/frontend/src/app/components/transaction/transaction.component.ts b/frontend/src/app/components/transaction/transaction.component.ts index cf111468c..282b50968 100644 --- a/frontend/src/app/components/transaction/transaction.component.ts +++ b/frontend/src/app/components/transaction/transaction.component.ts @@ -21,7 +21,7 @@ import { ApiService } from '../../services/api.service'; import { SeoService } from '../../services/seo.service'; import { StorageService } from '../../services/storage.service'; import { seoDescriptionNetwork } from '../../shared/common.utils'; -import { BlockExtended, CpfpInfo, RbfTree, MempoolPosition, DifficultyAdjustment } from '../../interfaces/node-api.interface'; +import { BlockExtended, CpfpInfo, RbfTree, MempoolPosition, DifficultyAdjustment, Acceleration } from '../../interfaces/node-api.interface'; import { LiquidUnblinding } from './liquid-ublinding'; import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe'; import { Price, PriceService } from '../../services/price.service'; @@ -49,6 +49,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { fetchCpfpSubscription: Subscription; fetchRbfSubscription: Subscription; fetchCachedTxSubscription: Subscription; + fetchAccelerationSubscription: Subscription; txReplacedSubscription: Subscription; txRbfInfoSubscription: Subscription; mempoolPositionSubscription: Subscription; @@ -62,12 +63,14 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { rbfReplaces: string[]; rbfInfo: RbfTree; cpfpInfo: CpfpInfo | null; + accelerationInfo: Acceleration | null = null; sigops: number | null; adjustedVsize: number | null; showCpfpDetails = false; fetchCpfp$ = new Subject(); fetchRbfHistory$ = new Subject(); fetchCachedTx$ = new Subject(); + fetchAcceleration$ = new Subject(); isCached: boolean = false; now = Date.now(); da$: Observable; @@ -238,6 +241,24 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { } }); + this.fetchAccelerationSubscription = this.fetchAcceleration$.pipe( + tap(() => { + this.accelerationInfo = null; + }), + switchMap((blockHash: string) => { + return this.apiService.getAccelerationHistory$({ blockHash }); + }), + catchError(() => { + return of(null); + }) + ).subscribe((accelerationHistory) => { + for (const acceleration of accelerationHistory) { + if (acceleration.txid === this.txId) { + this.accelerationInfo = acceleration; + } + } + }); + this.mempoolPositionSubscription = this.stateService.mempoolTxPosition$.subscribe(txPosition => { this.now = Date.now(); if (txPosition && txPosition.txid === this.txId && txPosition.position) { @@ -365,6 +386,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { this.getTransactionTime(); } } else { + this.fetchAcceleration$.next(tx.status.block_hash); this.transactionTime = 0; } @@ -417,6 +439,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { }; this.stateService.markBlock$.next({ blockHeight: block.height }); this.audioService.playSound('magic'); + this.fetchAcceleration$.next(block.id); } }); @@ -585,6 +608,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { this.rbfInfo = null; this.rbfReplaces = []; this.showCpfpDetails = false; + this.accelerationInfo = null; this.txInBlockIndex = null; this.mempoolPosition = null; document.body.scrollTo(0, 0); @@ -664,6 +688,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { this.fetchCpfpSubscription.unsubscribe(); this.fetchRbfSubscription.unsubscribe(); this.fetchCachedTxSubscription.unsubscribe(); + this.fetchAccelerationSubscription.unsubscribe(); this.txReplacedSubscription.unsubscribe(); this.txRbfInfoSubscription.unsubscribe(); this.queryParamsSubscription.unsubscribe(); diff --git a/frontend/src/app/interfaces/node-api.interface.ts b/frontend/src/app/interfaces/node-api.interface.ts index 08de11a6a..8b98b6761 100644 --- a/frontend/src/app/interfaces/node-api.interface.ts +++ b/frontend/src/app/interfaces/node-api.interface.ts @@ -302,3 +302,26 @@ export interface INode { funding_balance?: number; closing_balance?: number; } + +export interface Acceleration { + txid: string; + status: 'requested' | 'accelerating' | 'mined' | 'completed' | 'failed'; + pools: number[]; + feePaid: number; + added: number; // timestamp + lastUpdated: number; // timestamp + baseFee: number; + vsizeFee: number; + effectiveFee: number; + effectiveVsize: number; + feeDelta: number; + blockHash: string; + blockHeight: number; +} + +export interface AccelerationHistoryParams { + timeframe?: string, + status?: string, + pool?: string, + blockHash?: string, +} \ No newline at end of file diff --git a/frontend/src/app/services/api.service.ts b/frontend/src/app/services/api.service.ts index 5cdf3d21a..854d15c2a 100644 --- a/frontend/src/app/services/api.service.ts +++ b/frontend/src/app/services/api.service.ts @@ -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 } from '../interfaces/node-api.interface'; + PoolStat, BlockExtended, TransactionStripped, RewardStats, AuditScore, BlockSizesAndWeights, RbfTree, BlockAudit, Acceleration, AccelerationHistoryParams } from '../interfaces/node-api.interface'; import { BehaviorSubject, Observable, catchError, filter, of, shareReplay, take, tap } from 'rxjs'; import { StateService } from './state.service'; import { IBackendInfo, WebsocketResponse } from '../interfaces/websocket.interface'; @@ -428,4 +428,12 @@ export class ApiService { accelerate$(txInput: string, userBid: number) { return this.httpClient.post(`${SERVICES_API_PREFIX}/accelerator/accelerate`, { txInput: txInput, userBid: userBid }); } + + getAccelerations$(): Observable { + return this.httpClient.get(`${SERVICES_API_PREFIX}/accelerator/accelerations`); + } + + getAccelerationHistory$(params: AccelerationHistoryParams): Observable { + return this.httpClient.get(`${SERVICES_API_PREFIX}/accelerator/accelerations/history`, { params: { ...params } }); + } }