| 
									
										
										
										
											2022-07-29 17:41:09 +02:00
										 |  |  | import { ILightningApi } from '../lightning-api.interface'; | 
					
						
							| 
									
										
										
										
											2022-08-02 16:39:34 +02:00
										 |  |  | import FundingTxFetcher from '../../../tasks/lightning/sync-tasks/funding-tx-fetcher'; | 
					
						
							| 
									
										
										
										
											2022-08-03 12:13:55 +02:00
										 |  |  | import logger from '../../../logger'; | 
					
						
							| 
									
										
										
										
											2022-08-10 16:58:29 +02:00
										 |  |  | import { Common } from '../../common'; | 
					
						
							| 
									
										
										
										
											2023-07-05 11:06:51 +02:00
										 |  |  | import { hex2bin } from '../../../utils/format'; | 
					
						
							| 
									
										
										
										
											2022-12-01 15:52:06 +01:00
										 |  |  | import config from '../../../config'; | 
					
						
							| 
									
										
										
										
											2022-07-29 16:33:07 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-05 11:06:51 +02:00
										 |  |  | // https://github.com/lightningnetwork/lnd/blob/master/lnwire/features.go
 | 
					
						
							| 
									
										
										
										
											2023-07-05 14:00:30 +02:00
										 |  |  | export enum FeatureBits { | 
					
						
							| 
									
										
										
										
											2023-07-05 11:06:51 +02:00
										 |  |  | 	DataLossProtectRequired = 0, | 
					
						
							|  |  |  | 	DataLossProtectOptional = 1, | 
					
						
							|  |  |  | 	InitialRoutingSync = 3, | 
					
						
							|  |  |  | 	UpfrontShutdownScriptRequired = 4, | 
					
						
							|  |  |  | 	UpfrontShutdownScriptOptional = 5, | 
					
						
							|  |  |  | 	GossipQueriesRequired = 6, | 
					
						
							|  |  |  | 	GossipQueriesOptional = 7, | 
					
						
							|  |  |  | 	TLVOnionPayloadRequired = 8, | 
					
						
							|  |  |  | 	TLVOnionPayloadOptional = 9, | 
					
						
							|  |  |  | 	StaticRemoteKeyRequired = 12, | 
					
						
							|  |  |  | 	StaticRemoteKeyOptional = 13, | 
					
						
							|  |  |  | 	PaymentAddrRequired = 14, | 
					
						
							|  |  |  | 	PaymentAddrOptional = 15, | 
					
						
							|  |  |  | 	MPPRequired = 16, | 
					
						
							|  |  |  | 	MPPOptional = 17, | 
					
						
							|  |  |  | 	WumboChannelsRequired = 18, | 
					
						
							|  |  |  | 	WumboChannelsOptional = 19, | 
					
						
							|  |  |  | 	AnchorsRequired = 20, | 
					
						
							|  |  |  | 	AnchorsOptional = 21, | 
					
						
							|  |  |  | 	AnchorsZeroFeeHtlcTxRequired = 22, | 
					
						
							|  |  |  | 	AnchorsZeroFeeHtlcTxOptional = 23, | 
					
						
							|  |  |  | 	ShutdownAnySegwitRequired = 26, | 
					
						
							|  |  |  | 	ShutdownAnySegwitOptional = 27, | 
					
						
							|  |  |  | 	AMPRequired = 30, | 
					
						
							|  |  |  | 	AMPOptional = 31, | 
					
						
							|  |  |  | 	ExplicitChannelTypeRequired = 44, | 
					
						
							|  |  |  | 	ExplicitChannelTypeOptional = 45, | 
					
						
							|  |  |  | 	ScidAliasRequired = 46, | 
					
						
							|  |  |  | 	ScidAliasOptional = 47, | 
					
						
							|  |  |  | 	PaymentMetadataRequired = 48, | 
					
						
							|  |  |  | 	PaymentMetadataOptional = 49, | 
					
						
							|  |  |  | 	ZeroConfRequired = 50, | 
					
						
							|  |  |  | 	ZeroConfOptional = 51, | 
					
						
							|  |  |  | 	KeysendRequired = 54, | 
					
						
							|  |  |  | 	KeysendOptional = 55, | 
					
						
							|  |  |  | 	ScriptEnforcedLeaseRequired = 2022, | 
					
						
							|  |  |  | 	ScriptEnforcedLeaseOptional = 2023, | 
					
						
							|  |  |  | 	MaxBolt11Feature = 5114, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  |    | 
					
						
							| 
									
										
										
										
											2023-07-05 14:00:30 +02:00
										 |  |  | export const FeaturesMap = new Map<FeatureBits, string>([ | 
					
						
							| 
									
										
										
										
											2023-07-05 11:06:51 +02:00
										 |  |  | 	[FeatureBits.DataLossProtectRequired, 'data-loss-protect'], | 
					
						
							|  |  |  | 	[FeatureBits.DataLossProtectOptional, 'data-loss-protect'], | 
					
						
							|  |  |  | 	[FeatureBits.InitialRoutingSync, 'initial-routing-sync'], | 
					
						
							|  |  |  | 	[FeatureBits.UpfrontShutdownScriptRequired, 'upfront-shutdown-script'], | 
					
						
							|  |  |  | 	[FeatureBits.UpfrontShutdownScriptOptional, 'upfront-shutdown-script'], | 
					
						
							|  |  |  | 	[FeatureBits.GossipQueriesRequired, 'gossip-queries'], | 
					
						
							|  |  |  | 	[FeatureBits.GossipQueriesOptional, 'gossip-queries'], | 
					
						
							|  |  |  | 	[FeatureBits.TLVOnionPayloadRequired, 'tlv-onion'], | 
					
						
							|  |  |  | 	[FeatureBits.TLVOnionPayloadOptional, 'tlv-onion'], | 
					
						
							|  |  |  | 	[FeatureBits.StaticRemoteKeyOptional, 'static-remote-key'], | 
					
						
							|  |  |  | 	[FeatureBits.StaticRemoteKeyRequired, 'static-remote-key'], | 
					
						
							|  |  |  | 	[FeatureBits.PaymentAddrOptional, 'payment-addr'], | 
					
						
							|  |  |  | 	[FeatureBits.PaymentAddrRequired, 'payment-addr'], | 
					
						
							|  |  |  | 	[FeatureBits.MPPOptional, 'multi-path-payments'], | 
					
						
							|  |  |  | 	[FeatureBits.MPPRequired, 'multi-path-payments'], | 
					
						
							|  |  |  | 	[FeatureBits.AnchorsRequired, 'anchor-commitments'], | 
					
						
							|  |  |  | 	[FeatureBits.AnchorsOptional, 'anchor-commitments'], | 
					
						
							|  |  |  | 	[FeatureBits.AnchorsZeroFeeHtlcTxRequired, 'anchors-zero-fee-htlc-tx'], | 
					
						
							|  |  |  | 	[FeatureBits.AnchorsZeroFeeHtlcTxOptional, 'anchors-zero-fee-htlc-tx'], | 
					
						
							|  |  |  | 	[FeatureBits.WumboChannelsRequired, 'wumbo-channels'], | 
					
						
							|  |  |  | 	[FeatureBits.WumboChannelsOptional, 'wumbo-channels'], | 
					
						
							|  |  |  | 	[FeatureBits.AMPRequired, 'amp'], | 
					
						
							|  |  |  | 	[FeatureBits.AMPOptional, 'amp'], | 
					
						
							|  |  |  | 	[FeatureBits.PaymentMetadataOptional, 'payment-metadata'], | 
					
						
							|  |  |  | 	[FeatureBits.PaymentMetadataRequired, 'payment-metadata'], | 
					
						
							|  |  |  | 	[FeatureBits.ExplicitChannelTypeOptional, 'explicit-commitment-type'], | 
					
						
							|  |  |  | 	[FeatureBits.ExplicitChannelTypeRequired, 'explicit-commitment-type'], | 
					
						
							|  |  |  | 	[FeatureBits.KeysendOptional, 'keysend'], | 
					
						
							|  |  |  | 	[FeatureBits.KeysendRequired, 'keysend'], | 
					
						
							|  |  |  | 	[FeatureBits.ScriptEnforcedLeaseRequired, 'script-enforced-lease'], | 
					
						
							|  |  |  | 	[FeatureBits.ScriptEnforcedLeaseOptional, 'script-enforced-lease'], | 
					
						
							|  |  |  | 	[FeatureBits.ScidAliasRequired, 'scid-alias'], | 
					
						
							|  |  |  | 	[FeatureBits.ScidAliasOptional, 'scid-alias'], | 
					
						
							|  |  |  | 	[FeatureBits.ZeroConfRequired, 'zero-conf'], | 
					
						
							|  |  |  | 	[FeatureBits.ZeroConfOptional, 'zero-conf'], | 
					
						
							|  |  |  | 	[FeatureBits.ShutdownAnySegwitRequired, 'shutdown-any-segwit'], | 
					
						
							|  |  |  | 	[FeatureBits.ShutdownAnySegwitOptional, 'shutdown-any-segwit'], | 
					
						
							|  |  |  | ]); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-29 17:41:09 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Convert a clightning "listnode" entry to a lnd node entry | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2022-07-29 16:33:07 +02:00
										 |  |  | export function convertNode(clNode: any): ILightningApi.Node { | 
					
						
							| 
									
										
										
										
											2022-11-04 18:21:08 -06:00
										 |  |  |   let custom_records: { [type: number]: string } | undefined = undefined; | 
					
						
							|  |  |  |   if (clNode.option_will_fund) { | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |       custom_records = { '1': Buffer.from(clNode.option_will_fund.compact_lease || '', 'hex').toString('base64') }; | 
					
						
							|  |  |  |     } catch (e) { | 
					
						
							|  |  |  |       logger.err(`Cannot decode option_will_fund compact_lease for ${clNode.nodeid}). Reason: ` + (e instanceof Error ? e.message : e)); | 
					
						
							|  |  |  |       custom_records = undefined; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-07-05 11:06:51 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const nodeFeatures: ILightningApi.Feature[] = []; | 
					
						
							|  |  |  |   const nodeFeaturesBinary = hex2bin(clNode.features).split('').reverse().join(''); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (let i = 0; i < nodeFeaturesBinary.length; i++) { | 
					
						
							|  |  |  |     if (nodeFeaturesBinary[i] === '0') { | 
					
						
							|  |  |  |       continue; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     const feature = FeaturesMap.get(i); | 
					
						
							|  |  |  |     if (!feature) { | 
					
						
							|  |  |  |       nodeFeatures.push({ | 
					
						
							| 
									
										
										
										
											2023-07-05 11:17:04 +02:00
										 |  |  |         bit: i, | 
					
						
							| 
									
										
										
										
											2023-07-05 11:06:51 +02:00
										 |  |  |         name: 'unknown', | 
					
						
							|  |  |  |         is_required: i % 2 === 0, | 
					
						
							|  |  |  |         is_known: false | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       nodeFeatures.push({ | 
					
						
							| 
									
										
										
										
											2023-07-05 11:17:04 +02:00
										 |  |  |         bit: i, | 
					
						
							| 
									
										
										
										
											2023-07-05 11:06:51 +02:00
										 |  |  |         name: feature, | 
					
						
							|  |  |  |         is_required: i % 2 === 0, | 
					
						
							|  |  |  |         is_known: true | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-29 16:33:07 +02:00
										 |  |  |   return { | 
					
						
							|  |  |  |     alias: clNode.alias ?? '', | 
					
						
							|  |  |  |     color: `#${clNode.color ?? ''}`, | 
					
						
							| 
									
										
										
										
											2023-07-05 11:06:51 +02:00
										 |  |  |     features: nodeFeatures, | 
					
						
							| 
									
										
										
										
											2022-08-01 19:42:33 +02:00
										 |  |  |     pub_key: clNode.nodeid, | 
					
						
							|  |  |  |     addresses: clNode.addresses?.map((addr) => { | 
					
						
							| 
									
										
										
										
											2022-08-30 20:31:04 +02:00
										 |  |  |       let address = addr.address; | 
					
						
							|  |  |  |       if (addr.type === 'ipv6') { | 
					
						
							|  |  |  |         address = `[${address}]`; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2022-08-01 19:42:33 +02:00
										 |  |  |       return { | 
					
						
							|  |  |  |         network: addr.type, | 
					
						
							| 
									
										
										
										
											2022-08-30 20:31:04 +02:00
										 |  |  |         addr: `${address}:${addr.port}` | 
					
						
							| 
									
										
										
										
											2022-08-01 19:42:33 +02:00
										 |  |  |       }; | 
					
						
							| 
									
										
										
										
											2022-08-13 10:24:11 +02:00
										 |  |  |     }) ?? [], | 
					
						
							| 
									
										
										
										
											2022-08-01 19:42:33 +02:00
										 |  |  |     last_update: clNode?.last_timestamp ?? 0, | 
					
						
							| 
									
										
										
										
											2022-11-04 18:21:08 -06:00
										 |  |  |     custom_records | 
					
						
							| 
									
										
										
										
											2022-07-29 16:33:07 +02:00
										 |  |  |   }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-29 17:41:09 +02:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2022-08-01 19:42:33 +02:00
										 |  |  |  * Convert clightning "listchannels" response to lnd "describegraph.edges" format | 
					
						
							| 
									
										
										
										
											2022-07-29 17:41:09 +02:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2022-08-03 12:13:55 +02:00
										 |  |  | export async function convertAndmergeBidirectionalChannels(clChannels: any[]): Promise<ILightningApi.Channel[]> { | 
					
						
							| 
									
										
										
										
											2022-12-01 15:52:06 +01:00
										 |  |  |   logger.debug(`Converting clightning nodes and channels to lnd graph format`, logger.tags.ln); | 
					
						
							| 
									
										
										
										
											2022-08-03 12:13:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   let loggerTimer = new Date().getTime() / 1000; | 
					
						
							|  |  |  |   let channelProcessed = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-29 16:33:07 +02:00
										 |  |  |   const consolidatedChannelList: ILightningApi.Channel[] = []; | 
					
						
							|  |  |  |   const clChannelsDict = {}; | 
					
						
							|  |  |  |   const clChannelsDictCount = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-03 12:13:55 +02:00
										 |  |  |   for (const clChannel of clChannels) { | 
					
						
							| 
									
										
										
										
											2022-07-29 16:33:07 +02:00
										 |  |  |     if (!clChannelsDict[clChannel.short_channel_id]) { | 
					
						
							|  |  |  |       clChannelsDict[clChannel.short_channel_id] = clChannel; | 
					
						
							|  |  |  |       clChannelsDictCount[clChannel.short_channel_id] = 1; | 
					
						
							|  |  |  |     } else { | 
					
						
							| 
									
										
										
										
											2022-12-06 10:51:01 +01:00
										 |  |  |       const fullChannel = await buildFullChannel(clChannel, clChannelsDict[clChannel.short_channel_id]); | 
					
						
							|  |  |  |       if (fullChannel !== null) { | 
					
						
							|  |  |  |         consolidatedChannelList.push(fullChannel); | 
					
						
							|  |  |  |         delete clChannelsDict[clChannel.short_channel_id]; | 
					
						
							|  |  |  |         clChannelsDictCount[clChannel.short_channel_id]++; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2022-07-29 16:33:07 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-08-03 12:13:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const elapsedSeconds = Math.round((new Date().getTime() / 1000) - loggerTimer); | 
					
						
							| 
									
										
										
										
											2022-12-01 15:52:06 +01:00
										 |  |  |     if (elapsedSeconds > config.LIGHTNING.LOGGER_UPDATE_INTERVAL) { | 
					
						
							|  |  |  |       logger.info(`Building complete channels from clightning output. Channels processed: ${channelProcessed + 1} of ${clChannels.length}`, logger.tags.ln); | 
					
						
							| 
									
										
										
										
											2022-08-03 12:13:55 +02:00
										 |  |  |       loggerTimer = new Date().getTime() / 1000; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ++channelProcessed; | 
					
						
							| 
									
										
										
										
											2022-07-29 16:33:07 +02:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-08-03 12:13:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   channelProcessed = 0; | 
					
						
							|  |  |  |   const keys = Object.keys(clChannelsDict); | 
					
						
							|  |  |  |   for (const short_channel_id of keys) { | 
					
						
							| 
									
										
										
										
											2022-12-06 10:51:01 +01:00
										 |  |  |     const incompleteChannel = await buildIncompleteChannel(clChannelsDict[short_channel_id]); | 
					
						
							|  |  |  |     if (incompleteChannel !== null) { | 
					
						
							|  |  |  |       consolidatedChannelList.push(incompleteChannel); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-08-03 12:13:55 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     const elapsedSeconds = Math.round((new Date().getTime() / 1000) - loggerTimer); | 
					
						
							| 
									
										
										
										
											2022-12-01 15:52:06 +01:00
										 |  |  |     if (elapsedSeconds > config.LIGHTNING.LOGGER_UPDATE_INTERVAL) { | 
					
						
							| 
									
										
										
										
											2022-08-03 12:13:55 +02:00
										 |  |  |       logger.info(`Building partial channels from clightning output. Channels processed: ${channelProcessed + 1} of ${keys.length}`); | 
					
						
							|  |  |  |       loggerTimer = new Date().getTime() / 1000; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-30 19:10:11 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     channelProcessed++; | 
					
						
							| 
									
										
										
										
											2022-07-29 16:33:07 +02:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return consolidatedChannelList; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-29 17:41:09 +02:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2022-08-01 19:42:33 +02:00
										 |  |  |  * Convert two clightning "getchannels" entries into a full a lnd "describegraph.edges" format | 
					
						
							| 
									
										
										
										
											2022-07-29 17:41:09 +02:00
										 |  |  |  * In this case, clightning knows the channel policy for both nodes | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2022-12-06 10:51:01 +01:00
										 |  |  | async function buildFullChannel(clChannelA: any, clChannelB: any): Promise<ILightningApi.Channel | null> { | 
					
						
							| 
									
										
										
										
											2022-07-29 16:33:07 +02:00
										 |  |  |   const lastUpdate = Math.max(clChannelA.last_update ?? 0, clChannelB.last_update ?? 0); | 
					
						
							| 
									
										
										
										
											2022-08-02 16:39:34 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const tx = await FundingTxFetcher.$fetchChannelOpenTx(clChannelA.short_channel_id); | 
					
						
							| 
									
										
										
										
											2022-12-06 10:51:01 +01:00
										 |  |  |   if (!tx) { | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-08-02 16:39:34 +02:00
										 |  |  |   const parts = clChannelA.short_channel_id.split('x'); | 
					
						
							|  |  |  |   const outputIdx = parts[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-29 16:33:07 +02:00
										 |  |  |   return { | 
					
						
							| 
									
										
										
										
											2022-08-10 16:58:29 +02:00
										 |  |  |     channel_id: Common.channelShortIdToIntegerId(clChannelA.short_channel_id), | 
					
						
							| 
									
										
										
										
											2023-07-23 22:35:32 +09:00
										 |  |  |     capacity: (clChannelA.amount_msat / 1000).toString(), | 
					
						
							| 
									
										
										
										
											2022-08-01 19:42:33 +02:00
										 |  |  |     last_update: lastUpdate, | 
					
						
							|  |  |  |     node1_policy: convertPolicy(clChannelA), | 
					
						
							|  |  |  |     node2_policy: convertPolicy(clChannelB), | 
					
						
							| 
									
										
										
										
											2022-08-02 16:39:34 +02:00
										 |  |  |     chan_point: `${tx.txid}:${outputIdx}`, | 
					
						
							| 
									
										
										
										
											2022-08-01 19:42:33 +02:00
										 |  |  |     node1_pub: clChannelA.source, | 
					
						
							|  |  |  |     node2_pub: clChannelB.source, | 
					
						
							| 
									
										
										
										
											2022-07-29 16:33:07 +02:00
										 |  |  |   }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-29 17:41:09 +02:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2022-08-01 19:42:33 +02:00
										 |  |  |  * Convert one clightning "getchannels" entry into a full a lnd "describegraph.edges" format | 
					
						
							| 
									
										
										
										
											2022-07-29 17:41:09 +02:00
										 |  |  |  * In this case, clightning knows the channel policy of only one node | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2022-12-06 10:51:01 +01:00
										 |  |  | async function buildIncompleteChannel(clChannel: any): Promise<ILightningApi.Channel | null> { | 
					
						
							| 
									
										
										
										
											2022-08-02 16:39:34 +02:00
										 |  |  |   const tx = await FundingTxFetcher.$fetchChannelOpenTx(clChannel.short_channel_id); | 
					
						
							| 
									
										
										
										
											2022-12-06 10:51:01 +01:00
										 |  |  |   if (!tx) { | 
					
						
							|  |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2022-08-02 16:39:34 +02:00
										 |  |  |   const parts = clChannel.short_channel_id.split('x'); | 
					
						
							|  |  |  |   const outputIdx = parts[2]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-29 16:33:07 +02:00
										 |  |  |   return { | 
					
						
							| 
									
										
										
										
											2022-08-10 16:58:29 +02:00
										 |  |  |     channel_id: Common.channelShortIdToIntegerId(clChannel.short_channel_id), | 
					
						
							| 
									
										
										
										
											2023-07-23 22:35:32 +09:00
										 |  |  |     capacity: (clChannel.amount_msat / 1000).toString(), | 
					
						
							| 
									
										
										
										
											2022-08-01 19:42:33 +02:00
										 |  |  |     last_update: clChannel.last_update ?? 0, | 
					
						
							|  |  |  |     node1_policy: convertPolicy(clChannel), | 
					
						
							|  |  |  |     node2_policy: null, | 
					
						
							| 
									
										
										
										
											2022-08-02 16:39:34 +02:00
										 |  |  |     chan_point: `${tx.txid}:${outputIdx}`, | 
					
						
							| 
									
										
										
										
											2022-08-01 19:42:33 +02:00
										 |  |  |     node1_pub: clChannel.source, | 
					
						
							|  |  |  |     node2_pub: clChannel.destination, | 
					
						
							| 
									
										
										
										
											2022-07-29 16:33:07 +02:00
										 |  |  |   }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-07-29 17:41:09 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Convert a clightning "listnode" response to a lnd channel policy format | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2022-08-03 12:13:55 +02:00
										 |  |  | function convertPolicy(clChannel: any): ILightningApi.RoutingPolicy { | 
					
						
							| 
									
										
										
										
											2022-07-29 16:33:07 +02:00
										 |  |  |   return { | 
					
						
							| 
									
										
										
										
											2022-09-04 09:23:49 +02:00
										 |  |  |     time_lock_delta: clChannel.delay, | 
					
						
							| 
									
										
										
										
											2023-07-23 22:21:53 +09:00
										 |  |  |     min_htlc: clChannel.htlc_minimum_msat.toString(), | 
					
						
							|  |  |  |     max_htlc_msat: clChannel.htlc_maximum_msat.toString(), | 
					
						
							| 
									
										
										
										
											2022-08-01 19:42:33 +02:00
										 |  |  |     fee_base_msat: clChannel.base_fee_millisatoshi, | 
					
						
							|  |  |  |     fee_rate_milli_msat: clChannel.fee_per_millionth, | 
					
						
							|  |  |  |     disabled: !clChannel.active, | 
					
						
							|  |  |  |     last_update: clChannel.last_update ?? 0, | 
					
						
							| 
									
										
										
										
											2022-07-29 16:33:07 +02:00
										 |  |  |   }; | 
					
						
							|  |  |  | } |