Skip to content

Commit 4d00cfb

Browse files
LSPS5 support on ldk-node
1 parent 65945f8 commit 4d00cfb

File tree

7 files changed

+1071
-12
lines changed

7 files changed

+1071
-12
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ bdk_esplora = { version = "0.22.0", default-features = false, features = ["async
8181
bdk_electrum = { version = "0.23.0", default-features = false, features = ["use-rustls-ring"]}
8282
bdk_wallet = { version = "2.0.0", default-features = false, features = ["std", "keys-bip39"]}
8383

84-
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
84+
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls", "blocking"] }
8585
rustls = { version = "0.23", default-features = false }
8686
rusqlite = { version = "0.31.0", features = ["bundled"] }
8787
bitcoin = "0.32.4"

bindings/ldk_node.udl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ interface Node {
130130
OnchainPayment onchain_payment();
131131
UnifiedQrPayment unified_qr_payment();
132132
LSPS1Liquidity lsps1_liquidity();
133+
LSPS5Liquidity lsps5_liquidity();
133134
[Throws=NodeError]
134135
void connect(PublicKey node_id, SocketAddress address, boolean persist);
135136
[Throws=NodeError]
@@ -264,6 +265,15 @@ interface LSPS1Liquidity {
264265
LSPS1OrderStatus check_order_status(LSPS1OrderId order_id);
265266
};
266267

268+
interface LSPS5Liquidity {
269+
[Throws=NodeError]
270+
LSPS5SetWebhookResponse set_webhook(string app_name, string webhook_url);
271+
[Throws=NodeError]
272+
LSPS5ListWebhooksResponse list_webhooks();
273+
[Throws=NodeError]
274+
LSPS5RemoveWebhookResponse remove_webhook(string app_name);
275+
};
276+
267277
[Error]
268278
enum NodeError {
269279
"AlreadyRunning",
@@ -320,6 +330,8 @@ enum NodeError {
320330
"LiquidityFeeTooHigh",
321331
"InvalidBlindedPaths",
322332
"AsyncPaymentServicesDisabled",
333+
"LiquiditySetWebhookFailed",
334+
"LiquidityRemoveWebhookFailed",
323335
};
324336

325337
dictionary NodeStatus {
@@ -531,6 +543,20 @@ enum LSPS1PaymentState {
531543
"Refunded",
532544
};
533545

546+
dictionary LSPS5SetWebhookResponse {
547+
u32 num_webhooks;
548+
u32 max_webhooks;
549+
boolean no_change;
550+
};
551+
552+
dictionary LSPS5ListWebhooksResponse {
553+
sequence<string> app_names;
554+
u32 max_webhooks;
555+
};
556+
557+
dictionary LSPS5RemoveWebhookResponse {
558+
};
559+
534560
[NonExhaustive]
535561
enum Network {
536562
"Bitcoin",

src/builder.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ use crate::io::{
2323
self, PAYMENT_INFO_PERSISTENCE_PRIMARY_NAMESPACE, PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE,
2424
};
2525
use crate::liquidity::{
26-
LSPS1ClientConfig, LSPS2ClientConfig, LSPS2ServiceConfig, LiquiditySourceBuilder,
26+
LSPS1ClientConfig, LSPS2ClientConfig, LSPS2ServiceConfig, LSPS5ClientConfig,
27+
LSPS5ServiceConfig, LiquiditySourceBuilder,
2728
};
2829
use crate::logger::{log_error, LdkLogger, LogLevel, LogWriter, Logger};
2930
use crate::message_handler::NodeCustomMessageHandler;
@@ -125,6 +126,10 @@ struct LiquiditySourceConfig {
125126
lsps2_client: Option<LSPS2ClientConfig>,
126127
// Act as an LSPS2 service.
127128
lsps2_service: Option<LSPS2ServiceConfig>,
129+
/// Act as an LSPS5 client connecting to the given service.
130+
lsps5_client: Option<LSPS5ClientConfig>,
131+
// Act as an LSPS5 service.
132+
lsps5_service: Option<LSPS5ServiceConfig>,
128133
}
129134

130135
#[derive(Clone)]
@@ -738,6 +743,27 @@ impl NodeBuilder {
738743
kv_store,
739744
)
740745
}
746+
747+
/// Configures the [`Node`] instance to source inbound liquidity from the given
748+
pub fn set_liquidity_source_lsps5(
749+
&mut self, node_id: PublicKey, address: SocketAddress,
750+
) -> &mut Self {
751+
let liquidity_source_config =
752+
self.liquidity_source_config.get_or_insert(LiquiditySourceConfig::default());
753+
let lsps5_client_config = LSPS5ClientConfig { node_id, address };
754+
liquidity_source_config.lsps5_client = Some(lsps5_client_config);
755+
self
756+
}
757+
758+
/// Configures the [`Node`] instance to provide an LSPS5 service
759+
pub fn set_liquidity_provider_lsps5(
760+
&mut self, service_config: LSPS5ServiceConfig,
761+
) -> &mut Self {
762+
let liquidity_source_config =
763+
self.liquidity_source_config.get_or_insert(LiquiditySourceConfig::default());
764+
liquidity_source_config.lsps5_service = Some(service_config);
765+
self
766+
}
741767
}
742768

743769
/// A builder for an [`Node`] instance, allowing to set some configuration and module choices from
@@ -928,6 +954,20 @@ impl ArcedNodeBuilder {
928954
self.inner.write().unwrap().set_liquidity_provider_lsps2(service_config);
929955
}
930956

957+
/// Configures the [`Node`] instance to source inbound liquidity from the given [LSPS5] LSP.
958+
///
959+
/// [LSPS5]: https://github.com/lightning/blips/blob/master/blip-0055.md
960+
pub fn set_liquidity_source_lsps5(&self, node_id: PublicKey, address: SocketAddress) {
961+
self.inner.write().unwrap().set_liquidity_source_lsps5(node_id, address);
962+
}
963+
964+
/// Configures the [`Node`] instance to provide an LSPS5 service.
965+
///
966+
/// [LSPS5]: https://github.com/lightning/blips/blob/master/blip-0055.md
967+
pub fn set_liquidity_provider_lsps5(&self, service_config: LSPS5ServiceConfig) {
968+
self.inner.write().unwrap().set_liquidity_provider_lsps5(service_config);
969+
}
970+
931971
/// Sets the used storage directory path.
932972
pub fn set_storage_dir_path(&self, storage_dir_path: String) {
933973
self.inner.write().unwrap().set_storage_dir_path(storage_dir_path);
@@ -1542,6 +1582,13 @@ fn build_with_store_internal(
15421582
liquidity_source_builder.lsps2_service(promise_secret, config.clone())
15431583
});
15441584

1585+
lsc.lsps5_client.as_ref().map(|config| {
1586+
liquidity_source_builder.lsps5_client(config.node_id, config.address.clone())
1587+
});
1588+
lsc.lsps5_service
1589+
.as_ref()
1590+
.map(|config| liquidity_source_builder.lsps5_service(config.clone()));
1591+
15451592
let liquidity_source = Arc::new(liquidity_source_builder.build());
15461593
let custom_message_handler =
15471594
Arc::new(NodeCustomMessageHandler::new_liquidity(Arc::clone(&liquidity_source)));

src/error.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,10 @@ pub enum Error {
124124
InvalidBlindedPaths,
125125
/// Asynchronous payment services are disabled.
126126
AsyncPaymentServicesDisabled,
127+
/// Failed to set a webhook with the LSP.
128+
LiquiditySetWebhookFailed,
129+
/// Failed to remove a webhook with the LSP.
130+
LiquidityRemoveWebhookFailed,
127131
}
128132

129133
impl fmt::Display for Error {
@@ -197,9 +201,17 @@ impl fmt::Display for Error {
197201
Self::LiquidityFeeTooHigh => {
198202
write!(f, "The given operation failed due to the LSP's required opening fee being too high.")
199203
},
204+
<<<<<<< HEAD
200205
Self::InvalidBlindedPaths => write!(f, "The given blinded paths are invalid."),
201206
Self::AsyncPaymentServicesDisabled => {
202207
write!(f, "Asynchronous payment services are disabled.")
208+
=======
209+
Self::LiquiditySetWebhookFailed => {
210+
write!(f, "Failed to set a webhook with the LSP.")
211+
},
212+
Self::LiquidityRemoveWebhookFailed => {
213+
write!(f, "Failed to remove a webhook with the LSP.")
214+
>>>>>>> cce04d5 (LSPS5 support on ldk-node)
203215
},
204216
}
205217
}

src/lib.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,14 @@ use std::sync::atomic::{AtomicBool, Ordering};
171171
use std::sync::{Arc, Mutex, RwLock};
172172
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
173173

174+
#[cfg(feature = "uniffi")]
175+
use crate::liquidity::{
176+
LSPS5Liquidity, LSPS5ListWebhooksResponse, LSPS5RemoveWebhookResponse, LSPS5SetWebhookResponse,
177+
};
178+
179+
#[cfg(not(feature = "uniffi"))]
180+
use crate::liquidity::LSPS5Liquidity;
181+
174182
#[cfg(feature = "uniffi")]
175183
uniffi::include_scaffolding!("ldk_node");
176184

@@ -958,6 +966,32 @@ impl Node {
958966
))
959967
}
960968

969+
/// Returns a liquidity handler allowing to handle webhooks and notifications via the [bLIP-55 / LSPS5] protocol.
970+
///
971+
/// [bLIP-55 / LSPS5]: https://github.com/lightning/blips/blob/master/blip-0055.md
972+
#[cfg(not(feature = "uniffi"))]
973+
pub fn lsps5_liquidity(&self) -> LSPS5Liquidity {
974+
LSPS5Liquidity::new(
975+
Arc::clone(&self.runtime),
976+
Arc::clone(&self.connection_manager),
977+
self.liquidity_source.clone(),
978+
Arc::clone(&self.logger),
979+
)
980+
}
981+
982+
/// Returns a liquidity handler allowing to handle webhooks and notifications via the [bLIP-55 / LSPS5] protocol.
983+
///
984+
/// [bLIP-55 / LSPS5]: https://github.com/lightning/blips/blob/master/blip-0055.md
985+
#[cfg(feature = "uniffi")]
986+
pub fn lsps5_liquidity(&self) -> Arc<LSPS5Liquidity> {
987+
Arc::new(LSPS5Liquidity::new(
988+
Arc::clone(&self.runtime),
989+
Arc::clone(&self.connection_manager),
990+
self.liquidity_source.clone(),
991+
Arc::clone(&self.logger),
992+
))
993+
}
994+
961995
/// Retrieve a list of known channels.
962996
pub fn list_channels(&self) -> Vec<ChannelDetails> {
963997
self.channel_manager.list_channels().into_iter().map(|c| c.into()).collect()

0 commit comments

Comments
 (0)