Refactord blockchain is rendering, block arrow location propagation and keynavigation.
This commit is contained in:
parent
69827843c9
commit
78e41fc3d3
@ -9,6 +9,7 @@ import { AboutComponent } from './components/about/about.component';
|
|||||||
import { TelevisionComponent } from './components/television/television.component';
|
import { TelevisionComponent } from './components/television/television.component';
|
||||||
import { StatisticsComponent } from './components/statistics/statistics.component';
|
import { StatisticsComponent } from './components/statistics/statistics.component';
|
||||||
import { MempoolBlockComponent } from './components/mempool-block/mempool-block.component';
|
import { MempoolBlockComponent } from './components/mempool-block/mempool-block.component';
|
||||||
|
import { LatestBlocksComponent } from './components/latest-blocks/latest-blocks.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
@ -18,6 +19,24 @@ const routes: Routes = [
|
|||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: StartComponent,
|
component: StartComponent,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: LatestBlocksComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'tx/:id',
|
||||||
|
component: TransactionComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'block/:id',
|
||||||
|
component: BlockComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'mempool-block/:id',
|
||||||
|
component: MempoolBlockComponent
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'graphs',
|
path: 'graphs',
|
||||||
@ -27,21 +46,6 @@ const routes: Routes = [
|
|||||||
path: 'contributors',
|
path: 'contributors',
|
||||||
component: AboutComponent,
|
component: AboutComponent,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: 'tx/:id',
|
|
||||||
children: [],
|
|
||||||
component: TransactionComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'block/:id',
|
|
||||||
children: [],
|
|
||||||
component: BlockComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'mempool-block/:id',
|
|
||||||
children: [],
|
|
||||||
component: MempoolBlockComponent
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: 'address/:id',
|
path: 'address/:id',
|
||||||
children: [],
|
children: [],
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
<div class="container-xl">
|
<div class="container-xl">
|
||||||
|
|
||||||
<div style="position: relative;">
|
|
||||||
<app-blockchain position="top" [markHeight]="blockHeight"></app-blockchain>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="title-block">
|
<div class="title-block">
|
||||||
<h1>Block <ng-template [ngIf]="blockHeight"><a [routerLink]="['/block/', blockHash]">{{ blockHeight }}</a></ng-template></h1>
|
<h1>Block <ng-template [ngIf]="blockHeight"><a [routerLink]="['/block/', blockHash]">{{ blockHeight }}</a></ng-template></h1>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||||
import { ActivatedRoute, ParamMap } from '@angular/router';
|
import { ActivatedRoute, ParamMap } from '@angular/router';
|
||||||
import { ElectrsApiService } from '../../services/electrs-api.service';
|
import { ElectrsApiService } from '../../services/electrs-api.service';
|
||||||
import { switchMap } from 'rxjs/operators';
|
import { switchMap, tap, debounceTime } from 'rxjs/operators';
|
||||||
import { Block, Transaction, Vout } from '../../interfaces/electrs.interface';
|
import { Block, Transaction, Vout } from '../../interfaces/electrs.interface';
|
||||||
import { of } from 'rxjs';
|
import { of, Observable } from 'rxjs';
|
||||||
import { StateService } from '../../services/state.service';
|
import { StateService } from '../../services/state.service';
|
||||||
import { WebsocketService } from 'src/app/services/websocket.service';
|
import { WebsocketService } from 'src/app/services/websocket.service';
|
||||||
|
|
||||||
@ -12,7 +12,7 @@ import { WebsocketService } from 'src/app/services/websocket.service';
|
|||||||
templateUrl: './block.component.html',
|
templateUrl: './block.component.html',
|
||||||
styleUrls: ['./block.component.scss']
|
styleUrls: ['./block.component.scss']
|
||||||
})
|
})
|
||||||
export class BlockComponent implements OnInit {
|
export class BlockComponent implements OnInit, OnDestroy {
|
||||||
block: Block;
|
block: Block;
|
||||||
blockHeight: number;
|
blockHeight: number;
|
||||||
blockHash: string;
|
blockHash: string;
|
||||||
@ -34,7 +34,8 @@ export class BlockComponent implements OnInit {
|
|||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.websocketService.want(['blocks', 'stats', 'mempool-blocks']);
|
this.websocketService.want(['blocks', 'stats', 'mempool-blocks']);
|
||||||
|
|
||||||
this.route.paramMap.pipe(
|
this.route.paramMap
|
||||||
|
.pipe(
|
||||||
switchMap((params: ParamMap) => {
|
switchMap((params: ParamMap) => {
|
||||||
const blockHash: string = params.get('id') || '';
|
const blockHash: string = params.get('id') || '';
|
||||||
this.error = undefined;
|
this.error = undefined;
|
||||||
@ -54,17 +55,28 @@ export class BlockComponent implements OnInit {
|
|||||||
this.isLoadingBlock = true;
|
this.isLoadingBlock = true;
|
||||||
return this.electrsApiService.getBlock$(blockHash);
|
return this.electrsApiService.getBlock$(blockHash);
|
||||||
}
|
}
|
||||||
})
|
}),
|
||||||
|
tap((block: Block) => {
|
||||||
|
this.block = block;
|
||||||
|
this.blockHeight = block.height;
|
||||||
|
this.isLoadingBlock = false;
|
||||||
|
this.setBlockSubsidy();
|
||||||
|
if (block.reward) {
|
||||||
|
this.fees = block.reward / 100000000 - this.blockSubsidy;
|
||||||
|
}
|
||||||
|
this.stateService.markBlock$.next({ blockHeight: this.blockHeight });
|
||||||
|
this.isLoadingTransactions = true;
|
||||||
|
this.transactions = null;
|
||||||
|
}),
|
||||||
|
debounceTime(250),
|
||||||
|
switchMap((block) => this.electrsApiService.getBlockTransactions$(block.id))
|
||||||
)
|
)
|
||||||
.subscribe((block: Block) => {
|
.subscribe((transactions: Transaction[]) => {
|
||||||
this.block = block;
|
if (this.fees === undefined) {
|
||||||
this.blockHeight = block.height;
|
this.fees = transactions[0].vout.reduce((acc: number, curr: Vout) => acc + curr.value, 0) / 100000000 - this.blockSubsidy;
|
||||||
this.isLoadingBlock = false;
|
|
||||||
this.setBlockSubsidy();
|
|
||||||
if (block.reward) {
|
|
||||||
this.fees = block.reward / 100000000 - this.blockSubsidy;
|
|
||||||
}
|
}
|
||||||
this.getBlockTransactions(block.id);
|
this.transactions = transactions;
|
||||||
|
this.isLoadingTransactions = false;
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
this.error = error;
|
this.error = error;
|
||||||
@ -75,6 +87,10 @@ export class BlockComponent implements OnInit {
|
|||||||
.subscribe((block) => this.latestBlock = block);
|
.subscribe((block) => this.latestBlock = block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnDestroy() {
|
||||||
|
this.stateService.markBlock$.next({});
|
||||||
|
}
|
||||||
|
|
||||||
setBlockSubsidy() {
|
setBlockSubsidy() {
|
||||||
this.blockSubsidy = 50;
|
this.blockSubsidy = 50;
|
||||||
let halvenings = Math.floor(this.block.height / 210000);
|
let halvenings = Math.floor(this.block.height / 210000);
|
||||||
@ -84,19 +100,6 @@ export class BlockComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getBlockTransactions(hash: string) {
|
|
||||||
this.isLoadingTransactions = true;
|
|
||||||
this.transactions = null;
|
|
||||||
this.electrsApiService.getBlockTransactions$(hash)
|
|
||||||
.subscribe((transactions: any) => {
|
|
||||||
if (this.fees === undefined) {
|
|
||||||
this.fees = transactions[0].vout.reduce((acc: number, curr: Vout) => acc + curr.value, 0) / 100000000 - this.blockSubsidy;
|
|
||||||
}
|
|
||||||
this.transactions = transactions;
|
|
||||||
this.isLoadingTransactions = false;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
loadMore() {
|
loadMore() {
|
||||||
if (this.isLoadingTransactions || !this.transactions.length || this.transactions.length === this.block.tx_count) {
|
if (this.isLoadingTransactions || !this.transactions.length || this.transactions.length === this.block.tx_count) {
|
||||||
return;
|
return;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, OnInit, OnDestroy, Input, OnChanges, HostListener } from '@angular/core';
|
import { Component, OnInit, OnDestroy, HostListener } from '@angular/core';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { Block } from 'src/app/interfaces/electrs.interface';
|
import { Block } from 'src/app/interfaces/electrs.interface';
|
||||||
import { StateService } from 'src/app/services/state.service';
|
import { StateService } from 'src/app/services/state.service';
|
||||||
@ -9,10 +9,9 @@ import { Router } from '@angular/router';
|
|||||||
templateUrl: './blockchain-blocks.component.html',
|
templateUrl: './blockchain-blocks.component.html',
|
||||||
styleUrls: ['./blockchain-blocks.component.scss']
|
styleUrls: ['./blockchain-blocks.component.scss']
|
||||||
})
|
})
|
||||||
export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
|
export class BlockchainBlocksComponent implements OnInit, OnDestroy {
|
||||||
@Input() markHeight = 0;
|
|
||||||
|
|
||||||
blocks: Block[] = [];
|
blocks: Block[] = [];
|
||||||
|
markHeight: number;
|
||||||
blocksSubscription: Subscription;
|
blocksSubscription: Subscription;
|
||||||
interval: any;
|
interval: any;
|
||||||
|
|
||||||
@ -37,10 +36,15 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
|
|
||||||
this.moveArrowToPosition(true);
|
this.moveArrowToPosition(true);
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
ngOnChanges() {
|
this.stateService.markBlock$
|
||||||
this.moveArrowToPosition(false);
|
.subscribe((state) => {
|
||||||
|
this.markHeight = undefined;
|
||||||
|
if (state.blockHeight) {
|
||||||
|
this.markHeight = state.blockHeight;
|
||||||
|
}
|
||||||
|
this.moveArrowToPosition(false);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<div class="text-center" class="blockchain-wrapper">
|
<div class="text-center" class="blockchain-wrapper">
|
||||||
<div class="position-container">
|
<div class="position-container">
|
||||||
<app-mempool-blocks [markIndex]="markMempoolBlockIndex" [txFeePerVSize]="markHeight ? 0 : txFeePerVSize"></app-mempool-blocks>
|
<app-mempool-blocks></app-mempool-blocks>
|
||||||
<app-blockchain-blocks [markHeight]="markHeight"></app-blockchain-blocks>
|
<app-blockchain-blocks></app-blockchain-blocks>
|
||||||
|
|
||||||
<div id="divider" *ngIf="!isLoading; else loadingTmpl"></div>
|
<div id="divider" *ngIf="!isLoading; else loadingTmpl"></div>
|
||||||
|
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { Component, OnInit, OnDestroy, Input } from '@angular/core';
|
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { take } from 'rxjs/operators';
|
import { take } from 'rxjs/operators';
|
||||||
import { StateService } from 'src/app/services/state.service';
|
import { StateService } from 'src/app/services/state.service';
|
||||||
import { Router } from '@angular/router';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-blockchain',
|
selector: 'app-blockchain',
|
||||||
@ -10,12 +9,6 @@ import { Router } from '@angular/router';
|
|||||||
styleUrls: ['./blockchain.component.scss']
|
styleUrls: ['./blockchain.component.scss']
|
||||||
})
|
})
|
||||||
export class BlockchainComponent implements OnInit, OnDestroy {
|
export class BlockchainComponent implements OnInit, OnDestroy {
|
||||||
@Input() position: 'middle' | 'top' = 'middle';
|
|
||||||
@Input() markHeight: number;
|
|
||||||
@Input() txFeePerVSize: number;
|
|
||||||
@Input() markMempoolBlockIndex = -1;
|
|
||||||
|
|
||||||
txTrackingSubscription: Subscription;
|
|
||||||
blocksSubscription: Subscription;
|
blocksSubscription: Subscription;
|
||||||
|
|
||||||
txTrackingLoading = false;
|
txTrackingLoading = false;
|
||||||
@ -24,7 +17,6 @@ export class BlockchainComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private stateService: StateService,
|
private stateService: StateService,
|
||||||
private router: Router,
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
|
<div class="container-xl">
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
<table class="table table-borderless" [alwaysCallback]="true" [fromRoot]="true" [infiniteScrollContainer]="'body'" infiniteScroll [infiniteScrollDistance]="1.5" [infiniteScrollUpDistance]="1.5" [infiniteScrollThrottle]="50" (scrolled)="loadMore()">
|
<table class="table table-borderless" [alwaysCallback]="true" [fromRoot]="true" [infiniteScrollContainer]="'body'" infiniteScroll [infiniteScrollDistance]="1.5" [infiniteScrollUpDistance]="1.5" [infiniteScrollThrottle]="50" (scrolled)="loadMore()">
|
||||||
<thead>
|
<thead>
|
||||||
<th style="width: 15%;">Height</th>
|
<th style="width: 15%;">Height</th>
|
||||||
@ -30,3 +34,5 @@
|
|||||||
</ng-template>
|
</ng-template>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
</div>
|
@ -1,9 +1,5 @@
|
|||||||
<div class="container-xl" *ngIf="mempoolBlock">
|
<div class="container-xl" *ngIf="mempoolBlock">
|
||||||
|
|
||||||
<div style="position: relative;">
|
|
||||||
<app-blockchain position="top" [markMempoolBlockIndex]="mempoolBlockIndex"></app-blockchain>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="title-block">
|
<div class="title-block">
|
||||||
<h1>Mempool block</h1>
|
<h1>Mempool block</h1>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||||
import { StateService } from 'src/app/services/state.service';
|
import { StateService } from 'src/app/services/state.service';
|
||||||
import { ActivatedRoute, ParamMap } from '@angular/router';
|
import { ActivatedRoute, ParamMap } from '@angular/router';
|
||||||
import { switchMap, map } from 'rxjs/operators';
|
import { switchMap, map } from 'rxjs/operators';
|
||||||
@ -10,7 +10,7 @@ import { WebsocketService } from 'src/app/services/websocket.service';
|
|||||||
templateUrl: './mempool-block.component.html',
|
templateUrl: './mempool-block.component.html',
|
||||||
styleUrls: ['./mempool-block.component.scss']
|
styleUrls: ['./mempool-block.component.scss']
|
||||||
})
|
})
|
||||||
export class MempoolBlockComponent implements OnInit {
|
export class MempoolBlockComponent implements OnInit, OnDestroy {
|
||||||
mempoolBlockIndex: number;
|
mempoolBlockIndex: number;
|
||||||
mempoolBlock: MempoolBlock;
|
mempoolBlock: MempoolBlock;
|
||||||
|
|
||||||
@ -26,6 +26,7 @@ export class MempoolBlockComponent implements OnInit {
|
|||||||
this.route.paramMap.pipe(
|
this.route.paramMap.pipe(
|
||||||
switchMap((params: ParamMap) => {
|
switchMap((params: ParamMap) => {
|
||||||
this.mempoolBlockIndex = parseInt(params.get('id'), 10) || 0;
|
this.mempoolBlockIndex = parseInt(params.get('id'), 10) || 0;
|
||||||
|
this.stateService.markBlock$.next({ mempoolBlockIndex: this.mempoolBlockIndex });
|
||||||
return this.stateService.mempoolBlocks$
|
return this.stateService.mempoolBlocks$
|
||||||
.pipe(
|
.pipe(
|
||||||
map((mempoolBlocks) => mempoolBlocks[this.mempoolBlockIndex])
|
map((mempoolBlocks) => mempoolBlocks[this.mempoolBlockIndex])
|
||||||
@ -37,4 +38,8 @@ export class MempoolBlockComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.stateService.markBlock$.next({});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Component, OnInit, OnDestroy, Input, OnChanges, HostListener } from '@angular/core';
|
import { Component, OnInit, OnDestroy, HostListener } from '@angular/core';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { MempoolBlock } from 'src/app/interfaces/websocket.interface';
|
import { MempoolBlock } from 'src/app/interfaces/websocket.interface';
|
||||||
import { StateService } from 'src/app/services/state.service';
|
import { StateService } from 'src/app/services/state.service';
|
||||||
@ -9,7 +9,7 @@ import { Router } from '@angular/router';
|
|||||||
templateUrl: './mempool-blocks.component.html',
|
templateUrl: './mempool-blocks.component.html',
|
||||||
styleUrls: ['./mempool-blocks.component.scss']
|
styleUrls: ['./mempool-blocks.component.scss']
|
||||||
})
|
})
|
||||||
export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
|
export class MempoolBlocksComponent implements OnInit, OnDestroy {
|
||||||
mempoolBlocks: MempoolBlock[];
|
mempoolBlocks: MempoolBlock[];
|
||||||
mempoolBlocksFull: MempoolBlock[];
|
mempoolBlocksFull: MempoolBlock[];
|
||||||
mempoolBlocksSubscription: Subscription;
|
mempoolBlocksSubscription: Subscription;
|
||||||
@ -21,8 +21,8 @@ export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
rightPosition = 0;
|
rightPosition = 0;
|
||||||
transition = '1s';
|
transition = '1s';
|
||||||
|
|
||||||
@Input() txFeePerVSize: number;
|
markIndex: number;
|
||||||
@Input() markIndex: number;
|
txFeePerVSize: number;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private router: Router,
|
private router: Router,
|
||||||
@ -36,11 +36,23 @@ export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
this.mempoolBlocks = this.reduceMempoolBlocksToFitScreen(blocks);
|
this.mempoolBlocks = this.reduceMempoolBlocksToFitScreen(blocks);
|
||||||
this.calculateTransactionPosition();
|
this.calculateTransactionPosition();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.stateService.markBlock$
|
||||||
|
.subscribe((state) => {
|
||||||
|
this.markIndex = undefined;
|
||||||
|
this.txFeePerVSize = undefined;
|
||||||
|
if (state.mempoolBlockIndex !== undefined) {
|
||||||
|
this.markIndex = state.mempoolBlockIndex;
|
||||||
|
}
|
||||||
|
if (state.txFeePerVSize) {
|
||||||
|
this.txFeePerVSize = state.txFeePerVSize;
|
||||||
|
}
|
||||||
|
this.calculateTransactionPosition();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@HostListener('window:resize', ['$event'])
|
@HostListener('window:resize', ['$event'])
|
||||||
onResize() {
|
onResize() {
|
||||||
console.log('onResize');
|
|
||||||
if (this.mempoolBlocks.length) {
|
if (this.mempoolBlocks.length) {
|
||||||
this.mempoolBlocks = this.reduceMempoolBlocksToFitScreen(JSON.parse(JSON.stringify(this.mempoolBlocksFull)));
|
this.mempoolBlocks = this.reduceMempoolBlocksToFitScreen(JSON.parse(JSON.stringify(this.mempoolBlocksFull)));
|
||||||
}
|
}
|
||||||
@ -48,29 +60,27 @@ export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
|
|||||||
|
|
||||||
@HostListener('document:keydown', ['$event'])
|
@HostListener('document:keydown', ['$event'])
|
||||||
handleKeyboardEvents(event: KeyboardEvent) {
|
handleKeyboardEvents(event: KeyboardEvent) {
|
||||||
if (this.markIndex === -1) {
|
setTimeout(() => {
|
||||||
return;
|
if (this.markIndex === undefined) {
|
||||||
}
|
return;
|
||||||
if (event.key === 'ArrowRight') {
|
|
||||||
if (this.mempoolBlocks[this.markIndex - 1]) {
|
|
||||||
this.router.navigate(['/mempool-block/', this.markIndex - 1]);
|
|
||||||
} else {
|
|
||||||
this.stateService.blocks$
|
|
||||||
.subscribe((block) => {
|
|
||||||
if (this.stateService.latestBlockHeight === block.height) {
|
|
||||||
this.router.navigate(['/block/', block.id], { state: { data: { block } }});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} else if (event.key === 'ArrowLeft') {
|
if (event.key === 'ArrowRight') {
|
||||||
if (this.mempoolBlocks[this.markIndex + 1]) {
|
if (this.mempoolBlocks[this.markIndex - 1]) {
|
||||||
this.router.navigate(['/mempool-block/', this.markIndex + 1]);
|
this.router.navigate(['/mempool-block/', this.markIndex - 1]);
|
||||||
|
} else {
|
||||||
|
this.stateService.blocks$
|
||||||
|
.subscribe((block) => {
|
||||||
|
if (this.stateService.latestBlockHeight === block.height) {
|
||||||
|
this.router.navigate(['/block/', block.id], { state: { data: { block } }});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (event.key === 'ArrowLeft') {
|
||||||
|
if (this.mempoolBlocks[this.markIndex + 1]) {
|
||||||
|
this.router.navigate(['/mempool-block/', this.markIndex + 1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
|
||||||
|
|
||||||
ngOnChanges() {
|
|
||||||
this.calculateTransactionPosition();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
<div class="container-xl">
|
<div style="position: relative;">
|
||||||
<div style="position: relative;">
|
<app-blockchain></app-blockchain>
|
||||||
<app-blockchain></app-blockchain>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<hr>
|
<router-outlet></router-outlet>
|
||||||
<app-latest-blocks></app-latest-blocks>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
@ -1,11 +1,5 @@
|
|||||||
<div class="container-xl">
|
<div class="container-xl">
|
||||||
|
|
||||||
<div style="position: relative;">
|
|
||||||
<app-blockchain position="top" [txFeePerVSize]="tx?.fee / (tx?.weight / 4)" [markHeight]="tx?.status?.block_height"></app-blockchain>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="transaction-content">
|
|
||||||
|
|
||||||
<div class="title-block">
|
<div class="title-block">
|
||||||
<h1 class="float-md-left">Transaction</h1>
|
<h1 class="float-md-left">Transaction</h1>
|
||||||
|
|
||||||
@ -181,6 +175,5 @@
|
|||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
@ -65,6 +65,11 @@ export class TransactionComponent implements OnInit, OnDestroy {
|
|||||||
} else {
|
} else {
|
||||||
this.findBlockAndSetFeeRating();
|
this.findBlockAndSetFeeRating();
|
||||||
}
|
}
|
||||||
|
if (this.tx.status.confirmed) {
|
||||||
|
this.stateService.markBlock$.next({ blockHeight: tx.status.block_height });
|
||||||
|
} else {
|
||||||
|
this.stateService.markBlock$.next({ txFeePerVSize: tx.fee / (tx.weight / 4) });
|
||||||
|
}
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
this.error = error;
|
this.error = error;
|
||||||
@ -82,6 +87,7 @@ export class TransactionComponent implements OnInit, OnDestroy {
|
|||||||
block_hash: block.id,
|
block_hash: block.id,
|
||||||
block_time: block.timestamp,
|
block_time: block.timestamp,
|
||||||
};
|
};
|
||||||
|
this.stateService.markBlock$.next({ blockHeight: block.height });
|
||||||
this.audioService.playSound('magic');
|
this.audioService.playSound('magic');
|
||||||
this.findBlockAndSetFeeRating();
|
this.findBlockAndSetFeeRating();
|
||||||
});
|
});
|
||||||
@ -121,5 +127,6 @@ export class TransactionComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
this.websocketService.startTrackTransaction('stop');
|
this.websocketService.startTrackTransaction('stop');
|
||||||
|
this.stateService.markBlock$.next({});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,3 @@
|
|||||||
|
|
||||||
export interface BlockTransaction {
|
|
||||||
f: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface OptimizedMempoolStats {
|
export interface OptimizedMempoolStats {
|
||||||
id: number;
|
id: number;
|
||||||
added: string;
|
added: string;
|
||||||
@ -13,7 +8,3 @@ export interface OptimizedMempoolStats {
|
|||||||
mempool_byte_weight: number;
|
mempool_byte_weight: number;
|
||||||
vsizes: number[] | string[];
|
vsizes: number[] | string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FeeData {
|
|
||||||
vsize: { [ fee: string ]: number };
|
|
||||||
}
|
|
||||||
|
@ -4,6 +4,12 @@ import { Block, Transaction } from '../interfaces/electrs.interface';
|
|||||||
import { MempoolBlock, MemPoolState } from '../interfaces/websocket.interface';
|
import { MempoolBlock, MemPoolState } from '../interfaces/websocket.interface';
|
||||||
import { OptimizedMempoolStats } from '../interfaces/node-api.interface';
|
import { OptimizedMempoolStats } from '../interfaces/node-api.interface';
|
||||||
|
|
||||||
|
interface MarkBlockState {
|
||||||
|
blockHeight?: number;
|
||||||
|
mempoolBlockIndex?: number;
|
||||||
|
txFeePerVSize?: number;
|
||||||
|
}
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
@ -21,4 +27,6 @@ export class StateService {
|
|||||||
|
|
||||||
viewFiat$ = new BehaviorSubject<boolean>(false);
|
viewFiat$ = new BehaviorSubject<boolean>(false);
|
||||||
connectionState$ = new BehaviorSubject<0 | 1 | 2>(2);
|
connectionState$ = new BehaviorSubject<0 | 1 | 2>(2);
|
||||||
|
|
||||||
|
markBlock$ = new Subject<MarkBlockState>();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user