Skip to content

Commit 9b48868

Browse files
committed
Add LSPS2 RPCs to ldk-server-protos and ldk-server
Expose dedicated LSPS2 invoice endpoints so callers can request fixed and variable-amount JIT invoices without overloading the existing `Bolt11Receive` API surface. Generated with the assistance of AI. Co-Authored-By: HAL 9000
1 parent 609547b commit 9b48868

6 files changed

Lines changed: 186 additions & 1 deletion

File tree

ldk-server-protos/src/api.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,70 @@ pub struct Bolt11FailForHashRequest {
259259
#[allow(clippy::derive_partial_eq_without_eq)]
260260
#[derive(Clone, PartialEq, ::prost::Message)]
261261
pub struct Bolt11FailForHashResponse {}
262+
/// Return a BOLT11 payable invoice that can be used to request and receive a payment via an
263+
/// LSPS2 just-in-time channel.
264+
/// See more: <https://docs.rs/ldk-node/latest/ldk_node/payment/struct.Bolt11Payment.html#method.receive_via_jit_channel>
265+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
266+
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
267+
#[allow(clippy::derive_partial_eq_without_eq)]
268+
#[derive(Clone, PartialEq, ::prost::Message)]
269+
pub struct Bolt11ReceiveViaJitChannelRequest {
270+
/// The amount in millisatoshi to request.
271+
#[prost(uint64, tag = "1")]
272+
pub amount_msat: u64,
273+
/// An optional description to attach along with the invoice.
274+
/// Will be set in the description field of the encoded payment request.
275+
#[prost(message, optional, tag = "2")]
276+
pub description: ::core::option::Option<super::types::Bolt11InvoiceDescription>,
277+
/// Invoice expiry time in seconds.
278+
#[prost(uint32, tag = "3")]
279+
pub expiry_secs: u32,
280+
/// Optional upper bound for the total fee an LSP may deduct when opening the JIT channel.
281+
#[prost(uint64, optional, tag = "4")]
282+
pub max_total_lsp_fee_limit_msat: ::core::option::Option<u64>,
283+
}
284+
/// The response `content` for the `Bolt11ReceiveViaJitChannel` API, when HttpStatusCode is OK (200).
285+
/// When HttpStatusCode is not OK (non-200), the response `content` contains a serialized `ErrorResponse`.
286+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
287+
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
288+
#[allow(clippy::derive_partial_eq_without_eq)]
289+
#[derive(Clone, PartialEq, ::prost::Message)]
290+
pub struct Bolt11ReceiveViaJitChannelResponse {
291+
/// An invoice for a payment within the Lightning Network.
292+
#[prost(string, tag = "1")]
293+
pub invoice: ::prost::alloc::string::String,
294+
}
295+
/// Return a variable-amount BOLT11 invoice that can be used to receive a payment via an LSPS2
296+
/// just-in-time channel.
297+
/// See more: <https://docs.rs/ldk-node/latest/ldk_node/payment/struct.Bolt11Payment.html#method.receive_variable_amount_via_jit_channel>
298+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
299+
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
300+
#[allow(clippy::derive_partial_eq_without_eq)]
301+
#[derive(Clone, PartialEq, ::prost::Message)]
302+
pub struct Bolt11ReceiveVariableAmountViaJitChannelRequest {
303+
/// An optional description to attach along with the invoice.
304+
/// Will be set in the description field of the encoded payment request.
305+
#[prost(message, optional, tag = "1")]
306+
pub description: ::core::option::Option<super::types::Bolt11InvoiceDescription>,
307+
/// Invoice expiry time in seconds.
308+
#[prost(uint32, tag = "2")]
309+
pub expiry_secs: u32,
310+
/// Optional upper bound for the proportional fee, in parts-per-million millisatoshis, that an
311+
/// LSP may deduct when opening the JIT channel.
312+
#[prost(uint64, optional, tag = "3")]
313+
pub max_proportional_lsp_fee_limit_ppm_msat: ::core::option::Option<u64>,
314+
}
315+
/// The response `content` for the `Bolt11ReceiveVariableAmountViaJitChannel` API, when HttpStatusCode is OK (200).
316+
/// When HttpStatusCode is not OK (non-200), the response `content` contains a serialized `ErrorResponse`.
317+
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
318+
#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))]
319+
#[allow(clippy::derive_partial_eq_without_eq)]
320+
#[derive(Clone, PartialEq, ::prost::Message)]
321+
pub struct Bolt11ReceiveVariableAmountViaJitChannelResponse {
322+
/// An invoice for a payment within the Lightning Network.
323+
#[prost(string, tag = "1")]
324+
pub invoice: ::prost::alloc::string::String,
325+
}
262326
/// Send a payment for a BOLT11 invoice.
263327
/// See more: <https://docs.rs/ldk-node/latest/ldk_node/payment/struct.Bolt11Payment.html#method.send>
264328
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]

ldk-server-protos/src/endpoints.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ pub const BOLT11_RECEIVE_PATH: &str = "Bolt11Receive";
1515
pub const BOLT11_RECEIVE_FOR_HASH_PATH: &str = "Bolt11ReceiveForHash";
1616
pub const BOLT11_CLAIM_FOR_HASH_PATH: &str = "Bolt11ClaimForHash";
1717
pub const BOLT11_FAIL_FOR_HASH_PATH: &str = "Bolt11FailForHash";
18+
pub const BOLT11_RECEIVE_VIA_JIT_CHANNEL_PATH: &str = "Bolt11ReceiveViaJitChannel";
19+
pub const BOLT11_RECEIVE_VARIABLE_AMOUNT_VIA_JIT_CHANNEL_PATH: &str =
20+
"Bolt11ReceiveVariableAmountViaJitChannel";
1821
pub const BOLT11_SEND_PATH: &str = "Bolt11Send";
1922
pub const BOLT12_RECEIVE_PATH: &str = "Bolt12Receive";
2023
pub const BOLT12_SEND_PATH: &str = "Bolt12Send";

ldk-server-protos/src/proto/api.proto

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,59 @@ message Bolt11FailForHashRequest {
215215
// When HttpStatusCode is not OK (non-200), the response `content` contains a serialized `ErrorResponse`.
216216
message Bolt11FailForHashResponse {}
217217

218+
// Return a BOLT11 payable invoice that can be used to request and receive a payment via an
219+
// LSPS2 just-in-time channel.
220+
// See more: https://docs.rs/ldk-node/latest/ldk_node/payment/struct.Bolt11Payment.html#method.receive_via_jit_channel
221+
message Bolt11ReceiveViaJitChannelRequest {
222+
223+
// The amount in millisatoshi to request.
224+
uint64 amount_msat = 1;
225+
226+
// An optional description to attach along with the invoice.
227+
// Will be set in the description field of the encoded payment request.
228+
types.Bolt11InvoiceDescription description = 2;
229+
230+
// Invoice expiry time in seconds.
231+
uint32 expiry_secs = 3;
232+
233+
// Optional upper bound for the total fee an LSP may deduct when opening the JIT channel.
234+
optional uint64 max_total_lsp_fee_limit_msat = 4;
235+
}
236+
237+
// The response `content` for the `Bolt11ReceiveViaJitChannel` API, when HttpStatusCode is OK (200).
238+
// When HttpStatusCode is not OK (non-200), the response `content` contains a serialized `ErrorResponse`.
239+
message Bolt11ReceiveViaJitChannelResponse {
240+
241+
// An invoice for a payment within the Lightning Network.
242+
string invoice = 1;
243+
}
244+
245+
// Return a variable-amount BOLT11 invoice that can be used to receive a payment via an LSPS2
246+
// just-in-time channel.
247+
// See more: https://docs.rs/ldk-node/latest/ldk_node/payment/struct.Bolt11Payment.html#method.receive_variable_amount_via_jit_channel
248+
message Bolt11ReceiveVariableAmountViaJitChannelRequest {
249+
250+
// An optional description to attach along with the invoice.
251+
// Will be set in the description field of the encoded payment request.
252+
types.Bolt11InvoiceDescription description = 1;
253+
254+
// Invoice expiry time in seconds.
255+
uint32 expiry_secs = 2;
256+
257+
// Optional upper bound for the proportional fee, in parts-per-million millisatoshis, that an
258+
// LSP may deduct when opening the JIT channel.
259+
optional uint64 max_proportional_lsp_fee_limit_ppm_msat = 3;
260+
}
261+
262+
// The response `content` for the `Bolt11ReceiveVariableAmountViaJitChannel` API, when HttpStatusCode is OK (200).
263+
// When HttpStatusCode is not OK (non-200), the response `content` contains a serialized `ErrorResponse`.
264+
message Bolt11ReceiveVariableAmountViaJitChannelResponse {
265+
266+
// An invoice for a payment within the Lightning Network.
267+
string invoice = 1;
268+
}
269+
270+
218271
// Send a payment for a BOLT11 invoice.
219272
// See more: https://docs.rs/ldk-node/latest/ldk_node/payment/struct.Bolt11Payment.html#method.send
220273
message Bolt11SendRequest {
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// This file is Copyright its original authors, visible in version control
2+
// history.
3+
//
4+
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
5+
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
7+
// You may not use this file except in accordance with one or both of these
8+
// licenses.
9+
10+
use ldk_server_protos::api::{
11+
Bolt11ReceiveVariableAmountViaJitChannelRequest,
12+
Bolt11ReceiveVariableAmountViaJitChannelResponse, Bolt11ReceiveViaJitChannelRequest,
13+
Bolt11ReceiveViaJitChannelResponse,
14+
};
15+
16+
use crate::api::error::LdkServerError;
17+
use crate::service::Context;
18+
use crate::util::proto_adapter::proto_to_bolt11_description;
19+
20+
pub(crate) fn handle_bolt11_receive_via_jit_channel_request(
21+
context: Context, request: Bolt11ReceiveViaJitChannelRequest,
22+
) -> Result<Bolt11ReceiveViaJitChannelResponse, LdkServerError> {
23+
let description = proto_to_bolt11_description(request.description)?;
24+
let invoice = context.node.bolt11_payment().receive_via_jit_channel(
25+
request.amount_msat,
26+
&description,
27+
request.expiry_secs,
28+
request.max_total_lsp_fee_limit_msat,
29+
)?;
30+
31+
Ok(Bolt11ReceiveViaJitChannelResponse { invoice: invoice.to_string() })
32+
}
33+
34+
pub(crate) fn handle_bolt11_receive_variable_amount_via_jit_channel_request(
35+
context: Context, request: Bolt11ReceiveVariableAmountViaJitChannelRequest,
36+
) -> Result<Bolt11ReceiveVariableAmountViaJitChannelResponse, LdkServerError> {
37+
let description = proto_to_bolt11_description(request.description)?;
38+
let invoice = context.node.bolt11_payment().receive_variable_amount_via_jit_channel(
39+
&description,
40+
request.expiry_secs,
41+
request.max_proportional_lsp_fee_limit_ppm_msat,
42+
)?;
43+
44+
Ok(Bolt11ReceiveVariableAmountViaJitChannelResponse { invoice: invoice.to_string() })
45+
}

ldk-server/src/api/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub(crate) mod bolt11_claim_for_hash;
1818
pub(crate) mod bolt11_fail_for_hash;
1919
pub(crate) mod bolt11_receive;
2020
pub(crate) mod bolt11_receive_for_hash;
21+
pub(crate) mod bolt11_receive_via_jit_channel;
2122
pub(crate) mod bolt11_send;
2223
pub(crate) mod bolt12_receive;
2324
pub(crate) mod bolt12_send;

ldk-server/src/service.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ use ldk_node::bitcoin::hashes::{sha256, Hash, HashEngine};
2020
use ldk_node::Node;
2121
use ldk_server_protos::endpoints::{
2222
BOLT11_CLAIM_FOR_HASH_PATH, BOLT11_FAIL_FOR_HASH_PATH, BOLT11_RECEIVE_FOR_HASH_PATH,
23-
BOLT11_RECEIVE_PATH, BOLT11_SEND_PATH, BOLT12_RECEIVE_PATH, BOLT12_SEND_PATH,
23+
BOLT11_RECEIVE_PATH, BOLT11_RECEIVE_VARIABLE_AMOUNT_VIA_JIT_CHANNEL_PATH,
24+
BOLT11_RECEIVE_VIA_JIT_CHANNEL_PATH, BOLT11_SEND_PATH, BOLT12_RECEIVE_PATH, BOLT12_SEND_PATH,
2425
CLOSE_CHANNEL_PATH, CONNECT_PEER_PATH, DISCONNECT_PEER_PATH, EXPORT_PATHFINDING_SCORES_PATH,
2526
FORCE_CLOSE_CHANNEL_PATH, GET_BALANCES_PATH, GET_NODE_INFO_PATH, GET_PAYMENT_DETAILS_PATH,
2627
GRAPH_GET_CHANNEL_PATH, GRAPH_GET_NODE_PATH, GRAPH_LIST_CHANNELS_PATH, GRAPH_LIST_NODES_PATH,
@@ -34,6 +35,10 @@ use crate::api::bolt11_claim_for_hash::handle_bolt11_claim_for_hash_request;
3435
use crate::api::bolt11_fail_for_hash::handle_bolt11_fail_for_hash_request;
3536
use crate::api::bolt11_receive::handle_bolt11_receive_request;
3637
use crate::api::bolt11_receive_for_hash::handle_bolt11_receive_for_hash_request;
38+
use crate::api::bolt11_receive_via_jit_channel::{
39+
handle_bolt11_receive_variable_amount_via_jit_channel_request,
40+
handle_bolt11_receive_via_jit_channel_request,
41+
};
3742
use crate::api::bolt11_send::handle_bolt11_send_request;
3843
use crate::api::bolt12_receive::handle_bolt12_receive_request;
3944
use crate::api::bolt12_send::handle_bolt12_send_request;
@@ -243,6 +248,20 @@ impl Service<Request<Incoming>> for NodeService {
243248
api_key,
244249
handle_bolt11_fail_for_hash_request,
245250
)),
251+
BOLT11_RECEIVE_VIA_JIT_CHANNEL_PATH => Box::pin(handle_request(
252+
context,
253+
req,
254+
auth_params,
255+
api_key,
256+
handle_bolt11_receive_via_jit_channel_request,
257+
)),
258+
BOLT11_RECEIVE_VARIABLE_AMOUNT_VIA_JIT_CHANNEL_PATH => Box::pin(handle_request(
259+
context,
260+
req,
261+
auth_params,
262+
api_key,
263+
handle_bolt11_receive_variable_amount_via_jit_channel_request,
264+
)),
246265
BOLT11_SEND_PATH => Box::pin(handle_request(
247266
context,
248267
req,

0 commit comments

Comments
 (0)