Show accelerated fee rates on mined tx pages
This commit is contained in:
		
							parent
							
								
									ae7b17c4fd
								
							
						
					
					
						commit
						966adf5963
					
				| @ -512,18 +512,32 @@ | ||||
|           <app-fee-rate [fee]="tx.feePerVsize"></app-fee-rate> | ||||
|           <ng-template [ngIf]="tx?.status?.confirmed"> | ||||
|               | ||||
|             <app-tx-fee-rating *ngIf="tx.fee && !hasEffectiveFeeRate" [tx]="tx"></app-tx-fee-rating> | ||||
|             <app-tx-fee-rating *ngIf="tx.fee && !hasEffectiveFeeRate && !accelerationInfo" [tx]="tx"></app-tx-fee-rating> | ||||
|           </ng-template> | ||||
|         </td> | ||||
|       </tr> | ||||
|       <tr *ngIf="cpfpInfo && hasEffectiveFeeRate"> | ||||
|         <td *ngIf="tx.acceleration" i18n="transaction.accelerated-fee-rate|Accelerated transaction fee rate">Accelerated fee rate</td> | ||||
|         <td *ngIf="!tx.acceleration" i18n="transaction.effective-fee-rate|Effective transaction fee rate">Effective fee rate</td> | ||||
|       <tr *ngIf="!hasEffectiveFeeRate && accelerationInfo"> | ||||
|         <td i18n="transaction.accelerated-fee-rate|Accelerated transaction fee rate">Accelerated fee rate</td> | ||||
|         <td> | ||||
|           <div class="effective-fee-container"> | ||||
|             <app-fee-rate [fee]="accelerationInfo.effectiveFee + accelerationInfo.feePaid - accelerationInfo.baseFee - accelerationInfo.vsizeFee" [weight]="accelerationInfo.effectiveVsize * 4"></app-fee-rate> | ||||
|               | ||||
|             <span class="badge badge-accelerated" i18n="transaction.audit.accelerated">Accelerated</span> | ||||
|           </div> | ||||
|         </td> | ||||
|       </tr> | ||||
|       <tr *ngIf="!accelerationInfo && cpfpInfo && hasEffectiveFeeRate"> | ||||
|         <td *ngIf="tx.acceleration || accelerationInfo" i18n="transaction.accelerated-fee-rate|Accelerated transaction fee rate">Accelerated fee rate</td> | ||||
|         <td *ngIf="!(tx.acceleration || accelerationInfo)" i18n="transaction.effective-fee-rate|Effective transaction fee rate">Effective fee rate</td> | ||||
|         <td> | ||||
|           <div class="effective-fee-container"> | ||||
|             <app-fee-rate [fee]="tx.effectiveFeePerVsize"></app-fee-rate> | ||||
|             <ng-template [ngIf]="tx?.status?.confirmed"> | ||||
|               <app-tx-fee-rating class="ml-2 mr-2 effective-fee-rating" *ngIf="tx.fee || tx.effectiveFeePerVsize" [tx]="tx"></app-tx-fee-rating> | ||||
|               <app-tx-fee-rating class="ml-2 mr-2 effective-fee-rating" *ngIf="!accelerationInfo && (tx.fee || tx.effectiveFeePerVsize)" [tx]="tx"></app-tx-fee-rating> | ||||
|               <ng-template [ngIf]="accelerationInfo"> | ||||
|                   | ||||
|                 <span class="badge badge-accelerated" i18n="transaction.audit.accelerated">Accelerated</span> | ||||
|               </ng-template> | ||||
|             </ng-template> | ||||
|           </div> | ||||
|           <button *ngIf="cpfpInfo.bestDescendant || cpfpInfo.descendants?.length || cpfpInfo.ancestors?.length" type="button" class="btn btn-outline-info btn-sm btn-small-height float-right" (click)="showCpfpDetails = !showCpfpDetails">CPFP <fa-icon [icon]="['fas', 'info-circle']" [fixedWidth]="true"></fa-icon></button> | ||||
|  | ||||
| @ -60,6 +60,11 @@ | ||||
| 	top: -1px; | ||||
| } | ||||
| 
 | ||||
| .badge.badge-accelerated { | ||||
|   background-color: #653b9c; | ||||
|   color: white; | ||||
| } | ||||
| 
 | ||||
| .btn-small-height { | ||||
| 	line-height: 1; | ||||
| } | ||||
|  | ||||
| @ -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<string>(); | ||||
|   fetchRbfHistory$ = new Subject<string>(); | ||||
|   fetchCachedTx$ = new Subject<string>(); | ||||
|   fetchAcceleration$ = new Subject<string>(); | ||||
|   isCached: boolean = false; | ||||
|   now = Date.now(); | ||||
|   da$: Observable<DifficultyAdjustment>; | ||||
| @ -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(); | ||||
|  | ||||
| @ -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, | ||||
| } | ||||
| @ -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<any>(`${SERVICES_API_PREFIX}/accelerator/accelerate`, { txInput: txInput, userBid: userBid }); | ||||
|   } | ||||
| 
 | ||||
|   getAccelerations$(): Observable<Acceleration[]> { | ||||
|     return this.httpClient.get<Acceleration[]>(`${SERVICES_API_PREFIX}/accelerator/accelerations`); | ||||
|   } | ||||
| 
 | ||||
|   getAccelerationHistory$(params: AccelerationHistoryParams): Observable<Acceleration[]> { | ||||
|     return this.httpClient.get<Acceleration[]>(`${SERVICES_API_PREFIX}/accelerator/accelerations/history`, { params: { ...params } }); | ||||
|   } | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user