Skip to content

Commit a2593ae

Browse files
committed
Add Uniffi bindings for LSPS1 API
1 parent 8423917 commit a2593ae

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",
@@ -410,6 +421,59 @@ dictionary CustomTlvRecord {
410421
sequence<u8> value;
411422
};
412423

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

657721
[Custom]
658722
typedef string NodeAlias;
723+
724+
[Custom]
725+
typedef string OrderId;
726+
727+
[Custom]
728+
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

@@ -885,6 +883,67 @@ pub struct LSPS1OrderStatus {
885883
pub channel_state: Option<ChannelInfo>,
886884
}
887885

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

@@ -30,12 +31,19 @@ pub use lightning_types::payment::{PaymentHash, PaymentPreimage, PaymentSecret};
3031

3132
pub use lightning_invoice::{Bolt11Invoice, Description};
3233

34+
pub use lightning_liquidity::lsps1::msgs::ChannelInfo as ChannelOrderInfo;
35+
pub use lightning_liquidity::lsps1::msgs::{
36+
Bolt11PaymentInfo, OrderId, OrderParameters, PaymentState,
37+
};
38+
3339
pub use bitcoin::{Address, BlockHash, FeeRate, Network, OutPoint, Txid};
3440

3541
pub use bip39::Mnemonic;
3642

3743
pub use vss_client::headers::{VssHeaderProvider, VssHeaderProviderError};
3844

45+
pub type DateTime = chrono::DateTime<chrono::Utc>;
46+
3947
use crate::UniffiCustomTypeConverter;
4048

4149
use crate::builder::sanitize_alias;
@@ -393,6 +401,30 @@ impl From<lightning_invoice::Bolt11InvoiceDescription> for Bolt11InvoiceDescript
393401
}
394402
}
395403

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

0 commit comments

Comments
 (0)