Index daily channel stats and show in dashboard widget
This commit is contained in:
@@ -15,7 +15,11 @@ export class ChangeComponent implements OnChanges {
|
||||
constructor() { }
|
||||
|
||||
ngOnChanges(): void {
|
||||
this.change = (this.current - this.previous) / this.previous * 100;
|
||||
if (!this.previous) {
|
||||
this.change = 0;
|
||||
} else {
|
||||
this.change = (this.current - this.previous) / this.previous * 100;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
<div class="widget-toggler">
|
||||
<a href="javascript:;" (click)="switchMode('avg')" class="toggler-option"
|
||||
[ngClass]="{'inactive': mode !== 'avg'}"><small>avg</small></a>
|
||||
<span style="color: #ffffff66; font-size: 8px"> | </span>
|
||||
<a href="javascript:;" (click)="switchMode('med')" class="toggler-option"
|
||||
[ngClass]="{'inactive': mode !== 'med'}"><small>med</small></a>
|
||||
</div>
|
||||
|
||||
<div class="fee-estimation-wrapper" *ngIf="statistics$ | async as statistics; else loadingReward">
|
||||
|
||||
<div class="fee-estimation-container" *ngIf="mode === 'avg'">
|
||||
<div class="item">
|
||||
<h5 class="card-title" i18n="ln.average-capacity">Avg Capacity</h5>
|
||||
<div class="card-text">
|
||||
<div class="fee-text">
|
||||
{{ statistics.latest?.avg_capacity || 0 | number: '1.0-0' }}
|
||||
<span i18n="shared.sat-vbyte|sat/vB">sats</span>
|
||||
</div>
|
||||
<span class="fiat">
|
||||
<app-change [current]="statistics.latest?.avg_capacity" [previous]="statistics.previous?.avg_capacity"></app-change>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item">
|
||||
<h5 class="card-title" i18n="ln.average-feerate">Avg Fee Rate</h5>
|
||||
<div class="card-text" i18n-ngbTooltip="ln.average-feerate-desc"
|
||||
ngbTooltip="The average fee rate charged by routing nodes, ignoring fee rates > 0.5% or 5000ppm"
|
||||
placement="bottom">
|
||||
<div class="fee-text">
|
||||
{{ statistics.latest?.avg_fee_rate || 0 | number: '1.0-0' }}
|
||||
<span i18n="shared.sat-vbyte|sat/vB">ppm</span>
|
||||
</div>
|
||||
<span class="fiat">
|
||||
<app-change [current]="statistics.latest?.avg_fee_rate" [previous]="statistics.previous?.avg_fee_rate"></app-change>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="item">
|
||||
<h5 class="card-title" i18n="ln.average-basefee">Avg Base Fee</h5>
|
||||
<div class="card-text" i18n-ngbTooltip="ln.average-basefee-desc"
|
||||
ngbTooltip="The average base fee charged by routing nodes, ignoring base fees > 5000ppm" placement="bottom">
|
||||
<div class="card-text">
|
||||
<div class="fee-text">
|
||||
{{ statistics.latest?.avg_base_fee_mtokens || 0 | number: '1.0-0' }}
|
||||
<span i18n="shared.sat-vbyte|sat/vB">msats</span>
|
||||
</div>
|
||||
<span class="fiat">
|
||||
<app-change [current]="statistics.latest?.avg_base_fee_mtokens" [previous]="statistics.previous?.avg_base_fee_mtokens"></app-change>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="fee-estimation-container" *ngIf="mode === 'med'">
|
||||
<div class="item">
|
||||
<h5 class="card-title" i18n="ln.median-capacity">Med Capacity</h5>
|
||||
<div class="card-text">
|
||||
<div class="fee-text">
|
||||
{{ statistics.latest?.med_capacity || 0 | number: '1.0-0' }}
|
||||
<span i18n="shared.sat-vbyte|sat/vB">sats</span>
|
||||
</div>
|
||||
<span class="fiat">
|
||||
<app-change [current]="statistics.latest?.med_capacity" [previous]="statistics.previous?.med_capacity"></app-change>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<h5 class="card-title" i18n="ln.average-feerate">Med Fee Rate</h5>
|
||||
<div class="card-text" i18n-ngbTooltip="ln.median-feerate-desc"
|
||||
ngbTooltip="The average fee rate charged by routing nodes, ignoring fee rates > 0.5% or 5000ppm"
|
||||
placement="bottom">
|
||||
<div class="fee-text">
|
||||
{{ statistics.latest?.med_fee_rate || 0 | number: '1.0-0' }}
|
||||
<span i18n="shared.sat-vbyte|sat/vB">ppm</span>
|
||||
</div>
|
||||
<span class="fiat">
|
||||
<app-change [current]="statistics.latest?.med_fee_rate" [previous]="statistics.previous?.med_fee_rate"></app-change>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<h5 class="card-title" i18n="ln.median-basefee">Med Base Fee</h5>
|
||||
<div class="card-text" i18n-ngbTooltip="ln.median-basefee-desc"
|
||||
ngbTooltip="The median base fee charged by routing nodes, ignoring base fees > 5000ppm" placement="bottom">
|
||||
<div class="card-text">
|
||||
<div class="fee-text">
|
||||
{{ statistics.latest?.med_base_fee_mtokens || 0 | number: '1.0-0' }}
|
||||
<span i18n="shared.sat-vbyte|sat/vB">msats</span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="fiat">
|
||||
<app-change [current]="statistics.latest?.med_base_fee_mtokens" [previous]="statistics.previous?.med_base_fee_mtokens"></app-change>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ng-template #loadingReward>
|
||||
<div class="fee-estimation-container loading-container">
|
||||
<div class="item">
|
||||
<h5 class="card-title" i18n="mining.rewards">Nodes</h5>
|
||||
<div class="card-text">
|
||||
<div class="skeleton-loader"></div>
|
||||
<div class="skeleton-loader"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<h5 class="card-title" i18n="mining.rewards-per-tx">Channels</h5>
|
||||
<div class="card-text">
|
||||
<div class="skeleton-loader"></div>
|
||||
<div class="skeleton-loader"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<h5 class="card-title" i18n="mining.average-fee">Average Channel</h5>
|
||||
<div class="card-text">
|
||||
<div class="skeleton-loader"></div>
|
||||
<div class="skeleton-loader"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
@@ -0,0 +1,101 @@
|
||||
.card-title {
|
||||
color: #4a68b9;
|
||||
font-size: 10px;
|
||||
margin-bottom: 4px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.card-text {
|
||||
font-size: 22px;
|
||||
span {
|
||||
font-size: 11px;
|
||||
position: relative;
|
||||
top: -2px;
|
||||
display: inline-flex;
|
||||
}
|
||||
.green-color {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.fee-estimation-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
@media (min-width: 376px) {
|
||||
flex-direction: row;
|
||||
}
|
||||
.item {
|
||||
max-width: 150px;
|
||||
margin: 0;
|
||||
width: -webkit-fill-available;
|
||||
@media (min-width: 376px) {
|
||||
margin: 0 auto 0px;
|
||||
}
|
||||
&:first-child{
|
||||
display: none;
|
||||
@media (min-width: 485px) {
|
||||
display: block;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
display: none;
|
||||
}
|
||||
@media (min-width: 992px) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.card-text span {
|
||||
color: #ffffff66;
|
||||
font-size: 12px;
|
||||
top: 0px;
|
||||
}
|
||||
.fee-text{
|
||||
border-bottom: 1px solid #ffffff1c;
|
||||
width: fit-content;
|
||||
margin: auto;
|
||||
line-height: 1.45;
|
||||
padding: 0px 2px;
|
||||
}
|
||||
.fiat {
|
||||
display: block;
|
||||
font-size: 14px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.loading-container {
|
||||
min-height: 76px;
|
||||
}
|
||||
|
||||
.card-text {
|
||||
.skeleton-loader {
|
||||
width: 100%;
|
||||
display: block;
|
||||
&:first-child {
|
||||
max-width: 90px;
|
||||
margin: 15px auto 3px;
|
||||
}
|
||||
&:last-child {
|
||||
margin: 10px auto 3px;
|
||||
max-width: 55px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.widget-toggler {
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
top: -20px;
|
||||
right: 3px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.toggler-option {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.inactive {
|
||||
color: #ffffff66;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'app-channels-statistics',
|
||||
templateUrl: './channels-statistics.component.html',
|
||||
styleUrls: ['./channels-statistics.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ChannelsStatisticsComponent implements OnInit {
|
||||
@Input() statistics$: Observable<any>;
|
||||
mode: string = 'avg';
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
switchMode(mode: 'avg' | 'med') {
|
||||
this.mode = mode;
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,10 @@ export class LightningApiService {
|
||||
return this.httpClient.get<any>(this.apiBasePath + '/api/v1/lightning/nodes/top');
|
||||
}
|
||||
|
||||
listChannelStats$(publicKey: string): Observable<any> {
|
||||
return this.httpClient.get<any>(this.apiBasePath + '/channels/' + publicKey + '/statistics');
|
||||
}
|
||||
|
||||
listStatistics$(): Observable<any> {
|
||||
return this.httpClient.get<any>(this.apiBasePath + '/api/v1/lightning/statistics');
|
||||
}
|
||||
|
||||
@@ -19,6 +19,16 @@
|
||||
<div class="main-title">
|
||||
<span i18n="lightning.statistics-title">Channels Statistics</span>
|
||||
</div>
|
||||
<div class="card-wrapper">
|
||||
<div class="card" style="height: 123px">
|
||||
<div class="card-body more-padding">
|
||||
<app-channels-statistics [statistics$]="statistics$"></app-channels-statistics>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<div class="card-wrapper">
|
||||
|
||||
</div>
|
||||
|
||||
@@ -35,7 +35,7 @@ export class LightningDashboardComponent implements OnInit {
|
||||
map((object) => object.topByChannels),
|
||||
);
|
||||
|
||||
this.statistics$ = this.lightningApiService.getLatestStatistics$();
|
||||
this.statistics$ = this.lightningApiService.getLatestStatistics$().pipe(share());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import { LightningStatisticsChartComponent } from './statistics-chart/lightning-
|
||||
import { NodeStatisticsChartComponent } from './node-statistics-chart/node-statistics-chart.component';
|
||||
import { GraphsModule } from '../graphs/graphs.module';
|
||||
import { NodesNetworksChartComponent } from './nodes-networks-chart/nodes-networks-chart.component';
|
||||
import { ChannelsStatisticsComponent } from './channels-statistics/channels-statistics.component';
|
||||
@NgModule({
|
||||
declarations: [
|
||||
LightningDashboardComponent,
|
||||
@@ -31,6 +32,7 @@ import { NodesNetworksChartComponent } from './nodes-networks-chart/nodes-networ
|
||||
ClosingTypeComponent,
|
||||
LightningStatisticsChartComponent,
|
||||
NodesNetworksChartComponent,
|
||||
ChannelsStatisticsComponent,
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
|
||||
@@ -2,18 +2,21 @@
|
||||
<div class="fee-estimation-container">
|
||||
<div class="item">
|
||||
<h5 class="card-title" i18n="mining.average-fee">Capacity</h5>
|
||||
<div class="card-text" i18n-ngbTooltip="mining.average-fee"
|
||||
ngbTooltip="Percentage change past week" placement="bottom">
|
||||
<app-amount [satoshis]="statistics.latest?.total_capacity" digitsInfo="1.2-2"></app-amount>
|
||||
<div class="card-text" i18n-ngbTooltip="mining.average-fee" ngbTooltip="Percentage change past week"
|
||||
placement="bottom">
|
||||
<div class="fee-text">
|
||||
<app-amount [satoshis]="statistics.latest?.total_capacity" digitsInfo="1.2-2"></app-amount>
|
||||
</div>
|
||||
<span class="fiat" *ngIf="statistics.previous">
|
||||
<app-change [current]="statistics.latest.total_capacity" [previous]="statistics.previous.total_capacity"></app-change>
|
||||
<app-change [current]="statistics.latest.total_capacity" [previous]="statistics.previous.total_capacity">
|
||||
</app-change>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<h5 class="card-title" i18n="mining.rewards">Nodes</h5>
|
||||
<div class="card-text" i18n-ngbTooltip="mining.rewards-desc"
|
||||
ngbTooltip="Percentage change past week" placement="bottom">
|
||||
<div class="card-text" i18n-ngbTooltip="mining.rewards-desc" ngbTooltip="Percentage change past week"
|
||||
placement="bottom">
|
||||
<div class="fee-text">
|
||||
{{ statistics.latest?.node_count || 0 | number }}
|
||||
</div>
|
||||
@@ -24,13 +27,14 @@
|
||||
</div>
|
||||
<div class="item">
|
||||
<h5 class="card-title" i18n="mining.rewards-per-tx">Channels</h5>
|
||||
<div class="card-text" i18n-ngbTooltip="mining.rewards-per-tx-desc"
|
||||
ngbTooltip="Percentage change past week" placement="bottom">
|
||||
<div class="card-text" i18n-ngbTooltip="mining.rewards-per-tx-desc" ngbTooltip="Percentage change past week"
|
||||
placement="bottom">
|
||||
<div class="fee-text">
|
||||
{{ statistics.latest?.channel_count || 0 | number }}
|
||||
</div>
|
||||
<span class="fiat" *ngIf="statistics.previous">
|
||||
<app-change [current]="statistics.latest.channel_count" [previous]="statistics.previous.channel_count"></app-change>
|
||||
<app-change [current]="statistics.latest.channel_count" [previous]="statistics.previous.channel_count">
|
||||
</app-change>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -73,4 +77,4 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
Reference in New Issue
Block a user