Remove frontend fee calculation and read it from the websocket instead
This commit is contained in:
		
							parent
							
								
									09b2e21fea
								
							
						
					
					
						commit
						f20cf266b6
					
				@ -13,6 +13,7 @@ import config from '../config';
 | 
				
			|||||||
import transactionUtils from './transaction-utils';
 | 
					import transactionUtils from './transaction-utils';
 | 
				
			||||||
import rbfCache from './rbf-cache';
 | 
					import rbfCache from './rbf-cache';
 | 
				
			||||||
import difficultyAdjustment from './difficulty-adjustment';
 | 
					import difficultyAdjustment from './difficulty-adjustment';
 | 
				
			||||||
 | 
					import feeApi from './fee-api';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class WebsocketHandler {
 | 
					class WebsocketHandler {
 | 
				
			||||||
  private wss: WebSocket.Server | undefined;
 | 
					  private wss: WebSocket.Server | undefined;
 | 
				
			||||||
@ -236,6 +237,7 @@ class WebsocketHandler {
 | 
				
			|||||||
    const rbfTransactions = Common.findRbfTransactions(newTransactions, deletedTransactions);
 | 
					    const rbfTransactions = Common.findRbfTransactions(newTransactions, deletedTransactions);
 | 
				
			||||||
    const da = difficultyAdjustment.getDifficultyAdjustment();
 | 
					    const da = difficultyAdjustment.getDifficultyAdjustment();
 | 
				
			||||||
    memPool.handleRbfTransactions(rbfTransactions);
 | 
					    memPool.handleRbfTransactions(rbfTransactions);
 | 
				
			||||||
 | 
					    const recommendedFees = feeApi.getRecommendedFee();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.wss.clients.forEach(async (client: WebSocket) => {
 | 
					    this.wss.clients.forEach(async (client: WebSocket) => {
 | 
				
			||||||
      if (client.readyState !== WebSocket.OPEN) {
 | 
					      if (client.readyState !== WebSocket.OPEN) {
 | 
				
			||||||
@ -249,6 +251,7 @@ class WebsocketHandler {
 | 
				
			|||||||
        response['vBytesPerSecond'] = vBytesPerSecond;
 | 
					        response['vBytesPerSecond'] = vBytesPerSecond;
 | 
				
			||||||
        response['transactions'] = newTransactions.slice(0, 6).map((tx) => Common.stripTransaction(tx));
 | 
					        response['transactions'] = newTransactions.slice(0, 6).map((tx) => Common.stripTransaction(tx));
 | 
				
			||||||
        response['da'] = da;
 | 
					        response['da'] = da;
 | 
				
			||||||
 | 
					        response['fees'] = recommendedFees;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (client['want-mempool-blocks']) {
 | 
					      if (client['want-mempool-blocks']) {
 | 
				
			||||||
@ -413,6 +416,7 @@ class WebsocketHandler {
 | 
				
			|||||||
        'block': block,
 | 
					        'block': block,
 | 
				
			||||||
        'mempoolInfo': memPool.getMempoolInfo(),
 | 
					        'mempoolInfo': memPool.getMempoolInfo(),
 | 
				
			||||||
        'da': difficultyAdjustment.getDifficultyAdjustment(),
 | 
					        'da': difficultyAdjustment.getDifficultyAdjustment(),
 | 
				
			||||||
 | 
					        'fees': feeApi.getRecommendedFee(),
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (mBlocks && client['want-mempool-blocks']) {
 | 
					      if (mBlocks && client['want-mempool-blocks']) {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,21 +1,21 @@
 | 
				
			|||||||
<div class="fee-estimation-wrapper">
 | 
					<div class="fee-estimation-wrapper">
 | 
				
			||||||
  <div class="fee-estimation-container" *ngIf="(isLoadingWebSocket$ | async) === false && (feeEstimations$ | async) as feeEstimations; else loadingFees">
 | 
					  <div class="fee-estimation-container" *ngIf="(isLoadingWebSocket$ | async) === false && (recommendedFees$ | async) as recommendedFees; else loadingFees">
 | 
				
			||||||
    <div class="item">
 | 
					    <div class="item">
 | 
				
			||||||
      <h5 class="card-title" i18n="fees-box.low-priority">Low priority</h5>
 | 
					      <h5 class="card-title" i18n="fees-box.low-priority">Low priority</h5>
 | 
				
			||||||
      <div class="card-text" i18n-ngbTooltip="Transaction fee tooltip" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom">
 | 
					      <div class="card-text" i18n-ngbTooltip="Transaction fee tooltip" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom">
 | 
				
			||||||
        <div class="fee-text">{{ feeEstimations.hourFee }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span></div> <span class="fiat"><app-fiat [value]="feeEstimations.hourFee * 140" ></app-fiat></span>
 | 
					        <div class="fee-text">{{ recommendedFees.hourFee }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span></div> <span class="fiat"><app-fiat [value]="recommendedFees.hourFee * 140" ></app-fiat></span>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div class="item">
 | 
					    <div class="item">
 | 
				
			||||||
      <h5 class="card-title" i18n="fees-box.medium-priority">Medium priority</h5>
 | 
					      <h5 class="card-title" i18n="fees-box.medium-priority">Medium priority</h5>
 | 
				
			||||||
      <div class="card-text" i18n-ngbTooltip="Transaction fee tooltip" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom">
 | 
					      <div class="card-text" i18n-ngbTooltip="Transaction fee tooltip" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom">
 | 
				
			||||||
        <div class="fee-text">{{ feeEstimations.halfHourFee }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span></div> <span class="fiat"><app-fiat [value]="feeEstimations.halfHourFee * 140" ></app-fiat></span>
 | 
					        <div class="fee-text">{{ recommendedFees.halfHourFee }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span></div> <span class="fiat"><app-fiat [value]="recommendedFees.halfHourFee * 140" ></app-fiat></span>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div class="item">
 | 
					    <div class="item">
 | 
				
			||||||
      <h5 class="card-title" i18n="fees-box.high-priority">High priority</h5>
 | 
					      <h5 class="card-title" i18n="fees-box.high-priority">High priority</h5>
 | 
				
			||||||
      <div class="card-text" i18n-ngbTooltip="Transaction fee tooltip" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom">
 | 
					      <div class="card-text" i18n-ngbTooltip="Transaction fee tooltip" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom">
 | 
				
			||||||
        <div class="fee-text">{{ feeEstimations.fastestFee }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span></div> <span class="fiat"><app-fiat [value]="feeEstimations.fastestFee * 140" ></app-fiat></span>
 | 
					        <div class="fee-text">{{ recommendedFees.fastestFee }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span></div> <span class="fiat"><app-fiat [value]="recommendedFees.fastestFee * 140" ></app-fiat></span>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,8 @@
 | 
				
			|||||||
import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
 | 
					import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
 | 
				
			||||||
import { StateService } from 'src/app/services/state.service';
 | 
					import { StateService } from 'src/app/services/state.service';
 | 
				
			||||||
import { map, filter } from 'rxjs/operators';
 | 
					import { map, filter, tap } from 'rxjs/operators';
 | 
				
			||||||
import { merge, Observable } from 'rxjs';
 | 
					import { merge, Observable } from 'rxjs';
 | 
				
			||||||
import { MempoolBlock } from 'src/app/interfaces/websocket.interface';
 | 
					import { MempoolBlock, Recommendedfees } from 'src/app/interfaces/websocket.interface';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface FeeEstimations {
 | 
					interface FeeEstimations {
 | 
				
			||||||
  fastestFee: number;
 | 
					  fastestFee: number;
 | 
				
			||||||
@ -17,8 +17,8 @@ interface FeeEstimations {
 | 
				
			|||||||
  changeDetection: ChangeDetectionStrategy.OnPush,
 | 
					  changeDetection: ChangeDetectionStrategy.OnPush,
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export class FeesBoxComponent implements OnInit {
 | 
					export class FeesBoxComponent implements OnInit {
 | 
				
			||||||
  feeEstimations$: Observable<FeeEstimations>;
 | 
					 | 
				
			||||||
  isLoadingWebSocket$: Observable<boolean>;
 | 
					  isLoadingWebSocket$: Observable<boolean>;
 | 
				
			||||||
 | 
					  recommendedFees$: Observable<Recommendedfees>;
 | 
				
			||||||
  defaultFee: number;
 | 
					  defaultFee: number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor(
 | 
					  constructor(
 | 
				
			||||||
@ -29,40 +29,6 @@ export class FeesBoxComponent implements OnInit {
 | 
				
			|||||||
    this.defaultFee = this.stateService.network === 'liquid' || this.stateService.network === 'liquidtestnet' ? 0.1 : 1;
 | 
					    this.defaultFee = this.stateService.network === 'liquid' || this.stateService.network === 'liquidtestnet' ? 0.1 : 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.isLoadingWebSocket$ = this.stateService.isLoadingWebSocket$;
 | 
					    this.isLoadingWebSocket$ = this.stateService.isLoadingWebSocket$;
 | 
				
			||||||
    this.feeEstimations$ = this.stateService.mempoolBlocks$
 | 
					    this.recommendedFees$ = this.stateService.recommendedFees$;
 | 
				
			||||||
      .pipe(
 | 
					 | 
				
			||||||
        map((pBlocks) => {
 | 
					 | 
				
			||||||
          if (!pBlocks.length) {
 | 
					 | 
				
			||||||
            return {
 | 
					 | 
				
			||||||
              'fastestFee': this.defaultFee,
 | 
					 | 
				
			||||||
              'halfHourFee': this.defaultFee,
 | 
					 | 
				
			||||||
              'hourFee': this.defaultFee,
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          const firstMedianFee = this.optimizeMedianFee(pBlocks[0], pBlocks[1]);
 | 
					 | 
				
			||||||
          const secondMedianFee = pBlocks[1] ? this.optimizeMedianFee(pBlocks[1], pBlocks[2], firstMedianFee) : this.defaultFee;
 | 
					 | 
				
			||||||
          const thirdMedianFee = pBlocks[2] ? this.optimizeMedianFee(pBlocks[2], pBlocks[3], secondMedianFee) : this.defaultFee;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          return {
 | 
					 | 
				
			||||||
            'fastestFee': firstMedianFee,
 | 
					 | 
				
			||||||
            'halfHourFee': secondMedianFee,
 | 
					 | 
				
			||||||
            'hourFee': thirdMedianFee,
 | 
					 | 
				
			||||||
          };
 | 
					 | 
				
			||||||
        })
 | 
					 | 
				
			||||||
      );
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					 | 
				
			||||||
  private optimizeMedianFee(pBlock: MempoolBlock, nextBlock: MempoolBlock | undefined, previousFee?: number): number {
 | 
					 | 
				
			||||||
    const useFee = previousFee ? (pBlock.medianFee + previousFee) / 2 : pBlock.medianFee;
 | 
					 | 
				
			||||||
    if (pBlock.blockVSize <= 500000) {
 | 
					 | 
				
			||||||
      return this.defaultFee;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (pBlock.blockVSize <= 950000 && !nextBlock) {
 | 
					 | 
				
			||||||
      const multiplier = (pBlock.blockVSize - 500000) / 500000;
 | 
					 | 
				
			||||||
      return Math.max(Math.round(useFee * multiplier), this.defaultFee);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return Math.ceil(useFee);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -21,6 +21,7 @@ export interface WebsocketResponse {
 | 
				
			|||||||
  loadingIndicators?: ILoadingIndicators;
 | 
					  loadingIndicators?: ILoadingIndicators;
 | 
				
			||||||
  backendInfo?: IBackendInfo;
 | 
					  backendInfo?: IBackendInfo;
 | 
				
			||||||
  da?: DifficultyAdjustment;
 | 
					  da?: DifficultyAdjustment;
 | 
				
			||||||
 | 
					  fees?: Recommendedfees;
 | 
				
			||||||
  'track-tx'?: string;
 | 
					  'track-tx'?: string;
 | 
				
			||||||
  'track-address'?: string;
 | 
					  'track-address'?: string;
 | 
				
			||||||
  'track-asset'?: string;
 | 
					  'track-asset'?: string;
 | 
				
			||||||
@ -65,3 +66,11 @@ export interface IBackendInfo {
 | 
				
			|||||||
  gitCommit: string;
 | 
					  gitCommit: string;
 | 
				
			||||||
  version: string;
 | 
					  version: string;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface Recommendedfees {
 | 
				
			||||||
 | 
					  fastestFee: number;
 | 
				
			||||||
 | 
					  halfHourFee: number;
 | 
				
			||||||
 | 
					  hourFee: number;
 | 
				
			||||||
 | 
					  minimumFee: number;
 | 
				
			||||||
 | 
					  economyFee: number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
 | 
					import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
 | 
				
			||||||
import { ReplaySubject, BehaviorSubject, Subject, fromEvent, Observable } from 'rxjs';
 | 
					import { ReplaySubject, BehaviorSubject, Subject, fromEvent, Observable } from 'rxjs';
 | 
				
			||||||
import { Transaction } from '../interfaces/electrs.interface';
 | 
					import { Transaction } from '../interfaces/electrs.interface';
 | 
				
			||||||
import { IBackendInfo, MempoolBlock, MempoolInfo, ReplacedTransaction, TransactionStripped } from '../interfaces/websocket.interface';
 | 
					import { IBackendInfo, MempoolBlock, MempoolInfo, Recommendedfees, ReplacedTransaction, TransactionStripped } from '../interfaces/websocket.interface';
 | 
				
			||||||
import { BlockExtended, DifficultyAdjustment, OptimizedMempoolStats } from '../interfaces/node-api.interface';
 | 
					import { BlockExtended, DifficultyAdjustment, OptimizedMempoolStats } from '../interfaces/node-api.interface';
 | 
				
			||||||
import { Router, NavigationStart } from '@angular/router';
 | 
					import { Router, NavigationStart } from '@angular/router';
 | 
				
			||||||
import { isPlatformBrowser } from '@angular/common';
 | 
					import { isPlatformBrowser } from '@angular/common';
 | 
				
			||||||
@ -90,6 +90,7 @@ export class StateService {
 | 
				
			|||||||
  previousRetarget$ = new ReplaySubject<number>(1);
 | 
					  previousRetarget$ = new ReplaySubject<number>(1);
 | 
				
			||||||
  backendInfo$ = new ReplaySubject<IBackendInfo>(1);
 | 
					  backendInfo$ = new ReplaySubject<IBackendInfo>(1);
 | 
				
			||||||
  loadingIndicators$ = new ReplaySubject<ILoadingIndicators>(1);
 | 
					  loadingIndicators$ = new ReplaySubject<ILoadingIndicators>(1);
 | 
				
			||||||
 | 
					  recommendedFees$ = new ReplaySubject<Recommendedfees>(1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  live2Chart$ = new Subject<OptimizedMempoolStats>();
 | 
					  live2Chart$ = new Subject<OptimizedMempoolStats>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -263,6 +263,10 @@ export class WebsocketService {
 | 
				
			|||||||
      this.stateService.difficultyAdjustment$.next(response.da);
 | 
					      this.stateService.difficultyAdjustment$.next(response.da);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (response.fees) {
 | 
				
			||||||
 | 
					     this.stateService.recommendedFees$.next(response.fees); 
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (response.backendInfo) {
 | 
					    if (response.backendInfo) {
 | 
				
			||||||
      this.stateService.backendInfo$.next(response.backendInfo);
 | 
					      this.stateService.backendInfo$.next(response.backendInfo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user