reduce latest rbf websocket data
This commit is contained in:
		
							parent
							
								
									240afbed95
								
							
						
					
					
						commit
						fa48791c59
					
				@ -6,6 +6,7 @@ import { Common } from "./common";
 | 
				
			|||||||
interface RbfTransaction extends TransactionStripped {
 | 
					interface RbfTransaction extends TransactionStripped {
 | 
				
			||||||
  rbf?: boolean;
 | 
					  rbf?: boolean;
 | 
				
			||||||
  mined?: boolean;
 | 
					  mined?: boolean;
 | 
				
			||||||
 | 
					  fullRbf?: boolean;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface RbfTree {
 | 
					interface RbfTree {
 | 
				
			||||||
@ -17,6 +18,16 @@ interface RbfTree {
 | 
				
			|||||||
  replaces: RbfTree[];
 | 
					  replaces: RbfTree[];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface ReplacementInfo {
 | 
				
			||||||
 | 
					  mined: boolean;
 | 
				
			||||||
 | 
					  fullRbf: boolean;
 | 
				
			||||||
 | 
					  txid: string;
 | 
				
			||||||
 | 
					  oldFee: number;
 | 
				
			||||||
 | 
					  oldVsize: number;
 | 
				
			||||||
 | 
					  newFee: number;
 | 
				
			||||||
 | 
					  newVsize: number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class RbfCache {
 | 
					class RbfCache {
 | 
				
			||||||
  private replacedBy: Map<string, string> = new Map();
 | 
					  private replacedBy: Map<string, string> = new Map();
 | 
				
			||||||
  private replaces: Map<string, string[]> = new Map();
 | 
					  private replaces: Map<string, string[]> = new Map();
 | 
				
			||||||
@ -41,11 +52,15 @@ class RbfCache {
 | 
				
			|||||||
    this.txs.set(newTx.txid, newTxExtended);
 | 
					    this.txs.set(newTx.txid, newTxExtended);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // maintain rbf trees
 | 
					    // maintain rbf trees
 | 
				
			||||||
    let fullRbf = false;
 | 
					    let txFullRbf = false;
 | 
				
			||||||
 | 
					    let treeFullRbf = false;
 | 
				
			||||||
    const replacedTrees: RbfTree[] = [];
 | 
					    const replacedTrees: RbfTree[] = [];
 | 
				
			||||||
    for (const replacedTxExtended of replaced) {
 | 
					    for (const replacedTxExtended of replaced) {
 | 
				
			||||||
      const replacedTx = Common.stripTransaction(replacedTxExtended) as RbfTransaction;
 | 
					      const replacedTx = Common.stripTransaction(replacedTxExtended) as RbfTransaction;
 | 
				
			||||||
      replacedTx.rbf = replacedTxExtended.vin.some((v) => v.sequence < 0xfffffffe);
 | 
					      replacedTx.rbf = replacedTxExtended.vin.some((v) => v.sequence < 0xfffffffe);
 | 
				
			||||||
 | 
					      if (!replacedTx.rbf) {
 | 
				
			||||||
 | 
					        txFullRbf = true;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
      this.replacedBy.set(replacedTx.txid, newTx.txid);
 | 
					      this.replacedBy.set(replacedTx.txid, newTx.txid);
 | 
				
			||||||
      if (this.treeMap.has(replacedTx.txid)) {
 | 
					      if (this.treeMap.has(replacedTx.txid)) {
 | 
				
			||||||
        const treeId = this.treeMap.get(replacedTx.txid);
 | 
					        const treeId = this.treeMap.get(replacedTx.txid);
 | 
				
			||||||
@ -55,7 +70,7 @@ class RbfCache {
 | 
				
			|||||||
          if (tree) {
 | 
					          if (tree) {
 | 
				
			||||||
            tree.interval = newTime - tree?.time;
 | 
					            tree.interval = newTime - tree?.time;
 | 
				
			||||||
            replacedTrees.push(tree);
 | 
					            replacedTrees.push(tree);
 | 
				
			||||||
            fullRbf = fullRbf || tree.fullRbf || !tree.tx.rbf;
 | 
					            treeFullRbf = treeFullRbf || tree.fullRbf || !tree.tx.rbf;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
@ -67,15 +82,16 @@ class RbfCache {
 | 
				
			|||||||
          fullRbf: !replacedTx.rbf,
 | 
					          fullRbf: !replacedTx.rbf,
 | 
				
			||||||
          replaces: [],
 | 
					          replaces: [],
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        fullRbf = fullRbf || !replacedTx.rbf;
 | 
					        treeFullRbf = treeFullRbf || !replacedTx.rbf;
 | 
				
			||||||
        this.txs.set(replacedTx.txid, replacedTxExtended);
 | 
					        this.txs.set(replacedTx.txid, replacedTxExtended);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    newTx.fullRbf = txFullRbf;
 | 
				
			||||||
    const treeId = replacedTrees[0].tx.txid;
 | 
					    const treeId = replacedTrees[0].tx.txid;
 | 
				
			||||||
    const newTree = {
 | 
					    const newTree = {
 | 
				
			||||||
      tx: newTx,
 | 
					      tx: newTx,
 | 
				
			||||||
      time: newTime,
 | 
					      time: newTime,
 | 
				
			||||||
      fullRbf,
 | 
					      fullRbf: treeFullRbf,
 | 
				
			||||||
      replaces: replacedTrees
 | 
					      replaces: replacedTrees
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    this.rbfTrees.set(treeId, newTree);
 | 
					    this.rbfTrees.set(treeId, newTree);
 | 
				
			||||||
@ -349,6 +365,27 @@ class RbfCache {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    return tree;
 | 
					    return tree;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public getLatestRbfSummary(): ReplacementInfo[] {
 | 
				
			||||||
 | 
					    const rbfList = this.getRbfTrees(false);
 | 
				
			||||||
 | 
					    return rbfList.slice(0, 6).map(rbfTree => {
 | 
				
			||||||
 | 
					      let oldFee = 0;
 | 
				
			||||||
 | 
					      let oldVsize = 0;
 | 
				
			||||||
 | 
					      for (const replaced of rbfTree.replaces) {
 | 
				
			||||||
 | 
					        oldFee += replaced.tx.fee;
 | 
				
			||||||
 | 
					        oldVsize += replaced.tx.vsize;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return {
 | 
				
			||||||
 | 
					        txid: rbfTree.tx.txid,
 | 
				
			||||||
 | 
					        mined: !!rbfTree.tx.mined,
 | 
				
			||||||
 | 
					        fullRbf: !!rbfTree.tx.fullRbf,
 | 
				
			||||||
 | 
					        oldFee,
 | 
				
			||||||
 | 
					        oldVsize,
 | 
				
			||||||
 | 
					        newFee: rbfTree.tx.fee,
 | 
				
			||||||
 | 
					        newVsize: rbfTree.tx.vsize,
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default new RbfCache();
 | 
					export default new RbfCache();
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@ import { Common } from './common';
 | 
				
			|||||||
import loadingIndicators from './loading-indicators';
 | 
					import loadingIndicators from './loading-indicators';
 | 
				
			||||||
import config from '../config';
 | 
					import config from '../config';
 | 
				
			||||||
import transactionUtils from './transaction-utils';
 | 
					import transactionUtils from './transaction-utils';
 | 
				
			||||||
import rbfCache from './rbf-cache';
 | 
					import rbfCache, { ReplacementInfo } from './rbf-cache';
 | 
				
			||||||
import difficultyAdjustment from './difficulty-adjustment';
 | 
					import difficultyAdjustment from './difficulty-adjustment';
 | 
				
			||||||
import feeApi from './fee-api';
 | 
					import feeApi from './fee-api';
 | 
				
			||||||
import BlocksAuditsRepository from '../repositories/BlocksAuditsRepository';
 | 
					import BlocksAuditsRepository from '../repositories/BlocksAuditsRepository';
 | 
				
			||||||
@ -40,6 +40,7 @@ class WebsocketHandler {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  private socketData: { [key: string]: string } = {};
 | 
					  private socketData: { [key: string]: string } = {};
 | 
				
			||||||
  private serializedInitData: string = '{}';
 | 
					  private serializedInitData: string = '{}';
 | 
				
			||||||
 | 
					  private lastRbfSummary: ReplacementInfo | null = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor() { }
 | 
					  constructor() { }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -225,6 +226,15 @@ class WebsocketHandler {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          if (parsedMessage && parsedMessage['track-rbf-summary'] != null) {
 | 
				
			||||||
 | 
					            if (parsedMessage['track-rbf-summary']) {
 | 
				
			||||||
 | 
					              client['track-rbf-summary'] = true;
 | 
				
			||||||
 | 
					              response['rbfLatestSummary'] = this.socketData['rbfSummary'];
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					              client['track-rbf-summary'] = false;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          if (parsedMessage.action === 'init') {
 | 
					          if (parsedMessage.action === 'init') {
 | 
				
			||||||
            if (!this.socketData['blocks']?.length || !this.socketData['da']) {
 | 
					            if (!this.socketData['blocks']?.length || !this.socketData['da']) {
 | 
				
			||||||
              this.updateSocketData();
 | 
					              this.updateSocketData();
 | 
				
			||||||
@ -395,10 +405,13 @@ class WebsocketHandler {
 | 
				
			|||||||
    const rbfChanges = rbfCache.getRbfChanges();
 | 
					    const rbfChanges = rbfCache.getRbfChanges();
 | 
				
			||||||
    let rbfReplacements;
 | 
					    let rbfReplacements;
 | 
				
			||||||
    let fullRbfReplacements;
 | 
					    let fullRbfReplacements;
 | 
				
			||||||
 | 
					    let rbfSummary;
 | 
				
			||||||
    if (Object.keys(rbfChanges.trees).length) {
 | 
					    if (Object.keys(rbfChanges.trees).length) {
 | 
				
			||||||
      rbfReplacements = rbfCache.getRbfTrees(false);
 | 
					      rbfReplacements = rbfCache.getRbfTrees(false);
 | 
				
			||||||
      fullRbfReplacements = rbfCache.getRbfTrees(true);
 | 
					      fullRbfReplacements = rbfCache.getRbfTrees(true);
 | 
				
			||||||
 | 
					      rbfSummary = rbfCache.getLatestRbfSummary();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (const deletedTx of deletedTransactions) {
 | 
					    for (const deletedTx of deletedTransactions) {
 | 
				
			||||||
      rbfCache.evict(deletedTx.txid);
 | 
					      rbfCache.evict(deletedTx.txid);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -409,7 +422,7 @@ class WebsocketHandler {
 | 
				
			|||||||
    const latestTransactions = newTransactions.slice(0, 6).map((tx) => Common.stripTransaction(tx));
 | 
					    const latestTransactions = newTransactions.slice(0, 6).map((tx) => Common.stripTransaction(tx));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // update init data
 | 
					    // update init data
 | 
				
			||||||
    this.updateSocketDataFields({
 | 
					    const socketDataFields = {
 | 
				
			||||||
      'mempoolInfo': mempoolInfo,
 | 
					      'mempoolInfo': mempoolInfo,
 | 
				
			||||||
      'vBytesPerSecond': vBytesPerSecond,
 | 
					      'vBytesPerSecond': vBytesPerSecond,
 | 
				
			||||||
      'mempool-blocks': mBlocks,
 | 
					      'mempool-blocks': mBlocks,
 | 
				
			||||||
@ -417,7 +430,11 @@ class WebsocketHandler {
 | 
				
			|||||||
      'loadingIndicators': loadingIndicators.getLoadingIndicators(),
 | 
					      'loadingIndicators': loadingIndicators.getLoadingIndicators(),
 | 
				
			||||||
      'da': da?.previousTime ? da : undefined,
 | 
					      'da': da?.previousTime ? da : undefined,
 | 
				
			||||||
      'fees': recommendedFees,
 | 
					      'fees': recommendedFees,
 | 
				
			||||||
    });
 | 
					    };
 | 
				
			||||||
 | 
					    if (rbfSummary) {
 | 
				
			||||||
 | 
					      socketDataFields['rbfSummary'] = rbfSummary;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    this.updateSocketDataFields(socketDataFields);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // cache serialized objects to avoid stringify-ing the same thing for every client
 | 
					    // cache serialized objects to avoid stringify-ing the same thing for every client
 | 
				
			||||||
    const responseCache = { ...this.socketData };
 | 
					    const responseCache = { ...this.socketData };
 | 
				
			||||||
@ -601,6 +618,10 @@ class WebsocketHandler {
 | 
				
			|||||||
        response['rbfLatest'] = getCachedResponse('fullrbfLatest', fullRbfReplacements);
 | 
					        response['rbfLatest'] = getCachedResponse('fullrbfLatest', fullRbfReplacements);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (client['track-rbf-summary'] && rbfSummary) {
 | 
				
			||||||
 | 
					        response['rbfLatestSummary'] = getCachedResponse('rbfLatestSummary', rbfSummary);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if (Object.keys(response).length) {
 | 
					      if (Object.keys(response).length) {
 | 
				
			||||||
        const serializedResponse = this.serializeResponse(response);
 | 
					        const serializedResponse = this.serializeResponse(response);
 | 
				
			||||||
        client.send(serializedResponse);
 | 
					        client.send(serializedResponse);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,8 @@
 | 
				
			|||||||
import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core';
 | 
					import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core';
 | 
				
			||||||
import { combineLatest, merge, Observable, of, Subscription } from 'rxjs';
 | 
					import { combineLatest, merge, Observable, of, Subscription } from 'rxjs';
 | 
				
			||||||
import { filter, map, scan, share, switchMap, tap } from 'rxjs/operators';
 | 
					import { filter, map, scan, share, switchMap } from 'rxjs/operators';
 | 
				
			||||||
import { BlockExtended, OptimizedMempoolStats, RbfTree } from '../interfaces/node-api.interface';
 | 
					import { BlockExtended, OptimizedMempoolStats, RbfTree } from '../interfaces/node-api.interface';
 | 
				
			||||||
import { MempoolInfo, TransactionStripped } from '../interfaces/websocket.interface';
 | 
					import { MempoolInfo, TransactionStripped, ReplacementInfo } from '../interfaces/websocket.interface';
 | 
				
			||||||
import { ApiService } from '../services/api.service';
 | 
					import { ApiService } from '../services/api.service';
 | 
				
			||||||
import { StateService } from '../services/state.service';
 | 
					import { StateService } from '../services/state.service';
 | 
				
			||||||
import { WebsocketService } from '../services/websocket.service';
 | 
					import { WebsocketService } from '../services/websocket.service';
 | 
				
			||||||
@ -25,17 +25,6 @@ interface MempoolStatsData {
 | 
				
			|||||||
  weightPerSecond: any;
 | 
					  weightPerSecond: any;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface ReplacementInfo {
 | 
					 | 
				
			||||||
  tree: RbfTree;
 | 
					 | 
				
			||||||
  mined: boolean;
 | 
					 | 
				
			||||||
  fullRbf: boolean;
 | 
					 | 
				
			||||||
  txid: string;
 | 
					 | 
				
			||||||
  oldFee: number;
 | 
					 | 
				
			||||||
  oldVsize: number;
 | 
					 | 
				
			||||||
  newFee: number;
 | 
					 | 
				
			||||||
  newVsize: number;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Component({
 | 
					@Component({
 | 
				
			||||||
  selector: 'app-dashboard',
 | 
					  selector: 'app-dashboard',
 | 
				
			||||||
  templateUrl: './dashboard.component.html',
 | 
					  templateUrl: './dashboard.component.html',
 | 
				
			||||||
@ -69,13 +58,14 @@ export class DashboardComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  ngOnDestroy(): void {
 | 
					  ngOnDestroy(): void {
 | 
				
			||||||
    this.currencySubscription.unsubscribe();
 | 
					    this.currencySubscription.unsubscribe();
 | 
				
			||||||
 | 
					    this.websocketService.stopTrackRbfSummary();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  ngOnInit(): void {
 | 
					  ngOnInit(): void {
 | 
				
			||||||
    this.isLoadingWebSocket$ = this.stateService.isLoadingWebSocket$;
 | 
					    this.isLoadingWebSocket$ = this.stateService.isLoadingWebSocket$;
 | 
				
			||||||
    this.seoService.resetTitle();
 | 
					    this.seoService.resetTitle();
 | 
				
			||||||
    this.websocketService.want(['blocks', 'stats', 'mempool-blocks', 'live-2h-chart']);
 | 
					    this.websocketService.want(['blocks', 'stats', 'mempool-blocks', 'live-2h-chart']);
 | 
				
			||||||
    this.websocketService.startTrackRbf('all');
 | 
					    this.websocketService.startTrackRbfSummary();
 | 
				
			||||||
    this.network$ = merge(of(''), this.stateService.networkChanged$);
 | 
					    this.network$ = merge(of(''), this.stateService.networkChanged$);
 | 
				
			||||||
    this.mempoolLoadingStatus$ = this.stateService.loadingIndicators$
 | 
					    this.mempoolLoadingStatus$ = this.stateService.loadingIndicators$
 | 
				
			||||||
      .pipe(
 | 
					      .pipe(
 | 
				
			||||||
@ -154,30 +144,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
        }, []),
 | 
					        }, []),
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.replacements$ = this.stateService.rbfLatest$.pipe(
 | 
					    this.replacements$ = this.stateService.rbfLatestSummary$;
 | 
				
			||||||
      switchMap((rbfList) => {
 | 
					 | 
				
			||||||
        const replacements = rbfList.slice(0, 6).map(rbfTree => {
 | 
					 | 
				
			||||||
          let oldFee = 0;
 | 
					 | 
				
			||||||
          let oldVsize = 0;
 | 
					 | 
				
			||||||
          for (const replaced of rbfTree.replaces) {
 | 
					 | 
				
			||||||
            oldFee += replaced.tx.fee;
 | 
					 | 
				
			||||||
            oldVsize += replaced.tx.vsize;
 | 
					 | 
				
			||||||
          }
 | 
					 | 
				
			||||||
          this.checkFullRbf(rbfTree);
 | 
					 | 
				
			||||||
          return {
 | 
					 | 
				
			||||||
            tree: rbfTree,
 | 
					 | 
				
			||||||
            txid: rbfTree.tx.txid,
 | 
					 | 
				
			||||||
            mined: rbfTree.tx.mined,
 | 
					 | 
				
			||||||
            fullRbf: rbfTree.tx.fullRbf,
 | 
					 | 
				
			||||||
            oldFee,
 | 
					 | 
				
			||||||
            oldVsize,
 | 
					 | 
				
			||||||
            newFee: rbfTree.tx.fee,
 | 
					 | 
				
			||||||
            newVsize: rbfTree.tx.vsize,
 | 
					 | 
				
			||||||
          };
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        return of(replacements);
 | 
					 | 
				
			||||||
      })
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.mempoolStats$ = this.stateService.connectionState$
 | 
					    this.mempoolStats$ = this.stateService.connectionState$
 | 
				
			||||||
      .pipe(
 | 
					      .pipe(
 | 
				
			||||||
 | 
				
			|||||||
@ -18,6 +18,7 @@ export interface WebsocketResponse {
 | 
				
			|||||||
  txReplaced?: ReplacedTransaction;
 | 
					  txReplaced?: ReplacedTransaction;
 | 
				
			||||||
  rbfInfo?: RbfTree;
 | 
					  rbfInfo?: RbfTree;
 | 
				
			||||||
  rbfLatest?: RbfTree[];
 | 
					  rbfLatest?: RbfTree[];
 | 
				
			||||||
 | 
					  rbfLatestSummary?: ReplacementInfo[];
 | 
				
			||||||
  utxoSpent?: object;
 | 
					  utxoSpent?: object;
 | 
				
			||||||
  transactions?: TransactionStripped[];
 | 
					  transactions?: TransactionStripped[];
 | 
				
			||||||
  loadingIndicators?: ILoadingIndicators;
 | 
					  loadingIndicators?: ILoadingIndicators;
 | 
				
			||||||
@ -29,6 +30,7 @@ export interface WebsocketResponse {
 | 
				
			|||||||
  'track-asset'?: string;
 | 
					  'track-asset'?: string;
 | 
				
			||||||
  'track-mempool-block'?: number;
 | 
					  'track-mempool-block'?: number;
 | 
				
			||||||
  'track-rbf'?: string;
 | 
					  'track-rbf'?: string;
 | 
				
			||||||
 | 
					  'track-rbf-summary'?: boolean;
 | 
				
			||||||
  'watch-mempool'?: boolean;
 | 
					  'watch-mempool'?: boolean;
 | 
				
			||||||
  'track-bisq-market'?: string;
 | 
					  'track-bisq-market'?: string;
 | 
				
			||||||
  'refresh-blocks'?: boolean;
 | 
					  'refresh-blocks'?: boolean;
 | 
				
			||||||
@ -37,6 +39,16 @@ export interface WebsocketResponse {
 | 
				
			|||||||
export interface ReplacedTransaction extends Transaction {
 | 
					export interface ReplacedTransaction extends Transaction {
 | 
				
			||||||
  txid: string;
 | 
					  txid: string;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface ReplacementInfo {
 | 
				
			||||||
 | 
					  mined: boolean;
 | 
				
			||||||
 | 
					  fullRbf: boolean;
 | 
				
			||||||
 | 
					  txid: string;
 | 
				
			||||||
 | 
					  oldFee: number;
 | 
				
			||||||
 | 
					  oldVsize: number;
 | 
				
			||||||
 | 
					  newFee: number;
 | 
				
			||||||
 | 
					  newVsize: number;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
export interface MempoolBlock {
 | 
					export interface MempoolBlock {
 | 
				
			||||||
  blink?: boolean;
 | 
					  blink?: boolean;
 | 
				
			||||||
  height?: number;
 | 
					  height?: number;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import { Inject, Injectable, PLATFORM_ID, LOCALE_ID } from '@angular/core';
 | 
					import { Inject, Injectable, PLATFORM_ID, LOCALE_ID } from '@angular/core';
 | 
				
			||||||
import { ReplaySubject, BehaviorSubject, Subject, fromEvent, Observable, merge } from 'rxjs';
 | 
					import { ReplaySubject, BehaviorSubject, Subject, fromEvent, Observable, merge } from 'rxjs';
 | 
				
			||||||
import { Transaction } from '../interfaces/electrs.interface';
 | 
					import { Transaction } from '../interfaces/electrs.interface';
 | 
				
			||||||
import { IBackendInfo, MempoolBlock, MempoolBlockDelta, MempoolInfo, Recommendedfees, ReplacedTransaction, TransactionStripped } from '../interfaces/websocket.interface';
 | 
					import { IBackendInfo, MempoolBlock, MempoolBlockDelta, MempoolInfo, Recommendedfees, ReplacedTransaction, ReplacementInfo, TransactionStripped } from '../interfaces/websocket.interface';
 | 
				
			||||||
import { BlockExtended, DifficultyAdjustment, MempoolPosition, OptimizedMempoolStats, RbfTree } from '../interfaces/node-api.interface';
 | 
					import { BlockExtended, DifficultyAdjustment, MempoolPosition, OptimizedMempoolStats, RbfTree } 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';
 | 
				
			||||||
@ -108,6 +108,7 @@ export class StateService {
 | 
				
			|||||||
  txReplaced$ = new Subject<ReplacedTransaction>();
 | 
					  txReplaced$ = new Subject<ReplacedTransaction>();
 | 
				
			||||||
  txRbfInfo$ = new Subject<RbfTree>();
 | 
					  txRbfInfo$ = new Subject<RbfTree>();
 | 
				
			||||||
  rbfLatest$ = new Subject<RbfTree[]>();
 | 
					  rbfLatest$ = new Subject<RbfTree[]>();
 | 
				
			||||||
 | 
					  rbfLatestSummary$ = new Subject<ReplacementInfo[]>();
 | 
				
			||||||
  utxoSpent$ = new Subject<object>();
 | 
					  utxoSpent$ = new Subject<object>();
 | 
				
			||||||
  difficultyAdjustment$ = new ReplaySubject<DifficultyAdjustment>(1);
 | 
					  difficultyAdjustment$ = new ReplaySubject<DifficultyAdjustment>(1);
 | 
				
			||||||
  mempoolTransactions$ = new Subject<Transaction>();
 | 
					  mempoolTransactions$ = new Subject<Transaction>();
 | 
				
			||||||
 | 
				
			|||||||
@ -29,6 +29,7 @@ export class WebsocketService {
 | 
				
			|||||||
  private trackingTxId: string;
 | 
					  private trackingTxId: string;
 | 
				
			||||||
  private isTrackingMempoolBlock = false;
 | 
					  private isTrackingMempoolBlock = false;
 | 
				
			||||||
  private isTrackingRbf = false;
 | 
					  private isTrackingRbf = false;
 | 
				
			||||||
 | 
					  private isTrackingRbfSummary = false;
 | 
				
			||||||
  private trackingMempoolBlock: number;
 | 
					  private trackingMempoolBlock: number;
 | 
				
			||||||
  private latestGitCommit = '';
 | 
					  private latestGitCommit = '';
 | 
				
			||||||
  private onlineCheckTimeout: number;
 | 
					  private onlineCheckTimeout: number;
 | 
				
			||||||
@ -185,6 +186,16 @@ export class WebsocketService {
 | 
				
			|||||||
    this.isTrackingRbf = false;
 | 
					    this.isTrackingRbf = false;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  startTrackRbfSummary() {
 | 
				
			||||||
 | 
					    this.websocketSubject.next({ 'track-rbf-summary': true });
 | 
				
			||||||
 | 
					    this.isTrackingRbfSummary = true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  stopTrackRbfSummary() {
 | 
				
			||||||
 | 
					    this.websocketSubject.next({ 'track-rbf-summary': false });
 | 
				
			||||||
 | 
					    this.isTrackingRbfSummary = false;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  startTrackBisqMarket(market: string) {
 | 
					  startTrackBisqMarket(market: string) {
 | 
				
			||||||
    this.websocketSubject.next({ 'track-bisq-market': market });
 | 
					    this.websocketSubject.next({ 'track-bisq-market': market });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -283,6 +294,10 @@ export class WebsocketService {
 | 
				
			|||||||
      this.stateService.rbfLatest$.next(response.rbfLatest);
 | 
					      this.stateService.rbfLatest$.next(response.rbfLatest);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (response.rbfLatestSummary) {
 | 
				
			||||||
 | 
					      this.stateService.rbfLatestSummary$.next(response.rbfLatestSummary);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (response.txReplaced) {
 | 
					    if (response.txReplaced) {
 | 
				
			||||||
      this.stateService.txReplaced$.next(response.txReplaced);
 | 
					      this.stateService.txReplaced$.next(response.txReplaced);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user