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