Merge branch 'master' into nymkappa/bugfix/missing-last-data-charts

This commit is contained in:
wiz 2022-08-08 15:59:34 +09:00 committed by GitHub
commit 771d21e410
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 55 additions and 58 deletions

View file

@ -4,7 +4,7 @@ import logger from '../logger';
import { Common } from './common'; import { Common } from './common';
class DatabaseMigration { class DatabaseMigration {
private static currentVersion = 34; private static currentVersion = 35;
private queryTimeout = 120000; private queryTimeout = 120000;
private statisticsAddedIndexed = false; private statisticsAddedIndexed = false;
private uniqueLogs: string[] = []; private uniqueLogs: string[] = [];
@ -315,6 +315,11 @@ class DatabaseMigration {
if (databaseSchemaVersion < 34 && isBitcoin == true) { if (databaseSchemaVersion < 34 && isBitcoin == true) {
await this.$executeQuery('ALTER TABLE `lightning_stats` ADD clearnet_tor_nodes int(11) NOT NULL DEFAULT "0"'); await this.$executeQuery('ALTER TABLE `lightning_stats` ADD clearnet_tor_nodes int(11) NOT NULL DEFAULT "0"');
} }
if (databaseSchemaVersion < 35 && isBitcoin == true) {
await this.$executeQuery('DELETE from `lightning_stats` WHERE added > "2021-09-19"');
await this.$executeQuery('ALTER TABLE `lightning_stats` ADD CONSTRAINT added_unique UNIQUE (added);');
}
} }
/** /**

View file

@ -71,8 +71,11 @@ export async function convertAndmergeBidirectionalChannels(clChannels: any[]): P
} }
export function convertChannelId(channelId): string { export function convertChannelId(channelId): string {
const s = channelId.split('x').map(part => parseInt(part)); if (channelId.indexOf('/') !== -1) {
return BigInt((s[0] << 40) | (s[1] << 16) | s[2]).toString(); channelId = channelId.slice(0, -2);
}
const s = channelId.split('x').map(part => BigInt(part));
return ((s[0] << 40n) | (s[1] << 16n) | s[2]).toString();
} }
/** /**

View file

@ -430,10 +430,13 @@ class NetworkSyncService {
} }
private toIntegerId(id: string): string { private toIntegerId(id: string): string {
if (config.LIGHTNING.BACKEND === 'lnd') { if (config.LIGHTNING.BACKEND === 'cln') {
return convertChannelId(id);
}
else if (config.LIGHTNING.BACKEND === 'lnd') {
return id; return id;
} }
return convertChannelId(id); return '';
} }
/** Decodes a channel id returned by lnd as uint64 to a short channel id */ /** Decodes a channel id returned by lnd as uint64 to a short channel id */

View file

@ -8,8 +8,8 @@ class LightningStatsUpdater {
public async $startService(): Promise<void> { public async $startService(): Promise<void> {
logger.info('Starting Lightning Stats service'); logger.info('Starting Lightning Stats service');
// LightningStatsImporter.$run(); await this.$runTasks();
this.$runTasks(); LightningStatsImporter.$run();
} }
private setDateMidnight(date: Date): void { private setDateMidnight(date: Date): void {
@ -34,7 +34,7 @@ class LightningStatsUpdater {
const date = new Date(); const date = new Date();
this.setDateMidnight(date); this.setDateMidnight(date);
logger.info(`Updating latest node stats`); logger.info(`Updating latest networks stats`);
const networkGraph = await lightningApi.$getNetworkGraph(); const networkGraph = await lightningApi.$getNetworkGraph();
LightningStatsImporter.computeNetworkStats(date.getTime() / 1000, networkGraph); LightningStatsImporter.computeNetworkStats(date.getTime() / 1000, networkGraph);
} }

View file

@ -1,7 +1,7 @@
<ng-container *ngIf="{ val: network$ | async } as network"> <ng-container *ngIf="{ val: network$ | async } as network">
<header> <header>
<nav class="navbar navbar-expand-md navbar-dark bg-dark"> <nav class="navbar navbar-expand-md navbar-dark bg-dark">
<a class="navbar-brand" [routerLink]="['/' | relativeUrl]"> <a class="navbar-brand" [ngClass]="{'dual-logos': subdomain}" [routerLink]="['/' | relativeUrl]">
<ng-template [ngIf]="subdomain"> <ng-template [ngIf]="subdomain">
<div class="subdomain_container"> <div class="subdomain_container">
<img [src]="'/api/v1/enterprise/images/' + subdomain + '/logo'" class="subdomain_logo"> <img [src]="'/api/v1/enterprise/images/' + subdomain + '/logo'" class="subdomain_logo">

View file

@ -9,6 +9,7 @@ fa-icon {
.navbar { .navbar {
z-index: 100; z-index: 100;
min-height: 64px; min-height: 64px;
width: 100%;
} }
li.nav-item { li.nav-item {
@ -86,6 +87,13 @@ li.nav-item {
height: 65px; height: 65px;
} }
.navbar-brand.dual-logos {
justify-content: space-between;
@media (max-width: 767.98px) {
width: 100%;
}
}
nav { nav {
box-shadow: 0px 0px 15px 0px #000; box-shadow: 0px 0px 15px 0px #000;
} }

View file

@ -102,9 +102,7 @@
</div> </div>
<br> <div class="input-group mt-3" *ngIf="!error && node.socketsObject.length">
<div class="input-group mb-3" *ngIf="!error && node.socketsObject.length">
<div class="d-inline-block" ngbDropdown #myDrop="ngbDropdown" <div class="d-inline-block" ngbDropdown #myDrop="ngbDropdown"
*ngIf="node.socketsObject.length > 1; else noDropdown"> *ngIf="node.socketsObject.length > 1; else noDropdown">
<button class="btn btn-secondary dropdown-toggle" type="button" aria-expanded="false" ngbDropdownAnchor <button class="btn btn-secondary dropdown-toggle" type="button" aria-expanded="false" ngbDropdownAnchor
@ -133,22 +131,14 @@
</button> </button>
</div> </div>
<br> <app-nodes-channels-map *ngIf="!error" [style]="'nodepage'" [publicKey]="node.public_key"></app-nodes-channels-map>
<app-node-statistics-chart [publicKey]="node.public_key" *ngIf="!error"></app-node-statistics-chart> <app-node-statistics-chart [publicKey]="node.public_key" *ngIf="!error"></app-node-statistics-chart>
<br>
<div class="d-flex justify-content-between" *ngIf="!error"> <div class="d-flex justify-content-between" *ngIf="!error">
<h2><span i18n="lightning.all-channels">All channels</span> ({{ channelsListStatus === 'open' ? node.opened_channel_count : node.closed_channel_count }})</h2> <h2>Channels ({{ channelsListStatus === 'open' ? node.opened_channel_count : node.closed_channel_count }})</h2>
<div class="d-flex justify-content-end">
<app-toggle [textLeft]="'List'" [textRight]="'Map'" (toggleStatusChanged)="channelsListModeChange($event)"></app-toggle>
</div>
</div> </div>
<app-nodes-channels-map *ngIf="channelsListMode === 'map' && !error" [style]="'nodepage'" [publicKey]="node.public_key"> <app-channels-list *ngIf="!error" [publicKey]="node.public_key"
</app-nodes-channels-map>
<app-channels-list *ngIf="channelsListMode === 'list' && !error" [publicKey]="node.public_key"
(channelsStatusChangedEvent)="onChannelsListStatusChanged($event)"></app-channels-list> (channelsStatusChangedEvent)="onChannelsListStatusChanged($event)"></app-channels-list>
</div> </div>

View file

@ -19,7 +19,6 @@ export class NodeComponent implements OnInit {
publicKey$: Observable<string>; publicKey$: Observable<string>;
selectedSocketIndex = 0; selectedSocketIndex = 0;
qrCodeVisible = false; qrCodeVisible = false;
channelsListMode = 'list';
channelsListStatus: string; channelsListStatus: string;
error: Error; error: Error;
publicKey: string; publicKey: string;
@ -83,14 +82,6 @@ export class NodeComponent implements OnInit {
this.selectedSocketIndex = index; this.selectedSocketIndex = index;
} }
channelsListModeChange(toggle) {
if (toggle === true) {
this.channelsListMode = 'map';
} else {
this.channelsListMode = 'list';
}
}
onChannelsListStatusChanged(e) { onChannelsListStatusChanged(e) {
this.channelsListStatus = e; this.channelsListStatus = e;
} }

View file

@ -3,9 +3,6 @@
<div *ngIf="style === 'graph'" class="card-header"> <div *ngIf="style === 'graph'" class="card-header">
<div class="d-flex d-md-block align-items-baseline" style="margin-bottom: -5px"> <div class="d-flex d-md-block align-items-baseline" style="margin-bottom: -5px">
<span i18n="lightning.nodes-channels-world-map">Lightning nodes channels world map</span> <span i18n="lightning.nodes-channels-world-map">Lightning nodes channels world map</span>
<button class="btn p-0 pl-2" style="margin: 0 0 4px 0px">
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true" (click)="onSaveChart()"></fa-icon>
</button>
</div> </div>
<small style="color: #ffffff66" i18n="lightning.tor-nodes-excluded">(Tor nodes excluded)</small> <small style="color: #ffffff66" i18n="lightning.tor-nodes-excluded">(Tor nodes excluded)</small>
</div> </div>

View file

@ -20,7 +20,8 @@
} }
.full-container.nodepage { .full-container.nodepage {
margin-top: 50px; margin-top: 25px;
margin-bottom: 25px;
} }
.full-container.widget { .full-container.widget {

View file

@ -3,7 +3,6 @@ import { SeoService } from 'src/app/services/seo.service';
import { ApiService } from 'src/app/services/api.service'; import { ApiService } from 'src/app/services/api.service';
import { Observable, switchMap, tap, zip } from 'rxjs'; import { Observable, switchMap, tap, zip } from 'rxjs';
import { AssetsService } from 'src/app/services/assets.service'; import { AssetsService } from 'src/app/services/assets.service';
import { download } from 'src/app/shared/graphs.utils';
import { ActivatedRoute, ParamMap, Router } from '@angular/router'; import { ActivatedRoute, ParamMap, Router } from '@angular/router';
import { RelativeUrlPipe } from 'src/app/shared/pipes/relative-url/relative-url.pipe'; import { RelativeUrlPipe } from 'src/app/shared/pipes/relative-url/relative-url.pipe';
import { StateService } from 'src/app/services/state.service'; import { StateService } from 'src/app/services/state.service';
@ -21,6 +20,7 @@ export class NodesChannelsMap implements OnInit, OnDestroy {
@Input() publicKey: string | undefined; @Input() publicKey: string | undefined;
observable$: Observable<any>; observable$: Observable<any>;
center: number[] | undefined = undefined;
chartInstance = undefined; chartInstance = undefined;
chartOptions: EChartsOption = {}; chartOptions: EChartsOption = {};
@ -42,6 +42,8 @@ export class NodesChannelsMap implements OnInit, OnDestroy {
ngOnDestroy(): void {} ngOnDestroy(): void {}
ngOnInit(): void { ngOnInit(): void {
this.center = this.style === 'widget' ? [0, 0, -10] : undefined;
if (this.style === 'graph') { if (this.style === 'graph') {
this.seoService.setTitle($localize`Lightning nodes channels world map`); this.seoService.setTitle($localize`Lightning nodes channels world map`);
} }
@ -52,13 +54,21 @@ export class NodesChannelsMap implements OnInit, OnDestroy {
return zip( return zip(
this.assetsService.getWorldMapJson$, this.assetsService.getWorldMapJson$,
this.apiService.getChannelsGeo$(params.get('public_key') ?? undefined), this.apiService.getChannelsGeo$(params.get('public_key') ?? undefined),
[params.get('public_key') ?? undefined]
).pipe(tap((data) => { ).pipe(tap((data) => {
registerMap('world', data[0]); registerMap('world', data[0]);
const channelsLoc = []; const channelsLoc = [];
const nodes = []; const nodes = [];
const nodesPubkeys = {}; const nodesPubkeys = {};
let thisNodeGPS: number[] | undefined = undefined;
for (const channel of data[1]) { for (const channel of data[1]) {
if (!thisNodeGPS && data[2] === channel[0]) {
thisNodeGPS = [channel[2], channel[3]];
} else if (!thisNodeGPS && data[2] === channel[4]) {
thisNodeGPS = [channel[6], channel[7]];
}
channelsLoc.push([[channel[2], channel[3]], [channel[6], channel[7]]]); channelsLoc.push([[channel[2], channel[3]], [channel[6], channel[7]]]);
if (!nodesPubkeys[channel[0]]) { if (!nodesPubkeys[channel[0]]) {
nodes.push({ nodes.push({
@ -77,6 +87,13 @@ export class NodesChannelsMap implements OnInit, OnDestroy {
nodesPubkeys[channel[4]] = true; nodesPubkeys[channel[4]] = true;
} }
} }
if (this.style === 'nodepage' && thisNodeGPS) {
// 1ML 0217890e3aad8d35bc054f43acc00084b25229ecff0ab68debd82883ad65ee8266
// New York GPS [-74.0068, 40.7123]
// Map center [-20.55, 0, -9.85]
this.center = [thisNodeGPS[0] * -20.55 / -74.0068, 0, thisNodeGPS[1] * -9.85 / 40.7123];
}
this.prepareChartOptions(nodes, channelsLoc); this.prepareChartOptions(nodes, channelsLoc);
})); }));
}) })
@ -111,10 +128,10 @@ export class NodesChannelsMap implements OnInit, OnDestroy {
} }
}, },
viewControl: { viewControl: {
center: this.style === 'widget' ? [0, 0, -10] : undefined, center: this.center,
minDistance: 1, minDistance: 1,
maxDistance: 60, maxDistance: 60,
distance: this.style === 'widget' ? 22 : 60, distance: this.style === 'widget' ? 22 : this.style === 'nodepage' ? 22 : 60,
alpha: 90, alpha: 90,
rotateSensitivity: 0, rotateSensitivity: 0,
panSensitivity: this.style === 'widget' ? 0 : 1, panSensitivity: this.style === 'widget' ? 0 : 1,
@ -204,22 +221,4 @@ export class NodesChannelsMap implements OnInit, OnDestroy {
} }
}); });
} }
onSaveChart() {
// @ts-ignore
const prevBottom = this.chartOptions.grid.bottom;
const now = new Date();
// @ts-ignore
this.chartOptions.grid.bottom = 30;
this.chartOptions.backgroundColor = '#11131f';
this.chartInstance.setOption(this.chartOptions);
download(this.chartInstance.getDataURL({
pixelRatio: 2,
excludeComponents: ['dataZoom'],
}), `lightning-nodes-heatmap-clearnet-${Math.round(now.getTime() / 1000)}.svg`);
// @ts-ignore
this.chartOptions.grid.bottom = prevBottom;
this.chartOptions.backgroundColor = 'none';
this.chartInstance.setOption(this.chartOptions);
}
} }