2022-06-14 00:33:48 +00:00
|
|
|
import { Component, ComponentRef, ViewChild, HostListener, Input, Output, EventEmitter,
|
2022-09-29 22:40:46 +00:00
|
|
|
OnInit, OnDestroy, OnChanges, ChangeDetectionStrategy, ChangeDetectorRef, AfterViewInit } from '@angular/core';
|
2022-09-21 17:23:45 +02:00
|
|
|
import { StateService } from '../../services/state.service';
|
|
|
|
import { MempoolBlockDelta, TransactionStripped } from '../../interfaces/websocket.interface';
|
|
|
|
import { BlockOverviewGraphComponent } from '../../components/block-overview-graph/block-overview-graph.component';
|
2022-06-05 23:40:36 +04:00
|
|
|
import { Subscription, BehaviorSubject, merge, of } from 'rxjs';
|
|
|
|
import { switchMap, filter } from 'rxjs/operators';
|
2022-09-21 17:23:45 +02:00
|
|
|
import { WebsocketService } from '../../services/websocket.service';
|
|
|
|
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
|
2022-06-15 01:40:05 +00:00
|
|
|
import { Router } from '@angular/router';
|
2022-05-30 17:29:30 +00:00
|
|
|
|
|
|
|
@Component({
|
|
|
|
selector: 'app-mempool-block-overview',
|
|
|
|
templateUrl: './mempool-block-overview.component.html',
|
|
|
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
|
|
})
|
2022-09-29 22:40:46 +00:00
|
|
|
export class MempoolBlockOverviewComponent implements OnInit, OnDestroy, OnChanges, AfterViewInit {
|
2022-05-30 17:29:30 +00:00
|
|
|
@Input() index: number;
|
2022-06-02 01:29:03 +04:00
|
|
|
@Output() txPreviewEvent = new EventEmitter<TransactionStripped | void>();
|
2022-05-30 17:29:30 +00:00
|
|
|
|
2022-06-14 00:33:48 +00:00
|
|
|
@ViewChild('blockGraph') blockGraph: BlockOverviewGraphComponent;
|
2022-05-30 21:53:39 +00:00
|
|
|
|
|
|
|
lastBlockHeight: number;
|
|
|
|
blockIndex: number;
|
2022-05-31 22:25:09 +00:00
|
|
|
isLoading$ = new BehaviorSubject<boolean>(true);
|
2022-09-29 22:40:46 +00:00
|
|
|
timeLtrSubscription: Subscription;
|
|
|
|
timeLtr: boolean;
|
|
|
|
chainDirection: string = 'right';
|
|
|
|
poolDirection: string = 'left';
|
2022-05-30 21:53:39 +00:00
|
|
|
|
2022-05-31 21:36:42 +00:00
|
|
|
blockSub: Subscription;
|
|
|
|
deltaSub: Subscription;
|
2022-05-30 17:29:30 +00:00
|
|
|
|
|
|
|
constructor(
|
|
|
|
public stateService: StateService,
|
2022-06-15 01:40:05 +00:00
|
|
|
private websocketService: WebsocketService,
|
|
|
|
private router: Router,
|
2022-09-29 22:40:46 +00:00
|
|
|
private cd: ChangeDetectorRef,
|
2022-06-14 00:33:48 +00:00
|
|
|
) { }
|
2022-05-30 17:29:30 +00:00
|
|
|
|
2022-09-29 22:40:46 +00:00
|
|
|
ngOnInit(): void {
|
|
|
|
this.timeLtrSubscription = this.stateService.timeLtr.subscribe((ltr) => {
|
|
|
|
this.timeLtr = !!ltr;
|
|
|
|
this.chainDirection = ltr ? 'left' : 'right';
|
|
|
|
this.poolDirection = ltr ? 'right' : 'left';
|
|
|
|
this.cd.markForCheck();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2022-06-14 00:33:48 +00:00
|
|
|
ngAfterViewInit(): void {
|
2022-06-05 23:40:36 +04:00
|
|
|
this.blockSub = merge(
|
|
|
|
of(true),
|
|
|
|
this.stateService.connectionState$.pipe(filter((state) => state === 2))
|
|
|
|
)
|
|
|
|
.pipe(switchMap(() => this.stateService.mempoolBlockTransactions$))
|
|
|
|
.subscribe((transactionsStripped) => {
|
|
|
|
this.replaceBlock(transactionsStripped);
|
|
|
|
});
|
2022-05-31 21:36:42 +00:00
|
|
|
this.deltaSub = this.stateService.mempoolBlockDelta$.subscribe((delta) => {
|
2022-06-02 01:29:03 +04:00
|
|
|
this.updateBlock(delta);
|
|
|
|
});
|
2022-05-30 17:29:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ngOnChanges(changes): void {
|
|
|
|
if (changes.index) {
|
2022-06-14 00:33:48 +00:00
|
|
|
if (this.blockGraph) {
|
2022-09-29 22:40:46 +00:00
|
|
|
this.blockGraph.clear(changes.index.currentValue > changes.index.previousValue ? this.chainDirection : this.poolDirection);
|
2022-06-14 00:33:48 +00:00
|
|
|
}
|
2022-06-02 01:29:03 +04:00
|
|
|
this.isLoading$.next(true);
|
2022-05-30 17:29:30 +00:00
|
|
|
this.websocketService.startTrackMempoolBlock(changes.index.currentValue);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ngOnDestroy(): void {
|
2022-05-31 21:36:42 +00:00
|
|
|
this.blockSub.unsubscribe();
|
|
|
|
this.deltaSub.unsubscribe();
|
2022-09-29 22:40:46 +00:00
|
|
|
this.timeLtrSubscription.unsubscribe();
|
2022-05-30 17:29:30 +00:00
|
|
|
this.websocketService.stopTrackMempoolBlock();
|
|
|
|
}
|
|
|
|
|
2022-06-02 01:29:03 +04:00
|
|
|
replaceBlock(transactionsStripped: TransactionStripped[]): void {
|
|
|
|
const blockMined = (this.stateService.latestBlockHeight > this.lastBlockHeight);
|
|
|
|
if (this.blockIndex !== this.index) {
|
2022-09-29 22:40:46 +00:00
|
|
|
const direction = (this.blockIndex == null || this.index < this.blockIndex) ? this.poolDirection : this.chainDirection;
|
2022-06-14 00:33:48 +00:00
|
|
|
this.blockGraph.enter(transactionsStripped, direction);
|
2022-05-31 21:36:42 +00:00
|
|
|
} else {
|
2022-09-29 22:40:46 +00:00
|
|
|
this.blockGraph.replace(transactionsStripped, blockMined ? this.chainDirection : this.poolDirection);
|
2022-05-30 21:53:39 +00:00
|
|
|
}
|
2022-05-31 21:36:42 +00:00
|
|
|
|
2022-06-02 01:29:03 +04:00
|
|
|
this.lastBlockHeight = this.stateService.latestBlockHeight;
|
|
|
|
this.blockIndex = this.index;
|
|
|
|
this.isLoading$.next(false);
|
2022-05-30 21:53:39 +00:00
|
|
|
}
|
|
|
|
|
2022-05-31 21:36:42 +00:00
|
|
|
updateBlock(delta: MempoolBlockDelta): void {
|
2022-06-02 01:29:03 +04:00
|
|
|
const blockMined = (this.stateService.latestBlockHeight > this.lastBlockHeight);
|
|
|
|
|
|
|
|
if (this.blockIndex !== this.index) {
|
2022-09-29 22:40:46 +00:00
|
|
|
const direction = (this.blockIndex == null || this.index < this.blockIndex) ? this.poolDirection : this.chainDirection;
|
2022-06-14 00:33:48 +00:00
|
|
|
this.blockGraph.replace(delta.added, direction);
|
2022-05-30 21:53:39 +00:00
|
|
|
} else {
|
2022-09-29 22:40:46 +00:00
|
|
|
this.blockGraph.update(delta.added, delta.removed, blockMined ? this.chainDirection : this.poolDirection, blockMined);
|
2022-05-30 21:53:39 +00:00
|
|
|
}
|
|
|
|
|
2022-06-02 01:29:03 +04:00
|
|
|
this.lastBlockHeight = this.stateService.latestBlockHeight;
|
|
|
|
this.blockIndex = this.index;
|
|
|
|
this.isLoading$.next(false);
|
2022-05-30 17:29:30 +00:00
|
|
|
}
|
2022-05-30 21:53:39 +00:00
|
|
|
|
2022-06-15 01:40:05 +00:00
|
|
|
onTxClick(event: TransactionStripped): void {
|
|
|
|
const url = new RelativeUrlPipe(this.stateService).transform(`/tx/${event.txid}`);
|
|
|
|
this.router.navigate([url]);
|
2022-05-30 21:53:39 +00:00
|
|
|
}
|
2022-05-30 17:29:30 +00:00
|
|
|
}
|