Fetch funding tx for clightning channels
This commit is contained in:
parent
00cd3ee9bf
commit
a25af16f7c
@ -245,7 +245,7 @@ export default class CLightningClient extends EventEmitter implements AbstractLi
|
|||||||
async $getNetworkGraph(): Promise<ILightningApi.NetworkGraph> {
|
async $getNetworkGraph(): Promise<ILightningApi.NetworkGraph> {
|
||||||
const listnodes: any[] = await this.call('listnodes');
|
const listnodes: any[] = await this.call('listnodes');
|
||||||
const listchannels: any[] = await this.call('listchannels');
|
const listchannels: any[] = await this.call('listchannels');
|
||||||
const channelsList = convertAndmergeBidirectionalChannels(listchannels['channels']);
|
const channelsList = await convertAndmergeBidirectionalChannels(listchannels['channels']);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
nodes: listnodes['nodes'].map(node => convertNode(node)),
|
nodes: listnodes['nodes'].map(node => convertNode(node)),
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { ILightningApi } from '../lightning-api.interface';
|
import { ILightningApi } from '../lightning-api.interface';
|
||||||
|
import FundingTxFetcher from '../../../tasks/lightning/sync-tasks/funding-tx-fetcher';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a clightning "listnode" entry to a lnd node entry
|
* Convert a clightning "listnode" entry to a lnd node entry
|
||||||
@ -22,7 +23,7 @@ export function convertNode(clNode: any): ILightningApi.Node {
|
|||||||
/**
|
/**
|
||||||
* Convert clightning "listchannels" response to lnd "describegraph.edges" format
|
* Convert clightning "listchannels" response to lnd "describegraph.edges" format
|
||||||
*/
|
*/
|
||||||
export function convertAndmergeBidirectionalChannels(clChannels: any[]): ILightningApi.Channel[] {
|
export async function convertAndmergeBidirectionalChannels(clChannels: any[]): Promise<ILightningApi.Channel[]> {
|
||||||
const consolidatedChannelList: ILightningApi.Channel[] = [];
|
const consolidatedChannelList: ILightningApi.Channel[] = [];
|
||||||
const clChannelsDict = {};
|
const clChannelsDict = {};
|
||||||
const clChannelsDictCount = {};
|
const clChannelsDictCount = {};
|
||||||
@ -33,14 +34,14 @@ export function convertNode(clNode: any): ILightningApi.Node {
|
|||||||
clChannelsDictCount[clChannel.short_channel_id] = 1;
|
clChannelsDictCount[clChannel.short_channel_id] = 1;
|
||||||
} else {
|
} else {
|
||||||
consolidatedChannelList.push(
|
consolidatedChannelList.push(
|
||||||
buildFullChannel(clChannel, clChannelsDict[clChannel.short_channel_id])
|
await buildFullChannel(clChannel, clChannelsDict[clChannel.short_channel_id])
|
||||||
);
|
);
|
||||||
delete clChannelsDict[clChannel.short_channel_id];
|
delete clChannelsDict[clChannel.short_channel_id];
|
||||||
clChannelsDictCount[clChannel.short_channel_id]++;
|
clChannelsDictCount[clChannel.short_channel_id]++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const short_channel_id of Object.keys(clChannelsDict)) {
|
for (const short_channel_id of Object.keys(clChannelsDict)) {
|
||||||
consolidatedChannelList.push(buildIncompleteChannel(clChannelsDict[short_channel_id]));
|
consolidatedChannelList.push(await buildIncompleteChannel(clChannelsDict[short_channel_id]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return consolidatedChannelList;
|
return consolidatedChannelList;
|
||||||
@ -55,16 +56,20 @@ export function convertChannelId(channelId): string {
|
|||||||
* Convert two clightning "getchannels" entries into a full a lnd "describegraph.edges" format
|
* Convert two clightning "getchannels" entries into a full a lnd "describegraph.edges" format
|
||||||
* In this case, clightning knows the channel policy for both nodes
|
* In this case, clightning knows the channel policy for both nodes
|
||||||
*/
|
*/
|
||||||
function buildFullChannel(clChannelA: any, clChannelB: any): ILightningApi.Channel {
|
async function buildFullChannel(clChannelA: any, clChannelB: any): Promise<ILightningApi.Channel> {
|
||||||
const lastUpdate = Math.max(clChannelA.last_update ?? 0, clChannelB.last_update ?? 0);
|
const lastUpdate = Math.max(clChannelA.last_update ?? 0, clChannelB.last_update ?? 0);
|
||||||
|
|
||||||
|
const tx = await FundingTxFetcher.$fetchChannelOpenTx(clChannelA.short_channel_id);
|
||||||
|
const parts = clChannelA.short_channel_id.split('x');
|
||||||
|
const outputIdx = parts[2];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
channel_id: clChannelA.short_channel_id,
|
channel_id: clChannelA.short_channel_id,
|
||||||
capacity: clChannelA.satoshis,
|
capacity: clChannelA.satoshis,
|
||||||
last_update: lastUpdate,
|
last_update: lastUpdate,
|
||||||
node1_policy: convertPolicy(clChannelA),
|
node1_policy: convertPolicy(clChannelA),
|
||||||
node2_policy: convertPolicy(clChannelB),
|
node2_policy: convertPolicy(clChannelB),
|
||||||
chan_point: ':0', // TODO
|
chan_point: `${tx.txid}:${outputIdx}`,
|
||||||
node1_pub: clChannelA.source,
|
node1_pub: clChannelA.source,
|
||||||
node2_pub: clChannelB.source,
|
node2_pub: clChannelB.source,
|
||||||
};
|
};
|
||||||
@ -74,14 +79,18 @@ function buildFullChannel(clChannelA: any, clChannelB: any): ILightningApi.Chann
|
|||||||
* Convert one clightning "getchannels" entry into a full a lnd "describegraph.edges" format
|
* Convert one clightning "getchannels" entry into a full a lnd "describegraph.edges" format
|
||||||
* In this case, clightning knows the channel policy of only one node
|
* In this case, clightning knows the channel policy of only one node
|
||||||
*/
|
*/
|
||||||
function buildIncompleteChannel(clChannel: any): ILightningApi.Channel {
|
async function buildIncompleteChannel(clChannel: any): Promise<ILightningApi.Channel> {
|
||||||
|
const tx = await FundingTxFetcher.$fetchChannelOpenTx(clChannel.short_channel_id);
|
||||||
|
const parts = clChannel.short_channel_id.split('x');
|
||||||
|
const outputIdx = parts[2];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
channel_id: clChannel.short_channel_id,
|
channel_id: clChannel.short_channel_id,
|
||||||
capacity: clChannel.satoshis,
|
capacity: clChannel.satoshis,
|
||||||
last_update: clChannel.last_update ?? 0,
|
last_update: clChannel.last_update ?? 0,
|
||||||
node1_policy: convertPolicy(clChannel),
|
node1_policy: convertPolicy(clChannel),
|
||||||
node2_policy: null,
|
node2_policy: null,
|
||||||
chan_point: ':0', // TODO
|
chan_point: `${tx.txid}:${outputIdx}`,
|
||||||
node1_pub: clChannel.source,
|
node1_pub: clChannel.source,
|
||||||
node2_pub: clChannel.destination,
|
node2_pub: clChannel.destination,
|
||||||
};
|
};
|
||||||
|
@ -34,6 +34,7 @@ import miningRoutes from './api/mining/mining-routes';
|
|||||||
import bisqRoutes from './api/bisq/bisq.routes';
|
import bisqRoutes from './api/bisq/bisq.routes';
|
||||||
import liquidRoutes from './api/liquid/liquid.routes';
|
import liquidRoutes from './api/liquid/liquid.routes';
|
||||||
import bitcoinRoutes from './api/bitcoin/bitcoin.routes';
|
import bitcoinRoutes from './api/bitcoin/bitcoin.routes';
|
||||||
|
import fundingTxFetcher from "./tasks/lightning/sync-tasks/funding-tx-fetcher";
|
||||||
|
|
||||||
class Server {
|
class Server {
|
||||||
private wss: WebSocket.Server | undefined;
|
private wss: WebSocket.Server | undefined;
|
||||||
@ -136,7 +137,8 @@ class Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (config.LIGHTNING.ENABLED) {
|
if (config.LIGHTNING.ENABLED) {
|
||||||
networkSyncService.$startService()
|
fundingTxFetcher.$init()
|
||||||
|
.then(() => networkSyncService.$startService())
|
||||||
.then(() => lightningStatsUpdater.$startService());
|
.then(() => lightningStatsUpdater.$startService());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
import { existsSync, promises } from 'fs';
|
import { existsSync, promises } from 'fs';
|
||||||
import bitcoinApiFactory from '../../../api/bitcoin/bitcoin-api-factory';
|
|
||||||
import bitcoinClient from '../../../api/bitcoin/bitcoin-client';
|
import bitcoinClient from '../../../api/bitcoin/bitcoin-client';
|
||||||
import config from '../../../config';
|
import config from '../../../config';
|
||||||
import DB from '../../../database';
|
|
||||||
import logger from '../../../logger';
|
import logger from '../../../logger';
|
||||||
|
|
||||||
const fsPromises = promises;
|
const fsPromises = promises;
|
||||||
@ -16,12 +14,7 @@ class FundingTxFetcher {
|
|||||||
private channelNewlyProcessed = 0;
|
private channelNewlyProcessed = 0;
|
||||||
public fundingTxCache = {};
|
public fundingTxCache = {};
|
||||||
|
|
||||||
async $fetchChannelsFundingTxs(channelIds: string[]): Promise<void> {
|
async $init(): Promise<void> {
|
||||||
if (this.running) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.running = true;
|
|
||||||
|
|
||||||
// Load funding tx disk cache
|
// Load funding tx disk cache
|
||||||
if (Object.keys(this.fundingTxCache).length === 0 && existsSync(CACHE_FILE_NAME)) {
|
if (Object.keys(this.fundingTxCache).length === 0 && existsSync(CACHE_FILE_NAME)) {
|
||||||
try {
|
try {
|
||||||
@ -32,6 +25,13 @@ class FundingTxFetcher {
|
|||||||
}
|
}
|
||||||
logger.debug(`Imported ${Object.keys(this.fundingTxCache).length} funding tx amount from the disk cache`);
|
logger.debug(`Imported ${Object.keys(this.fundingTxCache).length} funding tx amount from the disk cache`);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async $fetchChannelsFundingTxs(channelIds: string[]): Promise<void> {
|
||||||
|
if (this.running) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.running = true;
|
||||||
|
|
||||||
const globalTimer = new Date().getTime() / 1000;
|
const globalTimer = new Date().getTime() / 1000;
|
||||||
let cacheTimer = new Date().getTime() / 1000;
|
let cacheTimer = new Date().getTime() / 1000;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user