mirror of
https://github.com/mempool/mempool.git
synced 2025-01-18 21:32:55 +01:00
Added fee distribution Pie Chart to the block inspector.
This commit is contained in:
parent
bd19b88f11
commit
9b287336d0
@ -19,6 +19,7 @@ import { BlockchainBlocksComponent } from './blockchain-blocks/blockchain-blocks
|
||||
import { BlockchainProjectedBlocksComponent } from './blockchain-projected-blocks/blockchain-projected-blocks.component';
|
||||
import { ApiService } from './services/api.service';
|
||||
import { MasterPageComponent } from './master-page/master-page.component';
|
||||
import { FeeDistributionGraphComponent } from './fee-distribution-graph/fee-distribution-graph.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@ -34,6 +35,7 @@ import { MasterPageComponent } from './master-page/master-page.component';
|
||||
BlockchainBlocksComponent,
|
||||
BlockchainProjectedBlocksComponent,
|
||||
MasterPageComponent,
|
||||
FeeDistributionGraphComponent,
|
||||
],
|
||||
imports: [
|
||||
ReactiveFormsModule,
|
||||
|
@ -30,16 +30,5 @@
|
||||
|
||||
<hr>
|
||||
|
||||
<div style="height: 400px;" *ngIf="mempoolVsizeFeesData; else loadingFees">
|
||||
<app-chartist
|
||||
[data]="mempoolVsizeFeesData"
|
||||
[type]="'Bar'"
|
||||
[options]="mempoolVsizeFeesOptions">
|
||||
</app-chartist>
|
||||
</div>
|
||||
<ng-template #loadingFees>
|
||||
<div class="text-center">
|
||||
<div class="spinner-border text-light"></div>
|
||||
</div>
|
||||
</ng-template>
|
||||
<app-fee-distribution-graph [blockHeight]="block.height"></app-fee-distribution-graph>
|
||||
</div>
|
||||
|
@ -1,9 +1,7 @@
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ApiService } from '../../services/api.service';
|
||||
import { IBlock } from '../../blockchain/interfaces';
|
||||
import { MemPoolService } from '../../services/mem-pool.service';
|
||||
import * as Chartist from 'chartist';
|
||||
|
||||
@Component({
|
||||
selector: 'app-block-modal',
|
||||
@ -13,61 +11,17 @@ import * as Chartist from 'chartist';
|
||||
export class BlockModalComponent implements OnInit {
|
||||
@Input() block: IBlock;
|
||||
|
||||
mempoolVsizeFeesData: any;
|
||||
mempoolVsizeFeesOptions: any;
|
||||
conversions: any;
|
||||
|
||||
constructor(
|
||||
public activeModal: NgbActiveModal,
|
||||
private apiService: ApiService,
|
||||
private memPoolService: MemPoolService,
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
|
||||
this.mempoolVsizeFeesOptions = {
|
||||
showArea: false,
|
||||
showLine: false,
|
||||
fullWidth: false,
|
||||
showPoint: false,
|
||||
low: 0,
|
||||
axisX: {
|
||||
position: 'start',
|
||||
showLabel: false,
|
||||
offset: 0,
|
||||
showGrid: false,
|
||||
},
|
||||
axisY: {
|
||||
position: 'end',
|
||||
scaleMinSpace: 40,
|
||||
showGrid: false,
|
||||
},
|
||||
plugins: [
|
||||
Chartist.plugins.tooltip({
|
||||
tooltipOffset: {
|
||||
x: 15,
|
||||
y: 250
|
||||
},
|
||||
transformTooltipTextFnc: (value: number): any => {
|
||||
return Math.ceil(value) + ' sat/vB';
|
||||
},
|
||||
anchorToPoint: false,
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
this.memPoolService.conversions$
|
||||
.subscribe((conversions) => {
|
||||
this.conversions = conversions;
|
||||
});
|
||||
|
||||
this.apiService.listTransactionsForBlock$(this.block.height)
|
||||
.subscribe((data) => {
|
||||
this.mempoolVsizeFeesData = {
|
||||
labels: data.map((x, i) => i),
|
||||
series: [data.map((tx) => tx.fpv)]
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,16 +26,5 @@
|
||||
|
||||
<hr>
|
||||
|
||||
<div style="height: 400px;" *ngIf="mempoolVsizeFeesData; else loadingFees">
|
||||
<app-chartist
|
||||
[data]="mempoolVsizeFeesData"
|
||||
[type]="'Bar'"
|
||||
[options]="mempoolVsizeFeesOptions">
|
||||
</app-chartist>
|
||||
</div>
|
||||
<ng-template #loadingFees>
|
||||
<div class="text-center">
|
||||
<div class="spinner-border text-light"></div>
|
||||
</div>
|
||||
</ng-template>
|
||||
<app-fee-distribution-graph [projectedBlockIndex]="index"></app-fee-distribution-graph>
|
||||
</div>
|
||||
|
@ -1,9 +1,7 @@
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ApiService } from '../../services/api.service';
|
||||
import { IBlock } from '../../blockchain/interfaces';
|
||||
import { MemPoolService } from '../../services/mem-pool.service';
|
||||
import * as Chartist from 'chartist';
|
||||
import { IBlock } from 'src/app/blockchain/interfaces';
|
||||
|
||||
@Component({
|
||||
selector: 'app-projected-block-modal',
|
||||
@ -14,61 +12,18 @@ export class ProjectedBlockModalComponent implements OnInit {
|
||||
@Input() block: IBlock;
|
||||
@Input() index: number;
|
||||
|
||||
mempoolVsizeFeesData: any;
|
||||
mempoolVsizeFeesOptions: any;
|
||||
conversions: any;
|
||||
|
||||
constructor(
|
||||
public activeModal: NgbActiveModal,
|
||||
private apiService: ApiService,
|
||||
private memPoolService: MemPoolService,
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
|
||||
this.mempoolVsizeFeesOptions = {
|
||||
showArea: false,
|
||||
showLine: false,
|
||||
fullWidth: false,
|
||||
showPoint: false,
|
||||
low: 0,
|
||||
axisX: {
|
||||
position: 'start',
|
||||
showLabel: false,
|
||||
offset: 0,
|
||||
showGrid: false,
|
||||
},
|
||||
axisY: {
|
||||
position: 'end',
|
||||
scaleMinSpace: 40,
|
||||
showGrid: false,
|
||||
},
|
||||
plugins: [
|
||||
Chartist.plugins.tooltip({
|
||||
tooltipOffset: {
|
||||
x: 15,
|
||||
y: 250
|
||||
},
|
||||
transformTooltipTextFnc: (value: number): any => {
|
||||
return Math.ceil(value) + ' sat/vB';
|
||||
},
|
||||
anchorToPoint: false,
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
this.memPoolService.conversions$
|
||||
.subscribe((conversions) => {
|
||||
this.conversions = conversions;
|
||||
});
|
||||
|
||||
this.apiService.listTransactionsForProjectedBlock$(this.index)
|
||||
.subscribe((data) => {
|
||||
this.mempoolVsizeFeesData = {
|
||||
labels: data.map((x, i) => i),
|
||||
series: [data.map((tx) => tx.fpv)]
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,30 @@
|
||||
<div style="height: 400px;" *ngIf="mempoolVsizeFeesData; else loadingFees">
|
||||
<form [formGroup]="radioGroupForm" style="position: absolute;">
|
||||
<div class="btn-group btn-group-toggle" ngbRadioGroup name="radioBasic" formControlName="model">
|
||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||
<input ngbButton type="radio" value="line"> Line
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||
<input ngbButton type="radio" value="pie"> Pie
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
<app-chartist
|
||||
*ngIf="radioGroupForm.get('model')?.value === 'pie'"
|
||||
[data]="mempoolVsizeFeesPieData"
|
||||
[type]="'Pie'"
|
||||
[options]="mempoolVsizeFeesPieOptions">
|
||||
</app-chartist>
|
||||
<app-chartist
|
||||
*ngIf="radioGroupForm.get('model')?.value === 'line'"
|
||||
[data]="mempoolVsizeFeesData"
|
||||
[type]="'Bar'"
|
||||
[options]="mempoolVsizeFeesOptions">
|
||||
</app-chartist>
|
||||
</div>
|
||||
|
||||
<ng-template #loadingFees>
|
||||
<div class="text-center">
|
||||
<div class="spinner-border text-light"></div>
|
||||
</div>
|
||||
</ng-template>
|
@ -0,0 +1,131 @@
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import * as Chartist from 'chartist';
|
||||
import { ApiService } from '../services/api.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-fee-distribution-graph',
|
||||
templateUrl: './fee-distribution-graph.component.html',
|
||||
styleUrls: ['./fee-distribution-graph.component.scss']
|
||||
})
|
||||
export class FeeDistributionGraphComponent implements OnInit {
|
||||
@Input() projectedBlockIndex: number;
|
||||
@Input() blockHeight: number;
|
||||
|
||||
mempoolVsizeFeesData: any;
|
||||
mempoolVsizeFeesOptions: any;
|
||||
|
||||
mempoolVsizeFeesPieData: any;
|
||||
mempoolVsizeFeesPieOptions: any;
|
||||
|
||||
feeLevels = [1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 20, 30, 40, 50, 60, 70, 80, 90, 100, 125, 150, 175, 200,
|
||||
250, 300, 350, 400, 500];
|
||||
|
||||
radioGroupForm: FormGroup;
|
||||
|
||||
constructor(
|
||||
private formBuilder: FormBuilder,
|
||||
private apiService: ApiService,
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.radioGroupForm = this.formBuilder.group({
|
||||
model: ['line'],
|
||||
});
|
||||
|
||||
this.mempoolVsizeFeesOptions = {
|
||||
showArea: false,
|
||||
showLine: false,
|
||||
fullWidth: false,
|
||||
showPoint: false,
|
||||
low: 0,
|
||||
axisX: {
|
||||
position: 'start',
|
||||
showLabel: false,
|
||||
offset: 0,
|
||||
showGrid: false,
|
||||
},
|
||||
axisY: {
|
||||
position: 'end',
|
||||
scaleMinSpace: 40,
|
||||
showGrid: false,
|
||||
},
|
||||
plugins: [
|
||||
Chartist.plugins.tooltip({
|
||||
tooltipOffset: {
|
||||
x: 15,
|
||||
y: 250
|
||||
},
|
||||
transformTooltipTextFnc: (value: number): any => {
|
||||
return Math.ceil(value) + ' sat/vB';
|
||||
},
|
||||
anchorToPoint: false,
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
this.mempoolVsizeFeesPieOptions = {
|
||||
showLabel: false,
|
||||
plugins: [
|
||||
Chartist.plugins.tooltip({
|
||||
tooltipOffset: {
|
||||
x: 15,
|
||||
y: 250
|
||||
},
|
||||
transformTooltipTextFnc: (value: string, seriesName: string): any => {
|
||||
const index = parseInt(seriesName.split(' ')[2].split('-')[1], 10);
|
||||
const intValue = parseInt(value, 10);
|
||||
const result = Math.ceil(intValue) + ' tx @ ' + this.feeLevels[index] +
|
||||
(this.feeLevels[index + 1] ? '-' + this.feeLevels[index + 1] : '+' ) + ' sat/vB';
|
||||
|
||||
return result;
|
||||
},
|
||||
anchorToPoint: false,
|
||||
})
|
||||
]
|
||||
};
|
||||
|
||||
let sub;
|
||||
if (this.blockHeight) {
|
||||
sub = this.apiService.listTransactionsForBlock$(this.blockHeight);
|
||||
} else {
|
||||
sub = this.apiService.listTransactionsForProjectedBlock$(this.projectedBlockIndex);
|
||||
}
|
||||
|
||||
sub.subscribe((data) => {
|
||||
const fees = data.map((tx) => tx.fpv);
|
||||
|
||||
const series = [];
|
||||
|
||||
for (let i = 0; i < this.feeLevels.length; i++) {
|
||||
let total = 0;
|
||||
for (let j = 0; j < fees.length; j++) {
|
||||
if (i === this.feeLevels.length - 1) {
|
||||
if (fees[j] >= this.feeLevels[i]) {
|
||||
total += 1;
|
||||
}
|
||||
} else if (fees[j] >= this.feeLevels[i] && fees[j] < this.feeLevels[i + 1]) {
|
||||
total += 1;
|
||||
}
|
||||
}
|
||||
series.push(total);
|
||||
}
|
||||
|
||||
this.mempoolVsizeFeesPieData = {
|
||||
series: series.map((d, index: number) => {
|
||||
return {
|
||||
value: d,
|
||||
className: 'ct-series-' + Chartist.alphaNumerate(index) + ' index-' + index
|
||||
};
|
||||
}),
|
||||
labels: data.map((x, i) => i),
|
||||
};
|
||||
|
||||
this.mempoolVsizeFeesData = {
|
||||
labels: data.map((x, i) => i),
|
||||
series: [fees]
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -496,9 +496,9 @@ Chartist.plugins.tooltip = function (options: any) {
|
||||
|
||||
return function tooltip(chart: any) {
|
||||
let tooltipSelector = options.pointClass;
|
||||
if (chart.constructor.name === Chartist.Bar.prototype.constructor.name) {
|
||||
if (chart instanceof Chartist.Bar) {
|
||||
tooltipSelector = 'ct-bar';
|
||||
} else if (chart.constructor.name === Chartist.Pie.prototype.constructor.name) {
|
||||
} else if (chart instanceof Chartist.Pie) {
|
||||
// Added support for donut graph
|
||||
if (chart.options.donut) {
|
||||
tooltipSelector = 'ct-slice-donut';
|
||||
@ -542,7 +542,7 @@ Chartist.plugins.tooltip = function (options: any) {
|
||||
let value = $point.getAttribute('ct:value');
|
||||
|
||||
if (options.transformTooltipTextFnc && typeof options.transformTooltipTextFnc === 'function') {
|
||||
value = options.transformTooltipTextFnc(value);
|
||||
value = options.transformTooltipTextFnc(value, $point.parentNode.getAttribute('class'));
|
||||
}
|
||||
|
||||
if (options.tooltipFnc && typeof options.tooltipFnc === 'function') {
|
||||
|
Loading…
Reference in New Issue
Block a user