Skip to content

Commit 20bb3b2

Browse files
committedFeb 6, 2025
Add Uniffi bindings for LSPS1 API
1 parent 4cc0a4a commit 20bb3b2

File tree

4 files changed

+172
-5
lines changed

4 files changed

+172
-5
lines changed
 

‎bindings/ldk_node.udl

+70
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ interface Builder {
5858
void set_chain_source_bitcoind_rpc(string rpc_host, u16 rpc_port, string rpc_user, string rpc_password);
5959
void set_gossip_source_p2p();
6060
void set_gossip_source_rgs(string rgs_server_url);
61+
void set_liquidity_source_lsps1(PublicKey node_id, SocketAddress address, string? token);
6162
void set_liquidity_source_lsps2(PublicKey node_id, SocketAddress address, string? token);
6263
void set_storage_dir_path(string storage_dir_path);
6364
void set_filesystem_logger(string? log_file_path, LogLevel? log_level);
@@ -100,6 +101,7 @@ interface Node {
100101
SpontaneousPayment spontaneous_payment();
101102
OnchainPayment onchain_payment();
102103
UnifiedQrPayment unified_qr_payment();
104+
LSPS1Liquidity lsps1_liquidity();
103105
[Throws=NodeError]
104106
void connect(PublicKey node_id, SocketAddress address, boolean persist);
105107
[Throws=NodeError]
@@ -211,6 +213,13 @@ interface UnifiedQrPayment {
211213
QrPaymentResult send([ByRef]string uri_str);
212214
};
213215

216+
interface LSPS1Liquidity {
217+
[Throws=NodeError]
218+
LSPS1OrderStatus request_channel(u64 lsp_balance_sat, u64 client_balance_sat, u32 channel_expiry_blocks, boolean announce_channel);
219+
[Throws=NodeError]
220+
LSPS1OrderStatus check_order_status(OrderId order_id);
221+
};
222+
214223
[Error]
215224
enum NodeError {
216225
"AlreadyRunning",
@@ -258,6 +267,8 @@ enum NodeError {
258267
"InvalidUri",
259268
"InvalidQuantity",
260269
"InvalidNodeAlias",
270+
"InvalidDateTime",
271+
"InvalidFeeRate",
261272
"DuplicatePayment",
262273
"UnsupportedCurrency",
263274
"InsufficientFunds",
@@ -416,6 +427,59 @@ dictionary CustomTlvRecord {
416427
sequence<u8> value;
417428
};
418429

430+
dictionary LSPS1OrderStatus {
431+
OrderId order_id;
432+
OrderParameters order_params;
433+
PaymentInfo payment_options;
434+
ChannelOrderInfo? channel_state;
435+
};
436+
437+
dictionary OrderParameters {
438+
u64 lsp_balance_sat;
439+
u64 client_balance_sat;
440+
u16 required_channel_confirmations;
441+
u16 funding_confirms_within_blocks;
442+
u32 channel_expiry_blocks;
443+
string? token;
444+
boolean announce_channel;
445+
};
446+
447+
dictionary PaymentInfo {
448+
Bolt11PaymentInfo? bolt11;
449+
OnchainPaymentInfo? onchain;
450+
};
451+
452+
dictionary Bolt11PaymentInfo {
453+
PaymentState state;
454+
DateTime expires_at;
455+
u64 fee_total_sat;
456+
u64 order_total_sat;
457+
Bolt11Invoice invoice;
458+
};
459+
460+
dictionary OnchainPaymentInfo {
461+
PaymentState state;
462+
DateTime expires_at;
463+
u64 fee_total_sat;
464+
u64 order_total_sat;
465+
Address address;
466+
u16? min_onchain_payment_confirmations;
467+
FeeRate min_fee_for_0conf;
468+
Address? refund_onchain_address;
469+
};
470+
471+
dictionary ChannelOrderInfo {
472+
DateTime funded_at;
473+
OutPoint funding_outpoint;
474+
DateTime expires_at;
475+
};
476+
477+
enum PaymentState {
478+
"ExpectPayment",
479+
"Paid",
480+
"Refunded",
481+
};
482+
419483
[Enum]
420484
interface MaxTotalRoutingFeeLimit {
421485
None ();
@@ -662,3 +726,9 @@ typedef string UntrustedString;
662726

663727
[Custom]
664728
typedef string NodeAlias;
729+
730+
[Custom]
731+
typedef string OrderId;
732+
733+
[Custom]
734+
typedef string DateTime;

‎src/error.rs

+6
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ pub enum Error {
106106
InvalidQuantity,
107107
/// The given node alias is invalid.
108108
InvalidNodeAlias,
109+
/// The given date time is invalid.
110+
InvalidDateTime,
111+
/// The given fee rate is invalid.
112+
InvalidFeeRate,
109113
/// A payment with the given hash has already been initiated.
110114
DuplicatePayment,
111115
/// The provided offer was denonminated in an unsupported currency.
@@ -172,6 +176,8 @@ impl fmt::Display for Error {
172176
Self::InvalidUri => write!(f, "The given URI is invalid."),
173177
Self::InvalidQuantity => write!(f, "The given quantity is invalid."),
174178
Self::InvalidNodeAlias => write!(f, "The given node alias is invalid."),
179+
Self::InvalidDateTime => write!(f, "The given date time is invalid."),
180+
Self::InvalidFeeRate => write!(f, "The given fee rate is invalid."),
175181
Self::DuplicatePayment => {
176182
write!(f, "A payment with the given hash has already been initiated.")
177183
},

‎src/liquidity.rs

+64-5
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,7 @@ use lightning_liquidity::events::Event;
2121
use lightning_liquidity::lsps0::ser::RequestId;
2222
use lightning_liquidity::lsps1::client::LSPS1ClientConfig;
2323
use lightning_liquidity::lsps1::event::LSPS1ClientEvent;
24-
use lightning_liquidity::lsps1::msgs::{
25-
ChannelInfo, LSPS1Options, OrderId, OrderParameters, PaymentInfo,
26-
};
24+
use lightning_liquidity::lsps1::msgs::{ChannelInfo, LSPS1Options, OrderId, OrderParameters};
2725
use lightning_liquidity::lsps2::client::LSPS2ClientConfig;
2826
use lightning_liquidity::lsps2::event::LSPS2ClientEvent;
2927
use lightning_liquidity::lsps2::msgs::OpeningFeeParams;
@@ -280,7 +278,7 @@ where
280278
let response = LSPS1OrderStatus {
281279
order_id,
282280
order_params: order,
283-
payment_options: payment,
281+
payment_options: payment.into(),
284282
channel_state: channel,
285283
};
286284

@@ -338,7 +336,7 @@ where
338336
let response = LSPS1OrderStatus {
339337
order_id,
340338
order_params: order,
341-
payment_options: payment,
339+
payment_options: payment.into(),
342340
channel_state: channel,
343341
};
344342

@@ -889,6 +887,67 @@ pub struct LSPS1OrderStatus {
889887
pub channel_state: Option<ChannelInfo>,
890888
}
891889

890+
#[cfg(not(feature = "uniffi"))]
891+
type PaymentInfo = lightning_liquidity::lsps1::msgs::PaymentInfo;
892+
893+
/// Details regarding how to pay for an order.
894+
#[cfg(feature = "uniffi")]
895+
#[derive(Clone, Debug, PartialEq, Eq)]
896+
pub struct PaymentInfo {
897+
/// A Lightning payment using BOLT 11.
898+
pub bolt11: Option<lightning_liquidity::lsps1::msgs::Bolt11PaymentInfo>,
899+
/// An onchain payment.
900+
pub onchain: Option<OnchainPaymentInfo>,
901+
}
902+
903+
#[cfg(feature = "uniffi")]
904+
impl From<lightning_liquidity::lsps1::msgs::PaymentInfo> for PaymentInfo {
905+
fn from(value: lightning_liquidity::lsps1::msgs::PaymentInfo) -> Self {
906+
PaymentInfo { bolt11: value.bolt11, onchain: value.onchain.map(|o| o.into()) }
907+
}
908+
}
909+
910+
/// An onchain payment.
911+
#[cfg(feature = "uniffi")]
912+
#[derive(Clone, Debug, PartialEq, Eq)]
913+
pub struct OnchainPaymentInfo {
914+
/// Indicates the current state of the payment.
915+
pub state: lightning_liquidity::lsps1::msgs::PaymentState,
916+
/// The datetime when the payment option expires.
917+
pub expires_at: chrono::DateTime<chrono::Utc>,
918+
/// The total fee the LSP will charge to open this channel in satoshi.
919+
pub fee_total_sat: u64,
920+
/// The amount the client needs to pay to have the requested channel openend.
921+
pub order_total_sat: u64,
922+
/// An on-chain address the client can send [`Self::order_total_sat`] to to have the channel
923+
/// opened.
924+
pub address: bitcoin::Address,
925+
/// The minimum number of block confirmations that are required for the on-chain payment to be
926+
/// considered confirmed.
927+
pub min_onchain_payment_confirmations: Option<u16>,
928+
/// The minimum fee rate for the on-chain payment in case the client wants the payment to be
929+
/// confirmed without a confirmation.
930+
pub min_fee_for_0conf: Arc<bitcoin::FeeRate>,
931+
/// The address where the LSP will send the funds if the order fails.
932+
pub refund_onchain_address: Option<bitcoin::Address>,
933+
}
934+
935+
#[cfg(feature = "uniffi")]
936+
impl From<lightning_liquidity::lsps1::msgs::OnchainPaymentInfo> for OnchainPaymentInfo {
937+
fn from(value: lightning_liquidity::lsps1::msgs::OnchainPaymentInfo) -> Self {
938+
Self {
939+
state: value.state,
940+
expires_at: value.expires_at,
941+
fee_total_sat: value.fee_total_sat,
942+
order_total_sat: value.order_total_sat,
943+
address: value.address,
944+
min_onchain_payment_confirmations: value.min_onchain_payment_confirmations,
945+
min_fee_for_0conf: Arc::new(value.min_fee_for_0conf),
946+
refund_onchain_address: value.refund_onchain_address,
947+
}
948+
}
949+
}
950+
892951
#[derive(Debug, Clone)]
893952
pub(crate) struct LSPS2FeeResponse {
894953
opening_fee_params_menu: Vec<OpeningFeeParams>,

‎src/uniffi_types.rs

+32
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub use crate::config::{
1414
default_config, AnchorChannelsConfig, EsploraSyncConfig, MaxDustHTLCExposure,
1515
};
1616
pub use crate::graph::{ChannelInfo, ChannelUpdateInfo, NodeAnnouncementInfo, NodeInfo};
17+
pub use crate::liquidity::{LSPS1OrderStatus, OnchainPaymentInfo, PaymentInfo};
1718
pub use crate::logger::{LogLevel, LogRecord, LogWriter};
1819
pub use crate::payment::store::{
1920
ConfirmationStatus, LSPFeeLimits, PaymentDirection, PaymentKind, PaymentStatus,
@@ -33,12 +34,19 @@ pub use lightning_types::payment::{PaymentHash, PaymentPreimage, PaymentSecret};
3334

3435
pub use lightning_invoice::{Bolt11Invoice, Description};
3536

37+
pub use lightning_liquidity::lsps1::msgs::ChannelInfo as ChannelOrderInfo;
38+
pub use lightning_liquidity::lsps1::msgs::{
39+
Bolt11PaymentInfo, OrderId, OrderParameters, PaymentState,
40+
};
41+
3642
pub use bitcoin::{Address, BlockHash, FeeRate, Network, OutPoint, Txid};
3743

3844
pub use bip39::Mnemonic;
3945

4046
pub use vss_client::headers::{VssHeaderProvider, VssHeaderProviderError};
4147

48+
pub type DateTime = chrono::DateTime<chrono::Utc>;
49+
4250
use crate::UniffiCustomTypeConverter;
4351

4452
use crate::builder::sanitize_alias;
@@ -396,6 +404,30 @@ impl From<lightning_invoice::Bolt11InvoiceDescription> for Bolt11InvoiceDescript
396404
}
397405
}
398406

407+
impl UniffiCustomTypeConverter for OrderId {
408+
type Builtin = String;
409+
410+
fn into_custom(val: Self::Builtin) -> uniffi::Result<Self> {
411+
Ok(Self(val))
412+
}
413+
414+
fn from_custom(obj: Self) -> Self::Builtin {
415+
obj.0
416+
}
417+
}
418+
419+
impl UniffiCustomTypeConverter for DateTime {
420+
type Builtin = String;
421+
422+
fn into_custom(val: Self::Builtin) -> uniffi::Result<Self> {
423+
Ok(DateTime::from_str(&val).map_err(|_| Error::InvalidDateTime)?)
424+
}
425+
426+
fn from_custom(obj: Self) -> Self::Builtin {
427+
obj.to_rfc3339()
428+
}
429+
}
430+
399431
#[cfg(test)]
400432
mod tests {
401433
use super::*;

0 commit comments

Comments
 (0)
Please sign in to comment.