Skip to content
This repository was archived by the owner on Feb 9, 2026. It is now read-only.

Commit 9c7139e

Browse files
committed
feat: ios return list of node details from array of pubkeys
1 parent 0c4803c commit 9c7139e

6 files changed

Lines changed: 91 additions & 55 deletions

File tree

example/App.tsx

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -405,16 +405,15 @@ const App = (): ReactElement => {
405405
return setMessage(decode.error.message);
406406
}
407407

408-
const { recover_payee_pub_key, amount_satoshis } = decode.value;
408+
const { recover_payee_pub_key, amount_satoshis, description } =
409+
decode.value;
409410

410411
const ownAmountSats = 1000;
411412
Alert.alert(
412413
amount_satoshis
413414
? `Pay ${amount_satoshis ?? 0}`
414415
: 'Zero sat invoice found',
415-
amount_satoshis
416-
? `To pubkey: ${recover_payee_pub_key}`
417-
: `Send ${ownAmountSats} sats (Our chosen amount) to send over?`,
416+
description,
418417
[
419418
{
420419
text: 'Cancel',
@@ -444,24 +443,29 @@ const App = (): ReactElement => {
444443
<Button
445444
title={'Get network graph'}
446445
onPress={async (): Promise<void> => {
447-
const nodesRes = await ldk.completeGraphNodes();
446+
const nodesRes = await ldk.networkGraphListNodeIds();
448447
if (nodesRes.isErr()) {
449448
return setMessage(nodesRes.error.message);
450449
}
451450

452-
const channelRes = await ldk.completeGraphChannels();
453-
if (channelRes.isErr()) {
454-
return setMessage(channelRes.error.message);
451+
let msg = 'Nodes: \n\n';
452+
453+
for (let index = 0; index < nodesRes.value.length; index++) {
454+
const id = nodesRes.value[index];
455+
456+
const nodes = await ldk.networkGraphNodes([id]);
457+
if (nodes.isOk()) {
458+
msg += `${JSON.stringify(nodes.value)}`;
459+
}
455460
}
456461

457-
const nodes = `Nodes:\n\n${nodesRes.value.map(
458-
(node) => `\n${JSON.stringify(node)}`,
459-
)}`;
460-
const channels = `Channels:\n\n${channelRes.value.map(
461-
(channel) => `\n${JSON.stringify(channel)}`,
462-
)}`;
462+
// const nodes = `Nodes:\n\n${nodesRes.value.map(async (id) => {
463+
// const res = await ldk.networkGraphNodes([id]);
464+
// const node = res.isOk() ? res.value : [];
465+
// return `\n${JSON.stringify(id)}\n${JSON.stringify(node[0])}\n`;
466+
// })}`;
463467

464-
setMessage(`${nodes}\n${channels}`);
468+
setMessage(`${msg}`);
465469
}}
466470
/>
467471

lib/ios/Helpers.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,12 @@ extension ChannelInfo {
116116

117117
//Nodes in our network graph
118118
extension NodeInfo {
119-
var asJson: Any {
119+
var asJson: [String: Any] {
120120
return [
121121
"shortChannelIds": get_channels().map({ String($0) }),
122-
//TODO gathering other details results in EXC_BAD_ACCESS. Test with next version of LDK.
122+
"lowest_inbound_channel_fees_base_msat": get_lowest_inbound_channel_fees().get_base_msat(),
123+
"lowest_inbound_channel_fees_proportional_millionths": get_lowest_inbound_channel_fees().get_proportional_millionths(),
124+
"announcement_info_last_update": get_announcement_info().get_last_update()
123125
]
124126
}
125127
}

lib/ios/Ldk.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,14 @@ @interface RCT_EXTERN_MODULE(Ldk, NSObject)
8686
reject:(RCTPromiseRejectBlock)reject)
8787
RCT_EXTERN_METHOD(listChannelFiles:(RCTPromiseResolveBlock)resolve
8888
reject:(RCTPromiseRejectBlock)reject)
89-
RCT_EXTERN_METHOD(networkGraphListNodes:(RCTPromiseResolveBlock)resolve
89+
RCT_EXTERN_METHOD(networkGraphListNodeIds:(RCTPromiseResolveBlock)resolve
9090
reject:(RCTPromiseRejectBlock)reject)
9191
RCT_EXTERN_METHOD(networkGraphListChannels:(RCTPromiseResolveBlock)resolve
9292
reject:(RCTPromiseRejectBlock)reject)
9393
RCT_EXTERN_METHOD(networkGraphChannel:(NSString *)shortChannelId
9494
resolve:(RCTPromiseResolveBlock)resolve
9595
reject:(RCTPromiseRejectBlock)reject)
96-
RCT_EXTERN_METHOD(networkGraphNode:(NSString *)nodeId
96+
RCT_EXTERN_METHOD(networkGraphNodes:(NSArray *)nodeIds
9797
resolve:(RCTPromiseResolveBlock)resolve
9898
reject:(RCTPromiseRejectBlock)reject)
9999
RCT_EXTERN_METHOD(claimableBalances:(BOOL *)ignoreOpenChannels

lib/ios/Ldk.swift

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -250,13 +250,14 @@ class Ldk: NSObject {
250250
if read.isOk() {
251251
networkGraph = read.getValue()
252252
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Loaded network graph from file")
253-
254253
}
255254
} catch {
256255
networkGraph = NetworkGraph(genesis_hash: String(genesisHash).hexaBytes, logger: logger)
257256
LdkEventEmitter.shared.send(withEvent: .native_log, body: "Failed to load cached network graph from disk. Will sync from scratch. \(error.localizedDescription)")
258257
}
259258

259+
print("rapidGossipSyncUrl: \(rapidGossipSyncUrl)")
260+
260261
//Download url passed, enable rapid gossip sync
261262
if rapidGossipSyncUrl != "" {
262263
do {
@@ -377,6 +378,8 @@ class Ldk: NSObject {
377378
channelMonitorsSerialized.append([UInt8](try! Data(contentsOf: channelFile.standardizedFileURL)))
378379
}
379380

381+
print("enableP2PGossip \(enableP2PGossip)")
382+
380383
do {
381384
//Only restore a node if we have existing channel monitors to restore. Else we lose our UserConfig settings when restoring.
382385
if let channelManagerSerialized = storedChannelManager, channelMonitorsSerialized.count > 0 {
@@ -430,6 +433,10 @@ class Ldk: NSObject {
430433
peerHandler = channelManagerConstructor!.getTCPPeerHandler()
431434
invoicePayer = channelManagerConstructor!.payer
432435

436+
if enableP2PGossip {
437+
self.networkGraph = channelManagerConstructor!.net_graph
438+
}
439+
433440
return handleResolve(resolve, .channel_manager_init_success)
434441
}
435442

@@ -819,7 +826,7 @@ class Ldk: NSObject {
819826
}
820827

821828
@objc
822-
func networkGraphListNodes(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
829+
func networkGraphListNodeIds(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
823830
guard let networkGraph = networkGraph?.read_only() else {
824831
return handleReject(reject, .init_network_graph)
825832
}
@@ -833,20 +840,29 @@ class Ldk: NSObject {
833840
}
834841

835842
@objc
836-
func networkGraphNode(_ nodeId: NSString, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
843+
func networkGraphNodes(_ nodeIds: NSArray, resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
837844
guard let networkGraph = networkGraph?.read_only() else {
838845
return handleReject(reject, .init_network_graph)
839846
}
847+
848+
//Filter out nodes we don't know about as querying unknown nodes will cause a crash
849+
let includedList = nodeIds.map({ $0 as! String }).filter { id in
850+
return networkGraph.list_nodes().contains { id == Data($0.as_slice()).hexEncodedString() }
851+
}
840852

841-
return resolve(networkGraph.node(node_id: NodeId(pubkey: String(nodeId).hexaBytes)).asJson)
853+
return resolve(includedList.map({ id in
854+
var info = networkGraph.node(node_id: NodeId(pubkey: id.hexaBytes)).asJson
855+
info["id"] = id
856+
return info
857+
}))
842858
}
843859

844860
@objc
845861
func networkGraphListChannels(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
846862
guard let networkGraph = networkGraph?.read_only() else {
847863
return handleReject(reject, .init_network_graph)
848864
}
849-
865+
850866
let total = networkGraph.list_channels().count
851867
if total > 100 {
852868
return handleReject(reject, .data_too_large_for_rn, nil, "Too many channels to return (\(total))")
@@ -861,7 +877,14 @@ class Ldk: NSObject {
861877
return handleReject(reject, .init_network_graph)
862878
}
863879

864-
return resolve(networkGraph.channel(short_channel_id: UInt64(shortChannelId as String)!).asJson)
880+
let channelId = String(shortChannelId)
881+
882+
let channels = networkGraph.list_channels()
883+
if !channels.contains{ channelId == String($0) } {
884+
return handleReject(reject, .init_network_graph)
885+
}
886+
887+
return resolve(networkGraph.channel(short_channel_id: UInt64(channelId)!).asJson)
865888
}
866889

867890
@objc

lib/src/ldk.ts

Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -520,16 +520,9 @@ class LDK {
520520
}
521521

522522
//Check if node is in our network graph
523-
const graphRes = await this.networkGraphListNodes();
523+
const graphRes = await this.networkGraphNodes([recover_payee_pub_key]);
524524
if (graphRes.isOk()) {
525-
let nodeInNetworkGraph = false;
526-
graphRes.value.forEach((node) => {
527-
if (node === recover_payee_pub_key) {
528-
nodeInNetworkGraph = true;
529-
}
530-
});
531-
532-
if (!nodeInNetworkGraph) {
525+
if (graphRes.value.length === 0) {
533526
useFullMessage = `${useFullMessage} Node not found in network graph.`;
534527
}
535528
}
@@ -666,31 +659,31 @@ class LDK {
666659
}
667660

668661
/**
669-
* Fetches list of node IDs in network graph
662+
* Fetches list of all node IDs in network graph
670663
* https://docs.rs/lightning/latest/lightning/routing/gossip/struct.ReadOnlyNetworkGraph.html#method.nodes
671664
* @returns {Promise<Ok<Ok<string[]> | Err<string[]>> | Err<unknown>>}
672665
*/
673-
async networkGraphListNodes(): Promise<Result<string[]>> {
666+
async networkGraphListNodeIds(): Promise<Result<string[]>> {
674667
try {
675-
const res = await NativeLDK.networkGraphListNodes();
668+
const res = await NativeLDK.networkGraphListNodeIds();
676669
return ok(res);
677670
} catch (e) {
678671
return err(e);
679672
}
680673
}
681674

682675
/**
683-
* Fetches node details from network graph
676+
* Fetches array of node details from network graph
684677
* https://docs.rs/lightning/latest/lightning/routing/gossip/struct.ChannelInfo.html
685-
* @param shortChannelId
678+
* @param nodeIds string[]
686679
* @returns {Promise<Ok<Ok<string> | Err<string>> | Err<unknown>>}
687680
*/
688-
async networkGraphNode(
689-
nodeId: string,
690-
): Promise<Result<TNetworkGraphNodeInfo>> {
681+
async networkGraphNodes(
682+
nodeIds: string[],
683+
): Promise<Result<TNetworkGraphNodeInfo[]>> {
691684
try {
692-
const res = await NativeLDK.networkGraphNode(nodeId);
693-
return ok({ ...res, nodeId });
685+
const res = await NativeLDK.networkGraphNodes(nodeIds);
686+
return ok(res);
694687
} catch (e) {
695688
return err(e);
696689
}
@@ -703,29 +696,28 @@ class LDK {
703696
*/
704697
async completeGraphNodes(): Promise<Result<TNetworkGraphNodeInfo[]>> {
705698
try {
706-
const res = await this.networkGraphListNodes();
707-
let nodes: TNetworkGraphNodeInfo[] = [];
699+
const res = await this.networkGraphListNodeIds();
708700
if (res.isErr()) {
709701
return err(res.error);
710702
}
711703

712-
for (let index = 0; index < res.value.length; index++) {
713-
const nodeRes = await this.networkGraphNode(res.value[index]);
714-
if (nodeRes.isErr()) {
715-
return err(nodeRes.error);
716-
}
704+
if (res.value.length > 100) {
705+
return err(`Too many nodes to query (${res.value.length})`);
706+
}
717707

718-
nodes.push(nodeRes.value);
708+
const nodeRes = await this.networkGraphNodes(res.value);
709+
if (nodeRes.isErr()) {
710+
return err(nodeRes.error);
719711
}
720712

721-
return ok(nodes);
713+
return ok(nodeRes.value);
722714
} catch (e) {
723715
return err(e);
724716
}
725717
}
726718

727719
/**
728-
* Fetches list of short channel IDs in network graph
720+
* Fetches list of all short channel IDs in network graph
729721
* https://docs.rs/lightning/latest/lightning/routing/gossip/struct.ReadOnlyNetworkGraph.html#method.channels
730722
* @returns {Promise<Ok<string[]>> | Err<unknown>>}
731723
*/

lib/src/utils/types.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@ export enum EEventTypes {
3030

3131
//LDK event responses
3232
export type TRegisterTxEvent = { txid: string; script_pubkey: string };
33+
3334
export type TRegisterOutputEvent = {
3435
block_hash: string;
3536
index: number;
3637
script_pubkey: string;
3738
};
39+
3840
export type TBroadcastTransactionEvent = { tx: string };
3941

4042
//LDK channel manager event responses
@@ -44,26 +46,30 @@ export type TChannelManagerFundingGenerationReady = {
4446
user_channel_id: number;
4547
value_satoshis: number;
4648
};
49+
4750
export type TChannelManagerPayment = {
4851
payment_hash: string;
4952
amount_sat: number;
5053
payment_preimage: string;
5154
payment_secret: string;
5255
spontaneous_payment_preimage: string;
5356
};
57+
5458
export type TChannelManagerPaymentSent = {
5559
payment_id: string;
5660
payment_preimage: string;
5761
payment_hash: string;
5862
fee_paid_sat: number;
5963
};
64+
6065
export type TChannelManagerOpenChannelRequest = {
6166
temp_channel_id: string;
6267
counterparty_node_id: string;
6368
push_sat: number;
6469
funding_satoshis: number;
6570
channel_type: string;
6671
};
72+
6773
export type TChannelUpdate = {
6874
channel_id: string;
6975
counterparty_node_id: string;
@@ -81,6 +87,7 @@ export type TChannelManagerPaymentPathSuccessful = {
8187
payment_hash: string;
8288
path: TPath[];
8389
};
90+
8491
export type TChannelManagerPaymentPathFailed = {
8592
payment_id: string;
8693
payment_hash: string;
@@ -89,21 +96,26 @@ export type TChannelManagerPaymentPathFailed = {
8996
path: TPath[];
9097
network_update: string;
9198
};
99+
92100
export type TChannelManagerPaymentFailed = {
93101
payment_id: string;
94102
payment_hash: string;
95103
};
104+
96105
export type TChannelManagerPendingHtlcsForwardable = {
97106
time_forwardable: number;
98107
};
108+
99109
export type TChannelManagerSpendableOutputs = {
100110
outputsSerialized: string[];
101111
};
112+
102113
export type TChannelManagerChannelClosed = {
103114
user_channel_id: number;
104115
channel_id: string;
105116
reason: string;
106117
};
118+
107119
export type TChannelManagerDiscardFunding = {
108120
channel_id: string;
109121
tx: string;
@@ -151,8 +163,11 @@ export type TNetworkGraphChannelInfo = {
151163
};
152164

153165
export type TNetworkGraphNodeInfo = {
154-
nodeId: string;
166+
id: string;
155167
shortChannelIds: string[];
168+
lowest_inbound_channel_fees_base_msat: number;
169+
lowest_inbound_channel_fees_proportional_millionths: number;
170+
announcement_info_last_update: number;
156171
};
157172

158173
export type TInvoice = {

0 commit comments

Comments
 (0)