Skip to content

Commit 5f70206

Browse files
committed
Expose list_channels in bindings
1 parent 26b8ea9 commit 5f70206

File tree

4 files changed

+130
-5
lines changed

4 files changed

+130
-5
lines changed

bindings/ldk_node.udl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ interface Node {
4848
Invoice receive_variable_amount_payment([ByRef]string description, u32 expiry_secs);
4949
PaymentInfo? payment_info([ByRef]PaymentHash payment_hash);
5050
sequence<PublicKey> list_peers();
51+
sequence<ChannelDetails> list_channels();
5152
};
5253

5354
[Error]
@@ -107,6 +108,29 @@ dictionary PaymentInfo {
107108
PaymentStatus status;
108109
};
109110

111+
dictionary OutPoint {
112+
string txid;
113+
u16 index;
114+
};
115+
116+
dictionary ChannelDetails {
117+
ChannelId channel_id;
118+
PublicKey counterparty;
119+
OutPoint? funding_txo;
120+
u64? short_channel_id;
121+
u64 channel_value_satoshis;
122+
u64 balance_msat;
123+
u64 outbound_capacity_msat;
124+
u64 inbound_capacity_msat;
125+
u32? confirmations_required;
126+
u32? confirmations;
127+
boolean is_outbound;
128+
boolean is_channel_ready;
129+
boolean is_usable;
130+
boolean is_public;
131+
u16? cltv_expiry_delta;
132+
};
133+
110134
[Custom]
111135
typedef string PublicKey;
112136

src/channel.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
use bitcoin::secp256k1::PublicKey;
2+
use lightning::chain::transaction::OutPoint as LdkOutpoint;
3+
use lightning::ln::channelmanager::ChannelDetails as LdkChannelDetails;
4+
use crate::ChannelId;
5+
6+
/// Data structure that references and transaction output.
7+
pub struct OutPoint {
8+
/// The referenced transaction's txid.
9+
pub txid: String,
10+
/// The index of the referenced output in its transaction's vout.
11+
pub index: u16,
12+
}
13+
14+
impl From<LdkOutpoint> for OutPoint {
15+
fn from(value: LdkOutpoint) -> Self {
16+
OutPoint {
17+
txid: value.txid.to_string(),
18+
index: value.index,
19+
}
20+
}
21+
}
22+
23+
/// Details about the user's channel as returned by [`Node::list_channels`].
24+
///
25+
/// [`Node::list_channels`]: [`crate::Node::list_channels`]
26+
pub struct ChannelDetails {
27+
/// The channel's ID.
28+
pub channel_id: ChannelId,
29+
/// The `node_id` of our channel's counterparty.
30+
pub counterparty: PublicKey,
31+
/// Information about the channel's funding transaction output. `None `unless a funding
32+
/// transaction has been successfully negotiated with the channel's counterparty.
33+
pub funding_txo: Option<OutPoint>,
34+
/// Position of the funding transaction on-chain. `None` unless the funding transaction has been
35+
/// confirmed and fully opened.
36+
pub short_channel_id: Option<u64>,
37+
/// The value, in satoshis, of this channel as appears in the funding output.
38+
pub channel_value_satoshis: u64,
39+
/// Total balance of the channel. It is the amount that will be returned to the user if the
40+
/// channel is closed. The value is not exact, due to potential in-flight and fee-rate changes.
41+
/// Therefore, exactly this amount is likely irrecoverable on close.
42+
pub balance_msat: u64,
43+
/// Available outbound capacity for sending HTLCs to the remote peer. The amount does not
44+
/// include any pending HTLCs which are not yet resolved (and, thus, whose balance is not
45+
/// available for inclusion in new outbound HTLCs). This further does not include any
46+
/// pending outgoing HTLCs which are awaiting some other resolution to be sent.
47+
pub outbound_capacity_msat: u64,
48+
/// Available outbound capacity for sending HTLCs to the remote peer. The amount does not
49+
/// include any pending HTLCs which are not yet resolved (and, thus, whose balance is not
50+
/// available for inclusion in new inbound HTLCs). This further does not include any
51+
/// pending outgoing HTLCs which are awaiting some other resolution to be sent.
52+
pub inbound_capacity_msat: u64,
53+
/// The number of required confirmations on the funding transactions before the funding is
54+
/// considered "locked". The amount is selected by the channel fundee.
55+
///
56+
/// The value will be `None` for outbound channels until the counterparty accepts the channel.
57+
pub confirmations_required: Option<u32>,
58+
/// The current number of confirmations on the funding transaction.
59+
pub confirmations: Option<u32>,
60+
/// Returns `True` if the channel was initiated (and therefore funded) by us.
61+
pub is_outbound: bool,
62+
/// Returns `True` if the channel is confirmed, both parties have exchanged `channel_ready`
63+
/// messages, and the channel is not currently being shut down. Both parties exchange
64+
/// `channel_ready` messages upon independently verifying that the required confirmations count
65+
/// provided by `confirmations_required` has been reached.
66+
pub is_channel_ready: bool,
67+
/// Returns `True` if the channel is (a) confirmed and `channel_ready` has been exchanged,
68+
/// (b) the peer is connected, and (c) the channel is not currently negotiating shutdown.
69+
pub is_usable: bool,
70+
/// Returns `True` if this channel is (or will be) publicly-announced
71+
pub is_public: bool,
72+
/// The difference in the CLTV value between incoming HTLCs and an outbound HTLC forwarded over
73+
/// the channel.
74+
pub cltv_expiry_delta: Option<u16>,
75+
}
76+
77+
impl From<LdkChannelDetails> for ChannelDetails {
78+
fn from(value: LdkChannelDetails) -> Self {
79+
ChannelDetails {
80+
channel_id: ChannelId(value.channel_id),
81+
counterparty: value.counterparty.node_id,
82+
funding_txo: value.funding_txo.and_then(|o| Some(o.into())),
83+
short_channel_id: value.short_channel_id,
84+
channel_value_satoshis: value.channel_value_satoshis,
85+
balance_msat: value.balance_msat,
86+
outbound_capacity_msat: value.outbound_capacity_msat,
87+
inbound_capacity_msat: value.inbound_capacity_msat,
88+
confirmations_required: value.confirmations_required,
89+
confirmations: value.confirmations,
90+
is_outbound: value.is_outbound,
91+
is_channel_ready: value.is_channel_ready,
92+
is_usable: value.is_usable,
93+
is_public: value.is_public,
94+
cltv_expiry_delta: value.config.and_then(|c| Some(c.cltv_expiry_delta)),
95+
}
96+
}
97+
}

src/lib.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ mod peer_store;
3434
mod tests;
3535
mod types;
3636
mod wallet;
37+
mod channel;
3738

3839
pub use bitcoin;
3940
pub use lightning;
@@ -59,9 +60,7 @@ use logger::{log_error, log_info, FilesystemLogger, Logger};
5960
use lightning::chain::keysinterface::EntropySource;
6061
use lightning::chain::{chainmonitor, BestBlock, Confirm, Watch};
6162
use lightning::ln::channelmanager;
62-
use lightning::ln::channelmanager::{
63-
ChainParameters, ChannelDetails, ChannelManagerReadArgs, PaymentId, Retry,
64-
};
63+
use lightning::ln::channelmanager::{ChainParameters, ChannelManagerReadArgs, PaymentId, Retry};
6564
use lightning::ln::peer_handler::{IgnoringMessageHandler, MessageHandler};
6665
use lightning::ln::{PaymentHash, PaymentPreimage, PaymentSecret};
6766
use lightning::routing::gossip::P2PGossipSync;
@@ -99,6 +98,7 @@ use std::str::FromStr;
9998
use std::sync::atomic::{AtomicBool, Ordering};
10099
use std::sync::{Arc, Mutex, RwLock};
101100
use std::time::{Duration, Instant, SystemTime};
101+
use crate::channel::{ChannelDetails, OutPoint};
102102

103103
uniffi::include_scaffolding!("ldk_node");
104104

@@ -754,7 +754,11 @@ impl Node {
754754

755755
/// Retrieve a list of known channels.
756756
pub fn list_channels(&self) -> Vec<ChannelDetails> {
757-
self.channel_manager.list_channels()
757+
self.channel_manager
758+
.list_channels()
759+
.iter()
760+
.map(|c| c.clone().into())
761+
.collect()
758762
}
759763

760764
/// Connect to a node and open a new channel. Disconnects and re-connects are handled automatically

src/tests/functional_tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ fn channel_full_cycle() {
186186
assert_eq!(node_a.list_peers(), [node_b.node_id()]);
187187

188188
let funding_txo = loop {
189-
let details = node_a.list_channels();
189+
let details = node_a.channel_manager.list_channels();
190190

191191
if details.is_empty() || details[0].funding_txo.is_none() {
192192
std::thread::sleep(Duration::from_secs(1));

0 commit comments

Comments
 (0)