mirror of
https://github.com/mempool/mempool.git
synced 2025-03-03 09:39:17 +01:00
[lightning] start integrating features bits in the node page
This commit is contained in:
parent
4d41d36fe7
commit
556eb65320
5 changed files with 67 additions and 11 deletions
|
@ -3,6 +3,7 @@ import DB from '../../database';
|
||||||
import { ResultSetHeader } from 'mysql2';
|
import { ResultSetHeader } from 'mysql2';
|
||||||
import { ILightningApi } from '../lightning/lightning-api.interface';
|
import { ILightningApi } from '../lightning/lightning-api.interface';
|
||||||
import { ITopNodesPerCapacity, ITopNodesPerChannels } from '../../mempool.interfaces';
|
import { ITopNodesPerCapacity, ITopNodesPerChannels } from '../../mempool.interfaces';
|
||||||
|
import { bin2hex } from '../../utils/format';
|
||||||
|
|
||||||
class NodesApi {
|
class NodesApi {
|
||||||
public async $getWorldNodes(): Promise<any> {
|
public async $getWorldNodes(): Promise<any> {
|
||||||
|
@ -76,8 +77,18 @@ class NodesApi {
|
||||||
node.subdivision = JSON.parse(node.subdivision);
|
node.subdivision = JSON.parse(node.subdivision);
|
||||||
node.city = JSON.parse(node.city);
|
node.city = JSON.parse(node.city);
|
||||||
node.country = JSON.parse(node.country);
|
node.country = JSON.parse(node.country);
|
||||||
|
|
||||||
|
// Features
|
||||||
node.features = JSON.parse(node.features);
|
node.features = JSON.parse(node.features);
|
||||||
|
let maxBit = 0;
|
||||||
|
for (const feature of node.features) {
|
||||||
|
maxBit = Math.max(maxBit, feature.bit);
|
||||||
|
}
|
||||||
|
node.featuresBits = new Array(maxBit + 1).fill(0);
|
||||||
|
for (const feature of node.features) {
|
||||||
|
node.featuresBits[feature.bit] = 1;
|
||||||
|
}
|
||||||
|
node.featuresBits = bin2hex(node.featuresBits.reverse().join(''));
|
||||||
|
|
||||||
// Active channels and capacity
|
// Active channels and capacity
|
||||||
const activeChannelsStats: any = await this.$getActiveChannelsStats(public_key);
|
const activeChannelsStats: any = await this.$getActiveChannelsStats(public_key);
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { hex2bin } from '../../../utils/format';
|
||||||
import config from '../../../config';
|
import config from '../../../config';
|
||||||
|
|
||||||
// https://github.com/lightningnetwork/lnd/blob/master/lnwire/features.go
|
// https://github.com/lightningnetwork/lnd/blob/master/lnwire/features.go
|
||||||
enum FeatureBits {
|
export enum FeatureBits {
|
||||||
DataLossProtectRequired = 0,
|
DataLossProtectRequired = 0,
|
||||||
DataLossProtectOptional = 1,
|
DataLossProtectOptional = 1,
|
||||||
InitialRoutingSync = 3,
|
InitialRoutingSync = 3,
|
||||||
|
@ -47,10 +47,7 @@ enum FeatureBits {
|
||||||
MaxBolt11Feature = 5114,
|
MaxBolt11Feature = 5114,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Features is a mapping of known feature bits to a descriptive name. All known
|
export const FeaturesMap = new Map<FeatureBits, string>([
|
||||||
// feature bits must be assigned a name in this mapping, and feature bit pairs
|
|
||||||
// must be assigned together for correct behavior.
|
|
||||||
const FeaturesMap = new Map<FeatureBits, string>([
|
|
||||||
[FeatureBits.DataLossProtectRequired, 'data-loss-protect'],
|
[FeatureBits.DataLossProtectRequired, 'data-loss-protect'],
|
||||||
[FeatureBits.DataLossProtectOptional, 'data-loss-protect'],
|
[FeatureBits.DataLossProtectOptional, 'data-loss-protect'],
|
||||||
[FeatureBits.InitialRoutingSync, 'initial-routing-sync'],
|
[FeatureBits.InitialRoutingSync, 'initial-routing-sync'],
|
||||||
|
|
|
@ -46,10 +46,10 @@ class LndApi implements AbstractLightningApi {
|
||||||
|
|
||||||
for (const node of graph.nodes) {
|
for (const node of graph.nodes) {
|
||||||
const nodeFeatures: ILightningApi.Feature[] = [];
|
const nodeFeatures: ILightningApi.Feature[] = [];
|
||||||
for (const bit in node.features) {
|
for (const bit in node.features) {
|
||||||
nodeFeatures.push({
|
nodeFeatures.push({
|
||||||
bit: parseInt(bit, 10),
|
bit: parseInt(bit, 10),
|
||||||
name: node.features[bit].name,
|
name: node.features[bit].name,
|
||||||
is_required: node.features[bit].is_required,
|
is_required: node.features[bit].is_required,
|
||||||
is_known: node.features[bit].is_known,
|
is_known: node.features[bit].is_known,
|
||||||
});
|
});
|
||||||
|
|
|
@ -29,7 +29,7 @@ export function formatBytes(bytes: number, toUnit: string, skipUnit = false): st
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://stackoverflow.com/a/64235212
|
// https://stackoverflow.com/a/64235212
|
||||||
export function hex2bin(hex): string {
|
export function hex2bin(hex: string): string {
|
||||||
if (!hex) {
|
if (!hex) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
@ -58,5 +58,38 @@ export function hex2bin(hex): string {
|
||||||
default: return '';
|
default: return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function bin2hex(bin: string): string {
|
||||||
|
if (!bin) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
let out = '';
|
||||||
|
|
||||||
|
for (let i = 0; i < bin.length; i += 4) {
|
||||||
|
const c = bin.substring(i, i + 4);
|
||||||
|
switch (c) {
|
||||||
|
case '0000': out += '0'; break;
|
||||||
|
case '0001': out += '1'; break;
|
||||||
|
case '0010': out += '2'; break;
|
||||||
|
case '0011': out += '3'; break;
|
||||||
|
case '0100': out += '4'; break;
|
||||||
|
case '0101': out += '5'; break;
|
||||||
|
case '0110': out += '6'; break;
|
||||||
|
case '0111': out += '7'; break;
|
||||||
|
case '1000': out += '8'; break;
|
||||||
|
case '1001': out += '9'; break;
|
||||||
|
case '1010': out += 'a'; break;
|
||||||
|
case '1011': out += 'b'; break;
|
||||||
|
case '1100': out += 'c'; break;
|
||||||
|
case '1101': out += 'd'; break;
|
||||||
|
case '1110': out += 'e'; break;
|
||||||
|
case '1111': out += 'f'; break;
|
||||||
|
default: return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
|
@ -21,7 +21,6 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="box" *ngIf="!error">
|
<div class="box" *ngIf="!error">
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md">
|
<div class="col-md">
|
||||||
<table class="table table-borderless table-striped table-fixed">
|
<table class="table table-borderless table-striped table-fixed">
|
||||||
|
@ -59,6 +58,9 @@
|
||||||
<td i18n="lightning.avg-distance" class="text-truncate">Avg channel distance</td>
|
<td i18n="lightning.avg-distance" class="text-truncate">Avg channel distance</td>
|
||||||
<td class="direction-ltr">{{ avgDistance | amountShortener: 1 }} <span class="symbol">km</span> <span class="separator">·</span>{{ kmToMiles(avgDistance) | amountShortener: 1 }} <span class="symbol">mi</span></td>
|
<td class="direction-ltr">{{ avgDistance | amountShortener: 1 }} <span class="symbol">km</span> <span class="separator">·</span>{{ kmToMiles(avgDistance) | amountShortener: 1 }} <span class="symbol">mi</span></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr *ngIf="!node.geolocation" class="d-none d-md-table-row">
|
||||||
|
<ng-container *ngTemplateOutlet="featurebits;context:{bits: node.featuresBits}"></ng-container>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
@ -100,13 +102,26 @@
|
||||||
</td>
|
</td>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr *ngIf="node.geolocation">
|
||||||
|
<ng-container *ngTemplateOutlet="featurebits;context:{bits: node.featuresBits}"></ng-container>
|
||||||
|
</tr>
|
||||||
|
<tr *ngIf="!node.geolocation" class="d-table-row d-md-none ">
|
||||||
|
<ng-container *ngTemplateOutlet="featurebits;context:{bits: node.featuresBits}"></ng-container>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<ng-template #featurebits let-bits="bits">
|
||||||
|
<td i18n="lightning.features" class="text-truncate label">Features</td>
|
||||||
|
<td class="d-flex justify-content-between">
|
||||||
|
<span class="text-truncate w-90">{{ bits }}</span>
|
||||||
|
<a href="#" class="w-10">⊕</a>
|
||||||
|
</td>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
<div class="input-group mt-3" *ngIf="!error && node.socketsObject.length">
|
<div class="input-group mt-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">
|
||||||
|
|
Loading…
Add table
Reference in a new issue