2020-07-30 15:38:55 +07:00
import { Component , OnInit , OnDestroy , ChangeDetectionStrategy } from '@angular/core' ;
2022-09-21 17:23:45 +02:00
import { StateService } from '../../services/state.service' ;
2020-03-17 21:53:20 +07:00
import { ActivatedRoute , ParamMap } from '@angular/router' ;
2020-06-10 23:52:14 +07:00
import { switchMap , map , tap , filter } from 'rxjs/operators' ;
2022-09-21 17:23:45 +02:00
import { MempoolBlock , TransactionStripped } from '../../interfaces/websocket.interface' ;
2020-07-30 15:38:55 +07:00
import { Observable , BehaviorSubject } from 'rxjs' ;
2022-09-21 17:23:45 +02:00
import { SeoService } from '../../services/seo.service' ;
2023-08-30 20:26:07 +09:00
import { seoDescriptionNetwork } from '../../shared/common.utils' ;
2022-09-21 17:23:45 +02:00
import { WebsocketService } from '../../services/websocket.service' ;
2020-03-17 21:53:20 +07:00
@Component ( {
selector : 'app-mempool-block' ,
templateUrl : './mempool-block.component.html' ,
2020-07-30 15:38:55 +07:00
styleUrls : [ './mempool-block.component.scss' ] ,
changeDetection : ChangeDetectionStrategy.OnPush ,
2020-03-17 21:53:20 +07:00
} )
2020-03-22 17:44:36 +07:00
export class MempoolBlockComponent implements OnInit , OnDestroy {
2020-07-30 15:38:55 +07:00
network$ : Observable < string > ;
2020-03-17 21:53:20 +07:00
mempoolBlockIndex : number ;
2020-03-23 01:43:03 +07:00
mempoolBlock$ : Observable < MempoolBlock > ;
2023-03-15 11:43:18 +09:00
mempoolBlockTransactions$ : Observable < TransactionStripped [ ] > ;
2020-07-30 15:38:55 +07:00
ordinal$ : BehaviorSubject < string > = new BehaviorSubject ( '' ) ;
2022-05-31 14:16:35 +00:00
previewTx : TransactionStripped | void ;
2022-05-31 22:25:09 +00:00
webGlEnabled : boolean ;
2020-03-17 21:53:20 +07:00
constructor (
private route : ActivatedRoute ,
2021-07-31 17:30:35 +03:00
public stateService : StateService ,
2020-03-24 00:52:08 +07:00
private seoService : SeoService ,
2020-09-26 22:46:26 +07:00
private websocketService : WebsocketService ,
2022-05-31 22:25:09 +00:00
) {
this . webGlEnabled = detectWebGL ( ) ;
}
2020-03-17 21:53:20 +07:00
ngOnInit ( ) : void {
2020-09-26 22:46:26 +07:00
this . websocketService . want ( [ 'blocks' , 'mempool-blocks' ] ) ;
2020-03-23 01:43:03 +07:00
this . mempoolBlock $ = this . route . paramMap
. pipe (
switchMap ( ( params : ParamMap ) = > {
this . mempoolBlockIndex = parseInt ( params . get ( 'id' ) , 10 ) || 0 ;
return this . stateService . mempoolBlocks $
2020-07-30 15:38:55 +07:00
. pipe (
map ( ( blocks ) = > {
if ( ! blocks . length ) {
return [ { index : 0 , blockSize : 0 , blockVSize : 0 , feeRange : [ 0 , 0 ] , medianFee : 0 , nTx : 0 , totalFees : 0 } ] ;
}
return blocks ;
} ) ,
filter ( ( mempoolBlocks ) = > mempoolBlocks . length > 0 ) ,
map ( ( mempoolBlocks ) = > {
while ( ! mempoolBlocks [ this . mempoolBlockIndex ] ) {
this . mempoolBlockIndex -- ;
}
const ordinal = this . getOrdinal ( mempoolBlocks [ this . mempoolBlockIndex ] ) ;
this . ordinal $ . next ( ordinal ) ;
this . seoService . setTitle ( ordinal ) ;
2023-08-30 20:26:07 +09:00
this . seoService . setDescription ( $localize ` :@@meta.description.mempool-block:See stats for ${ this . stateService . network === 'liquid' || this . stateService . network === 'liquidtestnet' ? 'Liquid' : 'Bitcoin' } ${ seoDescriptionNetwork ( this . stateService . network ) } transactions in the mempool: fee range, aggregate size, and more. Mempool blocks are updated in real-time as the network receives new transactions. ` ) ;
2023-06-07 13:22:27 -04:00
mempoolBlocks [ this . mempoolBlockIndex ] . isStack = mempoolBlocks [ this . mempoolBlockIndex ] . blockVSize > this . stateService . blockVSize ;
2020-07-30 15:38:55 +07:00
return mempoolBlocks [ this . mempoolBlockIndex ] ;
} )
) ;
2020-03-23 01:43:03 +07:00
} ) ,
tap ( ( ) = > {
this . stateService . markBlock $ . next ( { mempoolBlockIndex : this.mempoolBlockIndex } ) ;
} )
) ;
2020-05-09 20:37:50 +07:00
2023-03-15 11:43:18 +09:00
this . mempoolBlockTransactions $ = this . stateService . liveMempoolBlockTransactions $ . pipe ( map ( txMap = > Object . values ( txMap ) ) ) ;
2020-07-30 15:38:55 +07:00
this . network $ = this . stateService . networkChanged $ ;
2020-03-17 21:53:20 +07:00
}
2020-03-22 17:44:36 +07:00
ngOnDestroy ( ) : void {
this . stateService . markBlock $ . next ( { } ) ;
}
2020-07-30 15:38:55 +07:00
getOrdinal ( mempoolBlock : MempoolBlock ) : string {
2021-07-31 17:30:35 +03:00
const blocksInBlock = Math . ceil ( mempoolBlock . blockVSize / this . stateService . blockVSize ) ;
2020-03-25 03:59:30 +07:00
if ( this . mempoolBlockIndex === 0 ) {
2022-05-10 17:05:07 +04:00
return $localize ` :@@bdf0e930eb22431140a2eaeacd809cc5f8ebd38c:Next Block ` ;
2020-12-08 00:11:38 +07:00
} else if ( this . mempoolBlockIndex === this . stateService . env . KEEP_BLOCKS_AMOUNT - 1 && blocksInBlock > 1 ) {
2020-12-03 18:34:19 +07:00
return $localize ` :@@mempool-block.stack.of.blocks:Stack of ${ blocksInBlock } :INTERPOLATION: mempool blocks ` ;
2020-07-21 13:20:17 +07:00
} else {
2020-12-03 18:34:19 +07:00
return $localize ` :@@mempool-block.block.no:Mempool block ${ this . mempoolBlockIndex + 1 } :INTERPOLATION: ` ;
2020-03-25 03:59:30 +07:00
}
2022-05-31 14:16:35 +00:00
}
setTxPreview ( event : TransactionStripped | void ) : void {
2022-06-14 00:33:48 +00:00
this . previewTx = event ;
2022-05-31 14:16:35 +00:00
}
2020-03-17 21:53:20 +07:00
}
2022-05-31 22:25:09 +00:00
2022-06-14 00:33:48 +00:00
function detectWebGL() {
const canvas = document . createElement ( 'canvas' ) ;
const gl = canvas . getContext ( 'webgl' ) || canvas . getContext ( 'experimental-webgl' ) ;
return ( gl && gl instanceof WebGLRenderingContext ) ;
2022-05-31 22:25:09 +00:00
}