Skip to content

Commit ed4e1c8

Browse files
committed
Add LSPS5 webhook notification support
Integrates LSPS5 (BLIP-0055) from lightning-liquidity to enable webhook-based push notifications for clients. - Add event system integration for LSPS5 events - Expose public API for webhook management This allows client developers to register webhook endpoints with their LSP to receive notifications when their app is offline.
1 parent 066c0e1 commit ed4e1c8

7 files changed

Lines changed: 1304 additions & 9 deletions

File tree

bindings/ldk_node.udl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,9 @@ enum NodeError {
351351
"InvalidBlindedPaths",
352352
"AsyncPaymentServicesDisabled",
353353
"HrnParsingFailed",
354+
"LiquiditySetWebhookFailed",
355+
"LiquidityRemoveWebhookFailed",
356+
"LiquidityListWebhooksFailed"
354357
};
355358

356359
dictionary NodeStatus {

src/builder.rs

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ use crate::io::{
6565
PENDING_PAYMENT_INFO_PERSISTENCE_SECONDARY_NAMESPACE,
6666
};
6767
use crate::liquidity::{
68-
LSPS1ClientConfig, LSPS2ClientConfig, LSPS2ServiceConfig, LiquiditySourceBuilder,
68+
LSPS1ClientConfig, LSPS2ClientConfig, LSPS2ServiceConfig, LSPS5ClientConfig,
69+
LiquiditySourceBuilder,
6970
};
7071
use crate::logger::{log_error, LdkLogger, LogLevel, LogWriter, Logger};
7172
use crate::message_handler::NodeCustomMessageHandler;
@@ -124,6 +125,12 @@ struct LiquiditySourceConfig {
124125
lsps2_client: Option<LSPS2ClientConfig>,
125126
// Act as an LSPS2 service.
126127
lsps2_service: Option<LSPS2ServiceConfig>,
128+
// Act as an LSPS5 client connecting to the given service.
129+
lsps5_client: Option<LSPS5ClientConfig>,
130+
// Act as an LSPS5 service.
131+
lsps5_service: Option<LSPS5ServiceConfig>,
132+
// Optional custom HTTP client to be used by LSPS5 service.
133+
http_client: Option<reqwest::Client>,
127134
}
128135

129136
#[derive(Clone)]
@@ -449,6 +456,44 @@ impl NodeBuilder {
449456
self
450457
}
451458

459+
/// Configures the [`Node`] instance to source webhook notifications from the given
460+
/// [bLIP-55 / LSPS5] service.
461+
///
462+
/// This allows the client to register webhook endpoints with the LSP to receive
463+
/// push notifications for Lightning events when the client is offline.
464+
///
465+
/// [bLIP-55 / LSPS5]: https://github.com/lightning/blips/blob/master/blip-0055.md
466+
pub fn set_liquidity_source_lsps5(
467+
&mut self, node_id: PublicKey, address: SocketAddress,
468+
) -> &mut Self {
469+
let liquidity_source_config =
470+
self.liquidity_source_config.get_or_insert(LiquiditySourceConfig::default());
471+
let lsps5_client_config = LSPS5ClientConfig { node_id, address };
472+
liquidity_source_config.lsps5_client = Some(lsps5_client_config);
473+
self
474+
}
475+
476+
/// Configures the [`Node`] instance to provide an [LSPS5] service, enabling clients
477+
/// to register webhooks for push notifications.
478+
///
479+
/// [LSPS5]: https://github.com/lightning/blips/blob/master/blip-0055.md
480+
pub fn set_liquidity_provider_lsps5(
481+
&mut self, service_config: LSPS5ServiceConfig,
482+
) -> &mut Self {
483+
let liquidity_source_config =
484+
self.liquidity_source_config.get_or_insert(LiquiditySourceConfig::default());
485+
liquidity_source_config.lsps5_service = Some(service_config);
486+
self
487+
}
488+
489+
/// Sets a custom HTTP client to be used by the LSPS5 service.
490+
pub fn set_liquidity_http_client(&mut self, http_client: reqwest::Client) -> &mut Self {
491+
let liquidity_source_config =
492+
self.liquidity_source_config.get_or_insert(LiquiditySourceConfig::default());
493+
liquidity_source_config.http_client = Some(http_client);
494+
self
495+
}
496+
452497
/// Sets the used storage directory path.
453498
pub fn set_storage_dir_path(&mut self, storage_dir_path: String) -> &mut Self {
454499
self.config.storage_dir_path = storage_dir_path;
@@ -850,6 +895,30 @@ impl ArcedNodeBuilder {
850895
self.inner.write().unwrap().set_liquidity_provider_lsps2(service_config);
851896
}
852897

898+
/// Configures the [`Node`] instance to source webhook notifications from the given
899+
/// [bLIP-55 / LSPS5] service.
900+
///
901+
/// This allows the client to register webhook endpoints with the LSP to receive
902+
/// push notifications for Lightning events when the client is offline.
903+
///
904+
/// [bLIP-55 / LSPS5]: https://github.com/lightning/blips/blob/master/blip-0055.md
905+
pub fn set_liquidity_source_lsps5(&self, node_id: PublicKey, address: SocketAddress) {
906+
self.inner.write().unwrap().set_liquidity_source_lsps5(node_id, address);
907+
}
908+
909+
/// Configures the [`Node`] instance to provide an [LSPS5] service, enabling clients
910+
/// to register webhooks for push notifications.
911+
///
912+
/// [LSPS5]: https://github.com/lightning/blips/blob/master/blip-0055.md
913+
pub fn set_liquidity_provider_lsps5(&self, service_config: LSPS5ServiceConfig) {
914+
self.inner.write().unwrap().set_liquidity_provider_lsps5(service_config);
915+
}
916+
917+
/// Sets a custom HTTP client to be used by the LSPS5 service.
918+
pub fn set_liquidity_http_client(&self, http_client: reqwest::Client) {
919+
self.inner.write().unwrap().set_liquidity_http_client(http_client);
920+
}
921+
853922
/// Sets the used storage directory path.
854923
pub fn set_storage_dir_path(&self, storage_dir_path: String) {
855924
self.inner.write().unwrap().set_storage_dir_path(storage_dir_path);
@@ -1626,6 +1695,15 @@ fn build_with_store_internal(
16261695
liquidity_source_builder.lsps2_service(promise_secret, config.clone())
16271696
});
16281697

1698+
lsc.lsps5_client.as_ref().map(|config| {
1699+
liquidity_source_builder.lsps5_client(config.node_id, config.address.clone())
1700+
});
1701+
1702+
lsc.lsps5_service.as_ref().map(|config| {
1703+
let http_client = lsc.http_client.clone().unwrap_or_else(|| reqwest::Client::new());
1704+
liquidity_source_builder.lsps5_service_with_http_client(config.clone(), http_client)
1705+
});
1706+
16291707
let liquidity_source = runtime
16301708
.block_on(async move { liquidity_source_builder.build().await.map(Arc::new) })?;
16311709
let custom_message_handler =

src/error.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ pub enum Error {
131131
AsyncPaymentServicesDisabled,
132132
/// Parsing a Human-Readable Name has failed.
133133
HrnParsingFailed,
134+
/// Failed to set a webhook with the LSP.
135+
LiquiditySetWebhookFailed,
136+
/// Failed to remove a webhook with the LSP.
137+
LiquidityRemoveWebhookFailed,
138+
/// Failed to list webhooks with the LSP.
139+
LiquidityListWebhooksFailed,
134140
}
135141

136142
impl fmt::Display for Error {
@@ -213,6 +219,15 @@ impl fmt::Display for Error {
213219
Self::HrnParsingFailed => {
214220
write!(f, "Failed to parse a human-readable name.")
215221
},
222+
Self::LiquiditySetWebhookFailed => {
223+
write!(f, "Failed to set a webhook with the LSP.")
224+
},
225+
Self::LiquidityRemoveWebhookFailed => {
226+
write!(f, "Failed to remove a webhook with the LSP.")
227+
},
228+
Self::LiquidityListWebhooksFailed => {
229+
write!(f, "Failed to list webhooks with the LSP.")
230+
},
216231
}
217232
}
218233
}

src/lib.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ use lightning::ln::msgs::SocketAddress;
148148
use lightning::routing::gossip::NodeAlias;
149149
use lightning::util::persist::KVStoreSync;
150150
use lightning_background_processor::process_events_async;
151-
use liquidity::{LSPS1Liquidity, LiquiditySource};
151+
use liquidity::{LSPS1Liquidity, LSPS5Liquidity, LiquiditySource};
152152
use logger::{log_debug, log_error, log_info, log_trace, LdkLogger, Logger};
153153
use payment::asynchronous::om_mailbox::OnionMessageMailbox;
154154
use payment::asynchronous::static_invoice_store::StaticInvoiceStore;
@@ -1032,6 +1032,32 @@ impl Node {
10321032
))
10331033
}
10341034

1035+
/// Returns a liquidity handler allowing to handle webhooks and notifications via the [bLIP-55 / LSPS5] protocol.
1036+
///
1037+
/// [bLIP-55 / LSPS5]: https://github.com/lightning/blips/blob/master/blip-0055.md
1038+
#[cfg(not(feature = "uniffi"))]
1039+
pub fn lsps5_liquidity(&self) -> LSPS5Liquidity {
1040+
LSPS5Liquidity::new(
1041+
Arc::clone(&self.runtime),
1042+
Arc::clone(&self.connection_manager),
1043+
self.liquidity_source.clone(),
1044+
Arc::clone(&self.logger),
1045+
)
1046+
}
1047+
1048+
/// Returns a liquidity handler allowing to handle webhooks and notifications via the [bLIP-55 / LSPS5] protocol.
1049+
///
1050+
/// [bLIP-55 / LSPS5]: https://github.com/lightning/blips/blob/master/blip-0055.md
1051+
#[cfg(feature = "uniffi")]
1052+
pub fn lsps5_liquidity(&self) -> Arc<LSPS5Liquidity> {
1053+
Arc::new(LSPS5Liquidity::new(
1054+
Arc::clone(&self.runtime),
1055+
Arc::clone(&self.connection_manager),
1056+
self.liquidity_source.clone(),
1057+
Arc::clone(&self.logger),
1058+
))
1059+
}
1060+
10351061
/// Retrieve a list of known channels.
10361062
pub fn list_channels(&self) -> Vec<ChannelDetails> {
10371063
self.channel_manager.list_channels().into_iter().map(|c| c.into()).collect()

0 commit comments

Comments
 (0)