Add standalone mempool block visualization page
This commit is contained in:
parent
72750267d0
commit
6773af92ed
@ -5,6 +5,7 @@ import { StartComponent } from './components/start/start.component';
|
||||
import { TransactionComponent } from './components/transaction/transaction.component';
|
||||
import { BlockComponent } from './components/block/block.component';
|
||||
import { BlockViewComponent } from './components/block-view/block-view.component';
|
||||
import { MempoolBlockViewComponent } from './components/mempool-block-view/mempool-block-view.component';
|
||||
import { ClockComponent } from './components/clock/clock.component';
|
||||
import { AddressComponent } from './components/address/address.component';
|
||||
import { MasterPageComponent } from './components/master-page/master-page.component';
|
||||
@ -378,6 +379,10 @@ let routes: Routes = [
|
||||
path: 'view/block/:id',
|
||||
component: BlockViewComponent,
|
||||
},
|
||||
{
|
||||
path: 'view/mempool-block/:index',
|
||||
component: MempoolBlockViewComponent,
|
||||
},
|
||||
{
|
||||
path: 'status',
|
||||
data: { networks: ['bitcoin', 'liquid'] },
|
||||
|
@ -0,0 +1,5 @@
|
||||
<div class="block-wrapper">
|
||||
<div class="block-container">
|
||||
<app-mempool-block-overview [index]="index"></app-mempool-block-overview>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,22 @@
|
||||
.block-wrapper {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
background: #181b2d;
|
||||
}
|
||||
|
||||
.block-container {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
width: 100vw;
|
||||
max-width: 100vh;
|
||||
height: 100vh;
|
||||
padding: 0;
|
||||
margin: auto;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
* {
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
import { Component, OnInit, OnDestroy, HostListener } from '@angular/core';
|
||||
import { ActivatedRoute, ParamMap } from '@angular/router';
|
||||
import { Subscription, filter, map, switchMap, tap } from 'rxjs';
|
||||
import { StateService } from '../../services/state.service';
|
||||
import { WebsocketService } from '../../services/websocket.service';
|
||||
|
||||
function bestFitResolution(min, max, n): number {
|
||||
const target = (min + max) / 2;
|
||||
let bestScore = Infinity;
|
||||
let best = null;
|
||||
for (let i = min; i <= max; i++) {
|
||||
const remainder = (n % i);
|
||||
if (remainder < bestScore || (remainder === bestScore && (Math.abs(i - target) < Math.abs(best - target)))) {
|
||||
bestScore = remainder;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'app-mempool-block-view',
|
||||
templateUrl: './mempool-block-view.component.html',
|
||||
styleUrls: ['./mempool-block-view.component.scss']
|
||||
})
|
||||
export class MempoolBlockViewComponent implements OnInit, OnDestroy {
|
||||
autofit: boolean = false;
|
||||
resolution: number = 80;
|
||||
index: number = 0;
|
||||
|
||||
routeParamsSubscription: Subscription;
|
||||
queryParamsSubscription: Subscription;
|
||||
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private websocketService: WebsocketService,
|
||||
public stateService: StateService,
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.websocketService.want(['blocks', 'mempool-blocks']);
|
||||
|
||||
this.routeParamsSubscription = this.route.paramMap
|
||||
.pipe(
|
||||
switchMap((params: ParamMap) => {
|
||||
this.index = parseInt(params.get('index'), 10) || 0;
|
||||
return this.stateService.mempoolBlocks$
|
||||
.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),
|
||||
tap((mempoolBlocks) => {
|
||||
while (!mempoolBlocks[this.index]) {
|
||||
this.index--;
|
||||
}
|
||||
})
|
||||
);
|
||||
})
|
||||
).subscribe();
|
||||
|
||||
this.queryParamsSubscription = this.route.queryParams.subscribe((params) => {
|
||||
this.autofit = params.autofit === 'true';
|
||||
if (this.autofit) {
|
||||
this.onResize();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@HostListener('window:resize', ['$event'])
|
||||
onResize(): void {
|
||||
if (this.autofit) {
|
||||
this.resolution = bestFitResolution(64, 96, Math.min(window.innerWidth, window.innerHeight));
|
||||
}
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.routeParamsSubscription.unsubscribe();
|
||||
this.queryParamsSubscription.unsubscribe();
|
||||
}
|
||||
}
|
@ -98,6 +98,7 @@ import { AccelerateFeeGraphComponent } from '../components/accelerate-preview/ac
|
||||
import { MempoolErrorComponent } from './components/mempool-error/mempool-error.component';
|
||||
|
||||
import { BlockViewComponent } from '../components/block-view/block-view.component';
|
||||
import { MempoolBlockViewComponent } from '../components/mempool-block-view/mempool-block-view.component';
|
||||
import { MempoolBlockOverviewComponent } from '../components/mempool-block-overview/mempool-block-overview.component';
|
||||
import { ClockchainComponent } from '../components/clockchain/clockchain.component';
|
||||
import { ClockFaceComponent } from '../components/clock-face/clock-face.component';
|
||||
@ -136,6 +137,7 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir
|
||||
ColoredPriceDirective,
|
||||
BlockchainComponent,
|
||||
BlockViewComponent,
|
||||
MempoolBlockViewComponent,
|
||||
MempoolBlocksComponent,
|
||||
BlockchainBlocksComponent,
|
||||
AmountComponent,
|
||||
@ -199,6 +201,7 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir
|
||||
CalculatorComponent,
|
||||
BitcoinsatoshisPipe,
|
||||
BlockViewComponent,
|
||||
MempoolBlockViewComponent,
|
||||
MempoolBlockOverviewComponent,
|
||||
ClockchainComponent,
|
||||
ClockComponent,
|
||||
|
Loading…
x
Reference in New Issue
Block a user