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 { TransactionComponent } from './components/transaction/transaction.component';
|
||||||
import { BlockComponent } from './components/block/block.component';
|
import { BlockComponent } from './components/block/block.component';
|
||||||
import { BlockViewComponent } from './components/block-view/block-view.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 { ClockComponent } from './components/clock/clock.component';
|
||||||
import { AddressComponent } from './components/address/address.component';
|
import { AddressComponent } from './components/address/address.component';
|
||||||
import { MasterPageComponent } from './components/master-page/master-page.component';
|
import { MasterPageComponent } from './components/master-page/master-page.component';
|
||||||
@ -378,6 +379,10 @@ let routes: Routes = [
|
|||||||
path: 'view/block/:id',
|
path: 'view/block/:id',
|
||||||
component: BlockViewComponent,
|
component: BlockViewComponent,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'view/mempool-block/:index',
|
||||||
|
component: MempoolBlockViewComponent,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'status',
|
path: 'status',
|
||||||
data: { networks: ['bitcoin', 'liquid'] },
|
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 { MempoolErrorComponent } from './components/mempool-error/mempool-error.component';
|
||||||
|
|
||||||
import { BlockViewComponent } from '../components/block-view/block-view.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 { MempoolBlockOverviewComponent } from '../components/mempool-block-overview/mempool-block-overview.component';
|
||||||
import { ClockchainComponent } from '../components/clockchain/clockchain.component';
|
import { ClockchainComponent } from '../components/clockchain/clockchain.component';
|
||||||
import { ClockFaceComponent } from '../components/clock-face/clock-face.component';
|
import { ClockFaceComponent } from '../components/clock-face/clock-face.component';
|
||||||
@ -136,6 +137,7 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir
|
|||||||
ColoredPriceDirective,
|
ColoredPriceDirective,
|
||||||
BlockchainComponent,
|
BlockchainComponent,
|
||||||
BlockViewComponent,
|
BlockViewComponent,
|
||||||
|
MempoolBlockViewComponent,
|
||||||
MempoolBlocksComponent,
|
MempoolBlocksComponent,
|
||||||
BlockchainBlocksComponent,
|
BlockchainBlocksComponent,
|
||||||
AmountComponent,
|
AmountComponent,
|
||||||
@ -199,6 +201,7 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir
|
|||||||
CalculatorComponent,
|
CalculatorComponent,
|
||||||
BitcoinsatoshisPipe,
|
BitcoinsatoshisPipe,
|
||||||
BlockViewComponent,
|
BlockViewComponent,
|
||||||
|
MempoolBlockViewComponent,
|
||||||
MempoolBlockOverviewComponent,
|
MempoolBlockOverviewComponent,
|
||||||
ClockchainComponent,
|
ClockchainComponent,
|
||||||
ClockComponent,
|
ClockComponent,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user