Merge branch 'master' into run_tests_on_merge
This commit is contained in:
commit
1d5e4aa410
@ -237,14 +237,21 @@ export class Common {
|
|||||||
].join('x');
|
].join('x');
|
||||||
}
|
}
|
||||||
|
|
||||||
static utcDateToMysql(date?: number): string {
|
static utcDateToMysql(date?: number | null): string | null {
|
||||||
|
if (date === null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
const d = new Date((date || 0) * 1000);
|
const d = new Date((date || 0) * 1000);
|
||||||
return d.toISOString().split('T')[0] + ' ' + d.toTimeString().split(' ')[0];
|
return d.toISOString().split('T')[0] + ' ' + d.toTimeString().split(' ')[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static findSocketNetwork(addr: string): {network: string | null, url: string} {
|
static findSocketNetwork(addr: string): {network: string | null, url: string} {
|
||||||
let network: string | null = null;
|
let network: string | null = null;
|
||||||
let url = addr.split('://')[1];
|
let url: string = addr;
|
||||||
|
|
||||||
|
if (config.LIGHTNING.BACKEND === 'cln') {
|
||||||
|
url = addr.split('://')[1];
|
||||||
|
}
|
||||||
|
|
||||||
if (!url) {
|
if (!url) {
|
||||||
return {
|
return {
|
||||||
@ -261,7 +268,7 @@ export class Common {
|
|||||||
}
|
}
|
||||||
} else if (addr.indexOf('i2p') !== -1) {
|
} else if (addr.indexOf('i2p') !== -1) {
|
||||||
network = 'i2p';
|
network = 'i2p';
|
||||||
} else if (addr.indexOf('ipv4') !== -1) {
|
} else if (addr.indexOf('ipv4') !== -1 || (config.LIGHTNING.BACKEND === 'lnd' && isIP(url.split(':')[0]) === 4)) {
|
||||||
const ipv = isIP(url.split(':')[0]);
|
const ipv = isIP(url.split(':')[0]);
|
||||||
if (ipv === 4) {
|
if (ipv === 4) {
|
||||||
network = 'ipv4';
|
network = 'ipv4';
|
||||||
@ -271,7 +278,7 @@ export class Common {
|
|||||||
url: addr,
|
url: addr,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
} else if (addr.indexOf('ipv6') !== -1) {
|
} else if (addr.indexOf('ipv6') !== -1 || (config.LIGHTNING.BACKEND === 'lnd' && url.indexOf(']:'))) {
|
||||||
url = url.split('[')[1].split(']')[0];
|
url = url.split('[')[1].split(']')[0];
|
||||||
const ipv = isIP(url);
|
const ipv = isIP(url);
|
||||||
if (ipv === 6) {
|
if (ipv === 6) {
|
||||||
|
@ -7,7 +7,7 @@ import cpfpRepository from '../repositories/CpfpRepository';
|
|||||||
import { RowDataPacket } from 'mysql2';
|
import { RowDataPacket } from 'mysql2';
|
||||||
|
|
||||||
class DatabaseMigration {
|
class DatabaseMigration {
|
||||||
private static currentVersion = 56;
|
private static currentVersion = 57;
|
||||||
private queryTimeout = 3600_000;
|
private queryTimeout = 3600_000;
|
||||||
private statisticsAddedIndexed = false;
|
private statisticsAddedIndexed = false;
|
||||||
private uniqueLogs: string[] = [];
|
private uniqueLogs: string[] = [];
|
||||||
@ -500,6 +500,11 @@ class DatabaseMigration {
|
|||||||
this.uniqueLog(logger.notice, '`pools` table has been truncated`');
|
this.uniqueLog(logger.notice, '`pools` table has been truncated`');
|
||||||
await this.updateToSchemaVersion(56);
|
await this.updateToSchemaVersion(56);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (databaseSchemaVersion < 57) {
|
||||||
|
await this.$executeQuery(`ALTER TABLE nodes MODIFY updated_at datetime NULL`);
|
||||||
|
await this.updateToSchemaVersion(57);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -559,6 +559,17 @@ class ChannelsApi {
|
|||||||
const policy1: Partial<ILightningApi.RoutingPolicy> = channel.node1_policy || {};
|
const policy1: Partial<ILightningApi.RoutingPolicy> = channel.node1_policy || {};
|
||||||
const policy2: Partial<ILightningApi.RoutingPolicy> = channel.node2_policy || {};
|
const policy2: Partial<ILightningApi.RoutingPolicy> = channel.node2_policy || {};
|
||||||
|
|
||||||
|
// https://github.com/mempool/mempool/issues/3006
|
||||||
|
if ((channel.last_update ?? 0) < 1514736061) { // January 1st 2018
|
||||||
|
channel.last_update = null;
|
||||||
|
}
|
||||||
|
if ((policy1.last_update ?? 0) < 1514736061) { // January 1st 2018
|
||||||
|
policy1.last_update = null;
|
||||||
|
}
|
||||||
|
if ((policy2.last_update ?? 0) < 1514736061) { // January 1st 2018
|
||||||
|
policy2.last_update = null;
|
||||||
|
}
|
||||||
|
|
||||||
const query = `INSERT INTO channels
|
const query = `INSERT INTO channels
|
||||||
(
|
(
|
||||||
id,
|
id,
|
||||||
|
@ -630,6 +630,11 @@ class NodesApi {
|
|||||||
*/
|
*/
|
||||||
public async $saveNode(node: ILightningApi.Node): Promise<void> {
|
public async $saveNode(node: ILightningApi.Node): Promise<void> {
|
||||||
try {
|
try {
|
||||||
|
// https://github.com/mempool/mempool/issues/3006
|
||||||
|
if ((node.last_update ?? 0) < 1514736061) { // January 1st 2018
|
||||||
|
node.last_update = null;
|
||||||
|
}
|
||||||
|
|
||||||
const sockets = (node.addresses?.map(a => a.addr).join(',')) ?? '';
|
const sockets = (node.addresses?.map(a => a.addr).join(',')) ?? '';
|
||||||
const query = `INSERT INTO nodes(
|
const query = `INSERT INTO nodes(
|
||||||
public_key,
|
public_key,
|
||||||
|
@ -21,7 +21,7 @@ export namespace ILightningApi {
|
|||||||
export interface Channel {
|
export interface Channel {
|
||||||
channel_id: string;
|
channel_id: string;
|
||||||
chan_point: string;
|
chan_point: string;
|
||||||
last_update: number;
|
last_update: number | null;
|
||||||
node1_pub: string;
|
node1_pub: string;
|
||||||
node2_pub: string;
|
node2_pub: string;
|
||||||
capacity: string;
|
capacity: string;
|
||||||
@ -36,11 +36,11 @@ export namespace ILightningApi {
|
|||||||
fee_rate_milli_msat: string;
|
fee_rate_milli_msat: string;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
max_htlc_msat: string;
|
max_htlc_msat: string;
|
||||||
last_update: number;
|
last_update: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Node {
|
export interface Node {
|
||||||
last_update: number;
|
last_update: number | null;
|
||||||
pub_key: string;
|
pub_key: string;
|
||||||
alias: string;
|
alias: string;
|
||||||
addresses: {
|
addresses: {
|
||||||
|
@ -36,7 +36,6 @@ import bitcoinRoutes from './api/bitcoin/bitcoin.routes';
|
|||||||
import fundingTxFetcher from './tasks/lightning/sync-tasks/funding-tx-fetcher';
|
import fundingTxFetcher from './tasks/lightning/sync-tasks/funding-tx-fetcher';
|
||||||
import forensicsService from './tasks/lightning/forensics.service';
|
import forensicsService from './tasks/lightning/forensics.service';
|
||||||
import priceUpdater from './tasks/price-updater';
|
import priceUpdater from './tasks/price-updater';
|
||||||
import mining from './api/mining/mining';
|
|
||||||
import chainTips from './api/chain-tips';
|
import chainTips from './api/chain-tips';
|
||||||
import { AxiosError } from 'axios';
|
import { AxiosError } from 'axios';
|
||||||
|
|
||||||
|
@ -16,6 +16,9 @@ class BlocksRepository {
|
|||||||
* Save indexed block data in the database
|
* Save indexed block data in the database
|
||||||
*/
|
*/
|
||||||
public async $saveBlockInDatabase(block: BlockExtended) {
|
public async $saveBlockInDatabase(block: BlockExtended) {
|
||||||
|
const truncatedCoinbaseSignature = block?.extras?.coinbaseSignature?.substring(0, 500);
|
||||||
|
const truncatedCoinbaseSignatureAscii = block?.extras?.coinbaseSignatureAscii?.substring(0, 500);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const query = `INSERT INTO blocks(
|
const query = `INSERT INTO blocks(
|
||||||
height, hash, blockTimestamp, size,
|
height, hash, blockTimestamp, size,
|
||||||
@ -65,7 +68,7 @@ class BlocksRepository {
|
|||||||
block.extras.medianTimestamp,
|
block.extras.medianTimestamp,
|
||||||
block.extras.header,
|
block.extras.header,
|
||||||
block.extras.coinbaseAddress,
|
block.extras.coinbaseAddress,
|
||||||
block.extras.coinbaseSignature,
|
truncatedCoinbaseSignature,
|
||||||
block.extras.utxoSetSize,
|
block.extras.utxoSetSize,
|
||||||
block.extras.utxoSetChange,
|
block.extras.utxoSetChange,
|
||||||
block.extras.avgTxSize,
|
block.extras.avgTxSize,
|
||||||
@ -78,7 +81,7 @@ class BlocksRepository {
|
|||||||
block.extras.segwitTotalSize,
|
block.extras.segwitTotalSize,
|
||||||
block.extras.segwitTotalWeight,
|
block.extras.segwitTotalWeight,
|
||||||
block.extras.medianFeeAmt,
|
block.extras.medianFeeAmt,
|
||||||
block.extras.coinbaseSignatureAscii,
|
truncatedCoinbaseSignatureAscii,
|
||||||
];
|
];
|
||||||
|
|
||||||
await DB.query(query, params);
|
await DB.query(query, params);
|
||||||
|
@ -72,7 +72,7 @@ class NetworkSyncService {
|
|||||||
const graphNodesPubkeys: string[] = [];
|
const graphNodesPubkeys: string[] = [];
|
||||||
for (const node of nodes) {
|
for (const node of nodes) {
|
||||||
const latestUpdated = await channelsApi.$getLatestChannelUpdateForNode(node.pub_key);
|
const latestUpdated = await channelsApi.$getLatestChannelUpdateForNode(node.pub_key);
|
||||||
node.last_update = Math.max(node.last_update, latestUpdated);
|
node.last_update = Math.max(node.last_update ?? 0, latestUpdated);
|
||||||
|
|
||||||
await nodesApi.$saveNode(node);
|
await nodesApi.$saveNode(node);
|
||||||
graphNodesPubkeys.push(node.pub_key);
|
graphNodesPubkeys.push(node.pub_key);
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Component, OnInit, OnDestroy, Input, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
|
import { Component, OnInit, OnDestroy, Input, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
|
||||||
import { StateService } from '../../services/state.service';
|
import { StateService } from '../../services/state.service';
|
||||||
import { Observable, Subscription } from 'rxjs';
|
import { Observable, Subscription } from 'rxjs';
|
||||||
import { Price } from 'src/app/services/price.service';
|
import { Price } from '../../services/price.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-amount',
|
selector: 'app-amount',
|
||||||
|
@ -5,7 +5,7 @@ import BlockScene from './block-scene';
|
|||||||
import TxSprite from './tx-sprite';
|
import TxSprite from './tx-sprite';
|
||||||
import TxView from './tx-view';
|
import TxView from './tx-view';
|
||||||
import { Position } from './sprite-types';
|
import { Position } from './sprite-types';
|
||||||
import { Price } from 'src/app/services/price.service';
|
import { Price } from '../../services/price.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-block-overview-graph',
|
selector: 'app-block-overview-graph',
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Component, ElementRef, ViewChild, Input, OnChanges, ChangeDetectionStrategy } from '@angular/core';
|
import { Component, ElementRef, ViewChild, Input, OnChanges, ChangeDetectionStrategy } from '@angular/core';
|
||||||
import { TransactionStripped } from '../../interfaces/websocket.interface';
|
import { TransactionStripped } from '../../interfaces/websocket.interface';
|
||||||
import { Position } from '../../components/block-overview-graph/sprite-types.js';
|
import { Position } from '../../components/block-overview-graph/sprite-types.js';
|
||||||
import { Price } from 'src/app/services/price.service';
|
import { Price } from '../../services/price.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-block-overview-tooltip',
|
selector: 'app-block-overview-tooltip',
|
||||||
|
@ -13,7 +13,7 @@ import { BlockAudit, BlockExtended, TransactionStripped } from '../../interfaces
|
|||||||
import { ApiService } from '../../services/api.service';
|
import { ApiService } from '../../services/api.service';
|
||||||
import { BlockOverviewGraphComponent } from '../../components/block-overview-graph/block-overview-graph.component';
|
import { BlockOverviewGraphComponent } from '../../components/block-overview-graph/block-overview-graph.component';
|
||||||
import { detectWebGL } from '../../shared/graphs.utils';
|
import { detectWebGL } from '../../shared/graphs.utils';
|
||||||
import { PriceService, Price } from 'src/app/services/price.service';
|
import { PriceService, Price } from '../../services/price.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-block',
|
selector: 'app-block',
|
||||||
|
@ -22,7 +22,7 @@ import { SeoService } from '../../services/seo.service';
|
|||||||
import { BlockExtended, CpfpInfo } from '../../interfaces/node-api.interface';
|
import { BlockExtended, CpfpInfo } from '../../interfaces/node-api.interface';
|
||||||
import { LiquidUnblinding } from './liquid-ublinding';
|
import { LiquidUnblinding } from './liquid-ublinding';
|
||||||
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
|
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
|
||||||
import { Price, PriceService } from 'src/app/services/price.service';
|
import { Price, PriceService } from '../../services/price.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-transaction',
|
selector: 'app-transaction',
|
||||||
|
@ -9,7 +9,7 @@ import { AssetsService } from '../../services/assets.service';
|
|||||||
import { filter, map, tap, switchMap, shareReplay } from 'rxjs/operators';
|
import { filter, map, tap, switchMap, shareReplay } from 'rxjs/operators';
|
||||||
import { BlockExtended } from '../../interfaces/node-api.interface';
|
import { BlockExtended } from '../../interfaces/node-api.interface';
|
||||||
import { ApiService } from '../../services/api.service';
|
import { ApiService } from '../../services/api.service';
|
||||||
import { PriceService } from 'src/app/services/price.service';
|
import { PriceService } from '../../services/price.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-transactions-list',
|
selector: 'app-transactions-list',
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Component, ElementRef, ViewChild, Input, OnChanges, OnInit } from '@angular/core';
|
import { Component, ElementRef, ViewChild, Input, OnChanges, OnInit } from '@angular/core';
|
||||||
import { tap } from 'rxjs';
|
import { tap } from 'rxjs';
|
||||||
import { Price, PriceService } from 'src/app/services/price.service';
|
import { Price, PriceService } from '../../services/price.service';
|
||||||
|
|
||||||
interface Xput {
|
interface Xput {
|
||||||
type: 'input' | 'output' | 'fee';
|
type: 'input' | 'output' | 'fee';
|
||||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user