Switch "latest blocks" to "latest replacements"
This commit is contained in:
		
							parent
							
								
									cff2022baf
								
							
						
					
					
						commit
						756fac7270
					
				| @ -75,36 +75,31 @@ | |||||||
|     <div class="col" style="max-height: 410px"> |     <div class="col" style="max-height: 410px"> | ||||||
|       <div class="card"> |       <div class="card"> | ||||||
|         <div class="card-body"> |         <div class="card-body"> | ||||||
|           <a class="title-link" href="" [routerLink]="['/blocks' | relativeUrl]"> |           <a class="title-link" href="" [routerLink]="['/rbf' | relativeUrl]"> | ||||||
|             <h5 class="card-title d-inline" i18n="dashboard.latest-blocks">Latest blocks</h5> |             <h5 class="card-title d-inline" i18n="dashboard.latest-rbf-replacements">Latest Replacements</h5> | ||||||
|             <span> </span> |             <span> </span> | ||||||
|             <fa-icon [icon]="['fas', 'external-link-alt']" [fixedWidth]="true" style="vertical-align: 'text-top'; font-size: 13px; color: '#4a68b9'"></fa-icon> |             <fa-icon [icon]="['fas', 'external-link-alt']" [fixedWidth]="true" style="vertical-align: 'text-top'; font-size: 13px; color: '#4a68b9'"></fa-icon> | ||||||
|           </a> |           </a> | ||||||
|           <table class="table lastest-blocks-table"> |           <table class="table lastest-replacements-table"> | ||||||
|             <thead> |             <thead> | ||||||
|               <th class="table-cell-height" i18n="dashboard.latest-blocks.height">Height</th> |               <th class="table-cell-txid" i18n="dashboard.latest-transactions.txid">TXID</th> | ||||||
|               <th *ngIf="!stateService.env.MINING_DASHBOARD" class="table-cell-mined" i18n="dashboard.latest-blocks.mined">Mined</th> |               <th class="table-cell-old-fee" i18n="dashboard.old-transaction-fee">Old fee</th> | ||||||
|               <th *ngIf="stateService.env.MINING_DASHBOARD" class="table-cell-mined pl-lg-4" i18n="mining.pool-name">Pool</th> |               <th class="table-cell-new-fee" i18n="dashboard.new-transaction-fee">New fee</th> | ||||||
|               <th class="table-cell-transaction-count" i18n="dashboard.latest-blocks.transaction-count">TXs</th> |               <th class="table-cell-badges"></th> | ||||||
|               <th class="table-cell-size" i18n="dashboard.latest-blocks.size">Size</th> |  | ||||||
|             </thead> |             </thead> | ||||||
|             <tbody> |             <tbody> | ||||||
|               <tr *ngFor="let block of blocks$ | async; let i = index; trackBy: trackByBlock"> |               <tr *ngFor="let replacement of replacements$ | async;"> | ||||||
|                 <td class="table-cell-height" ><a [routerLink]="['/block' | relativeUrl, block.id]" [state]="{ data: { block: block } }">{{ block.height }}</a></td> |                 <td class="table-cell-txid"> | ||||||
|                 <td *ngIf="!stateService.env.MINING_DASHBOARD" class="table-cell-mined" ><app-time kind="since" [time]="block.timestamp" [fastRender]="true"></app-time></td> |                   <a [routerLink]="['/tx' | relativeUrl, replacement.txid]"> | ||||||
|                 <td *ngIf="stateService.env.MINING_DASHBOARD" class="table-cell-mined pl-lg-4"> |                     <app-truncate [text]="replacement.txid" [lastChars]="5"></app-truncate> | ||||||
|                   <a class="clear-link" [routerLink]="[('/mining/pool/' + block.extras.pool.slug) | relativeUrl]"> |  | ||||||
|                     <img width="22" height="22" src="{{ block.extras.pool['logo'] }}" |  | ||||||
|                       onError="this.src = '/resources/mining-pools/default.svg'"> |  | ||||||
|                     <span class="pool-name">{{ block.extras.pool.name }}</span> |  | ||||||
|                   </a> |                   </a> | ||||||
|                 </td> |                 </td> | ||||||
|                 <td class="table-cell-transaction-count">{{ block.tx_count | number }}</td> |                 <td class="table-cell-old-fee"><app-fee-rate [fee]="replacement.oldFee" [weight]="replacement.oldVsize * 4"></app-fee-rate></td> | ||||||
|                 <td class="table-cell-size"> |                 <td class="table-cell-new-fee"><app-fee-rate [fee]="replacement.newFee" [weight]="replacement.newVsize * 4"></app-fee-rate></td> | ||||||
|                   <div class="progress"> |                 <td class="table-cell-badges"> | ||||||
|                     <div class="progress-bar progress-mempool {{ network$ | async }}" role="progressbar" [ngStyle]="{'width': (block.weight / stateService.env.BLOCK_WEIGHT_UNITS)*100 + '%' }"> </div> |                   <span *ngIf="replacement.mined" class="badge badge-success" i18n="transaction.rbf.mined">Mined</span> | ||||||
|                     <div class="progress-text" [innerHTML]="block.size | bytes: 2"></div> |                   <span *ngIf="replacement.fullRbf" class="badge badge-info" i18n="transaction.full-rbf">Full RBF</span> | ||||||
|                   </div> |                   <span *ngIf="!replacement.fullRbf" class="badge badge-success" i18n="transaction.rbf">RBF</span> | ||||||
|                 </td> |                 </td> | ||||||
|               </tr> |               </tr> | ||||||
|             </tbody> |             </tbody> | ||||||
|  | |||||||
| @ -175,40 +175,34 @@ | |||||||
|   height: 18px; |   height: 18px; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .lastest-blocks-table { | .lastest-replacements-table { | ||||||
|   width: 100%; |   width: 100%; | ||||||
|   text-align: left; |   text-align: left; | ||||||
|  |   table-layout:fixed; | ||||||
|   tr, td, th { |   tr, td, th { | ||||||
|     border: 0px; |     border: 0px; | ||||||
|     padding-top: 0.65rem !important; |     padding-top: 0.71rem !important; | ||||||
|     padding-bottom: 0.7rem !important; |     padding-bottom: 0.75rem !important; | ||||||
|   } |   } | ||||||
|   .table-cell-height { |   td { | ||||||
|     width: 15%; |     overflow:hidden; | ||||||
|  |     width: 25%; | ||||||
|   } |   } | ||||||
|   .table-cell-mined { |   .table-cell-txid { | ||||||
|     width: 35%; |     width: 33%; | ||||||
|     text-align: left; |     text-align: start; | ||||||
|   } |   } | ||||||
|   .table-cell-transaction-count { |   .table-cell-old-fee { | ||||||
|     display: none; |     width: 33%; | ||||||
|     text-align: right; |     text-align: end; | ||||||
|     width: 20%; |  | ||||||
|     display: table-cell; |  | ||||||
|   } |   } | ||||||
|   .table-cell-size { |   .table-cell-new-fee { | ||||||
|     display: none; |     width: 33%; | ||||||
|     text-align: center; |     text-align: end; | ||||||
|     width: 30%; |  | ||||||
|     @media (min-width: 485px) { |  | ||||||
|       display: table-cell; |  | ||||||
|     } |  | ||||||
|     @media (min-width: 768px) { |  | ||||||
|       display: none; |  | ||||||
|     } |  | ||||||
|     @media (min-width: 992px) { |  | ||||||
|       display: table-cell; |  | ||||||
|   } |   } | ||||||
|  |   .table-cell-badges { | ||||||
|  |     width: 25%; | ||||||
|  |     text-align: end; | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| 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, tap } from 'rxjs/operators'; | ||||||
| import { BlockExtended, OptimizedMempoolStats } from '../interfaces/node-api.interface'; | import { BlockExtended, OptimizedMempoolStats, RbfTree } from '../interfaces/node-api.interface'; | ||||||
| import { MempoolInfo, TransactionStripped } from '../interfaces/websocket.interface'; | import { MempoolInfo, TransactionStripped } 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'; | ||||||
| @ -25,6 +25,17 @@ 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', | ||||||
| @ -38,8 +49,8 @@ export class DashboardComponent implements OnInit, OnDestroy { | |||||||
|   mempoolInfoData$: Observable<MempoolInfoData>; |   mempoolInfoData$: Observable<MempoolInfoData>; | ||||||
|   mempoolLoadingStatus$: Observable<number>; |   mempoolLoadingStatus$: Observable<number>; | ||||||
|   vBytesPerSecondLimit = 1667; |   vBytesPerSecondLimit = 1667; | ||||||
|   blocks$: Observable<BlockExtended[]>; |  | ||||||
|   transactions$: Observable<TransactionStripped[]>; |   transactions$: Observable<TransactionStripped[]>; | ||||||
|  |   replacements$: Observable<ReplacementInfo[]>; | ||||||
|   latestBlockHeight: number; |   latestBlockHeight: number; | ||||||
|   mempoolTransactionsWeightPerSecondData: any; |   mempoolTransactionsWeightPerSecondData: any; | ||||||
|   mempoolStats$: Observable<MempoolStatsData>; |   mempoolStats$: Observable<MempoolStatsData>; | ||||||
| @ -64,6 +75,7 @@ export class DashboardComponent implements OnInit, OnDestroy { | |||||||
|     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.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( | ||||||
| @ -130,23 +142,6 @@ export class DashboardComponent implements OnInit, OnDestroy { | |||||||
|         }), |         }), | ||||||
|       ); |       ); | ||||||
| 
 | 
 | ||||||
|     this.blocks$ = this.stateService.blocks$ |  | ||||||
|       .pipe( |  | ||||||
|         tap((blocks) => { |  | ||||||
|           this.latestBlockHeight = blocks[0].height; |  | ||||||
|         }), |  | ||||||
|         switchMap((blocks) => { |  | ||||||
|           if (this.stateService.env.MINING_DASHBOARD === true) { |  | ||||||
|             for (const block of blocks) { |  | ||||||
|               // @ts-ignore: Need to add an extra field for the template
 |  | ||||||
|               block.extras.pool.logo = `/resources/mining-pools/` + |  | ||||||
|                 block.extras.pool.name.toLowerCase().replace(' ', '').replace('.', '') + '.svg'; |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|           return of(blocks.slice(0, 6)); |  | ||||||
|         }) |  | ||||||
|       ); |  | ||||||
| 
 |  | ||||||
|     this.transactions$ = this.stateService.transactions$ |     this.transactions$ = this.stateService.transactions$ | ||||||
|       .pipe( |       .pipe( | ||||||
|         scan((acc, tx) => { |         scan((acc, tx) => { | ||||||
| @ -159,6 +154,31 @@ export class DashboardComponent implements OnInit, OnDestroy { | |||||||
|         }, []), |         }, []), | ||||||
|       ); |       ); | ||||||
| 
 | 
 | ||||||
|  |     this.replacements$ = this.stateService.rbfLatest$.pipe( | ||||||
|  |       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( | ||||||
|         filter((state) => state === 2), |         filter((state) => state === 2), | ||||||
| @ -219,4 +239,16 @@ export class DashboardComponent implements OnInit, OnDestroy { | |||||||
|   trackByBlock(index: number, block: BlockExtended) { |   trackByBlock(index: number, block: BlockExtended) { | ||||||
|     return block.height; |     return block.height; | ||||||
|   } |   } | ||||||
|  | 
 | ||||||
|  |   checkFullRbf(tree: RbfTree): void { | ||||||
|  |     let fullRbf = false; | ||||||
|  |     for (const replaced of tree.replaces) { | ||||||
|  |       if (!replaced.tx.rbf) { | ||||||
|  |         fullRbf = true; | ||||||
|  |       } | ||||||
|  |       replaced.replacedBy = tree.tx; | ||||||
|  |       this.checkFullRbf(replaced); | ||||||
|  |     } | ||||||
|  |     tree.tx.fullRbf = fullRbf; | ||||||
|  |   } | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user