Index daily channel stats and show in dashboard widget

This commit is contained in:
nymkappa
2022-07-06 14:56:10 +02:00
parent 4009a066e0
commit 9000b6b18e
13 changed files with 386 additions and 26 deletions

View File

@@ -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;
}
}
}

View File

@@ -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>

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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');
}

View File

@@ -19,6 +19,16 @@
<div class="main-title">
<span i18n="lightning.statistics-title">Channels Statistics</span>&nbsp;
</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>

View File

@@ -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());
}
}

View File

@@ -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,

View File

@@ -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>