Skip to content

Commit 49c19a4

Browse files
committed
Generate UniFFI scaffolding
We generate the scaffolding from an UDL file and include it in `lib.rs`. Furthermore, we add a bindings generation shell script for convenience.
1 parent 13f8c55 commit 49c19a4

File tree

12 files changed

+674
-61
lines changed

12 files changed

+674
-61
lines changed

Cargo.toml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,22 @@ description = "A ready-to-go node implementation built using LDK."
88

99
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1010

11+
[lib]
12+
crate-type = ["staticlib", "cdylib"]
13+
name = "ldk_node"
14+
15+
[[bin]]
16+
name = "uniffi-bindgen"
17+
path = "uniffi-bindgen.rs"
18+
19+
[profile.release-smaller]
20+
inherits = "release"
21+
opt-level = 'z' # Optimize for size.
22+
lto = true # Enable Link Time Optimization
23+
codegen-units = 1 # Reduce number of codegen units to increase optimizations.
24+
panic = 'abort' # Abort on panic
25+
strip = true # Strip symbols from binary*
26+
1127
[dependencies]
1228
#lightning = { version = "0.0.114", features = ["max_level_trace", "std"] }
1329
#lightning-invoice = { version = "0.22" }
@@ -53,13 +69,18 @@ serde_json = { version = "1.0" }
5369
tokio = { version = "1", default-features = false, features = [ "rt-multi-thread", "time", "sync" ] }
5470
esplora-client = { version = "0.4", default-features = false }
5571
libc = "0.2"
72+
uniffi = { version = "0.23.0", features = ["build"] }
5673

5774
[dev-dependencies]
5875
electrsd = { version = "0.22.0", features = ["legacy", "esplora_a33e97e1", "bitcoind_23_0"] }
5976
electrum-client = "0.12.0"
6077
proptest = "1.0.0"
6178
regex = "1.5.6"
6279

80+
[build-dependencies]
81+
uniffi = { version = "0.23.0", features = ["build", "cli"] }
82+
83+
6384
[profile.release]
6485
panic = "abort"
6586

bindings/ldk_node.udl

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
namespace ldk_node {
2+
};
3+
4+
dictionary Config {
5+
string storage_dir_path;
6+
string esplora_server_url;
7+
Network network;
8+
SocketAddr? listening_address;
9+
u32 default_cltv_expiry_delta;
10+
};
11+
12+
interface Builder {
13+
constructor();
14+
[Name=from_config]
15+
constructor(Config config);
16+
Node build();
17+
};
18+
19+
interface Node {
20+
[Throws=NodeError]
21+
void start();
22+
[Throws=NodeError]
23+
void stop();
24+
[Throws=NodeError]
25+
void sync_wallets();
26+
Event next_event();
27+
void event_handled();
28+
PublicKey node_id();
29+
[Throws=NodeError]
30+
Address new_funding_address();
31+
[Throws=NodeError]
32+
u64 spendable_onchain_balance_sats();
33+
[Throws=NodeError]
34+
u64 total_onchain_balance_sats();
35+
[Throws=NodeError]
36+
void connect_open_channel([ByRef]PublicKey pubkey, [ByRef]SocketAddr address, u64 channel_amount_sats, boolean announce_channel);
37+
[Throws=NodeError]
38+
void close_channel([ByRef]ChannelId channel_id, [ByRef]PublicKey counterparty_node_id);
39+
[Throws=NodeError]
40+
PaymentHash send_payment([ByRef]Invoice invoice);
41+
[Throws=NodeError]
42+
PaymentHash send_payment_using_amount([ByRef]Invoice invoice, u64 amount_msat);
43+
[Throws=NodeError]
44+
PaymentHash send_spontaneous_payment(u64 amount_msat, [ByRef]PublicKey node_id);
45+
[Throws=NodeError]
46+
Invoice receive_payment(u64 amount_msat, [ByRef]string description, u32 expiry_secs);
47+
[Throws=NodeError]
48+
Invoice receive_variable_amount_payment([ByRef]string description, u32 expiry_secs);
49+
PaymentInfo? payment_info([ByRef]PaymentHash payment_hash);
50+
};
51+
52+
[Error]
53+
enum NodeError {
54+
"AlreadyRunning",
55+
"NotRunning",
56+
"FundingTxCreationFailed",
57+
"ConnectionFailed",
58+
"AddressInvalid",
59+
"PublicKeyInvalid",
60+
"PaymentHashInvalid",
61+
"PaymentPreimageInvalid",
62+
"PaymentSecretInvalid",
63+
"NonUniquePaymentHash",
64+
"InvalidAmount",
65+
"InvalidInvoice",
66+
"InvoiceCreationFailed",
67+
"InsufficientFunds",
68+
"PaymentFailed",
69+
"ChannelIdInvalid",
70+
"NetworkInvalid",
71+
"PeerInfoParseFailed",
72+
"ChannelCreationFailed",
73+
"ChannelClosingFailed",
74+
"PersistenceFailed",
75+
"WalletOperationFailed",
76+
"WalletSigningFailed",
77+
"TxSyncFailed",
78+
};
79+
80+
[Enum]
81+
interface Event {
82+
PaymentSuccessful( PaymentHash payment_hash );
83+
PaymentFailed( PaymentHash payment_hash );
84+
PaymentReceived( PaymentHash payment_hash, u64 amount_msat);
85+
ChannelReady ( ChannelId channel_id, UserChannelId user_channel_id );
86+
ChannelClosed ( ChannelId channel_id, UserChannelId user_channel_id );
87+
};
88+
89+
enum PaymentDirection {
90+
"Inbound",
91+
"Outbound",
92+
};
93+
94+
enum PaymentStatus {
95+
"Pending",
96+
"Succeeded",
97+
"Failed",
98+
};
99+
100+
dictionary PaymentInfo {
101+
PaymentHash payment_hash;
102+
PaymentPreimage? preimage;
103+
PaymentSecret? secret;
104+
u64? amount_msat;
105+
PaymentDirection direction;
106+
PaymentStatus status;
107+
};
108+
109+
[Custom]
110+
typedef string SocketAddr;
111+
112+
[Custom]
113+
typedef string PublicKey;
114+
115+
[Custom]
116+
typedef string Address;
117+
118+
[Custom]
119+
typedef string Invoice;
120+
121+
[Custom]
122+
typedef string PaymentHash;
123+
124+
[Custom]
125+
typedef string PaymentPreimage;
126+
127+
[Custom]
128+
typedef string PaymentSecret;
129+
130+
[Custom]
131+
typedef string ChannelId;
132+
133+
[Custom]
134+
typedef string UserChannelId;
135+
136+
[Custom]
137+
typedef string Network;

build.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn main() {
2+
uniffi::generate_scaffolding("bindings/ldk_node.udl").unwrap();
3+
}

scripts/uniffi_bindgen_generate.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#!/bin/bash

src/error.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ pub enum Error {
1111
FundingTxCreationFailed,
1212
/// A network connection has been closed.
1313
ConnectionFailed,
14+
/// The given address is invalid.
15+
AddressInvalid,
16+
/// The given public key is invalid.
17+
PublicKeyInvalid,
18+
/// The given payment hash is invalid.
19+
PaymentHashInvalid,
20+
/// The given payment preimage is invalid.
21+
PaymentPreimageInvalid,
22+
/// The given payment secret is invalid.
23+
PaymentSecretInvalid,
1424
/// Payment of the given invoice has already been intiated.
1525
NonUniquePaymentHash,
1626
/// The given amount is invalid.
@@ -23,6 +33,10 @@ pub enum Error {
2333
InsufficientFunds,
2434
/// An attempted payment has failed.
2535
PaymentFailed,
36+
/// The given channel ID is invalid.
37+
ChannelIdInvalid,
38+
/// The given network is invalid.
39+
NetworkInvalid,
2640
/// A given peer info could not be parsed.
2741
PeerInfoParseFailed,
2842
/// A channel could not be opened.
@@ -44,10 +58,13 @@ impl fmt::Display for Error {
4458
match *self {
4559
Self::AlreadyRunning => write!(f, "Node is already running."),
4660
Self::NotRunning => write!(f, "Node is not running."),
47-
Self::FundingTxCreationFailed => {
48-
write!(f, "Funding transaction could not be created.")
49-
}
61+
Self::FundingTxCreationFailed => write!(f, "Funding transaction could not be created."),
5062
Self::ConnectionFailed => write!(f, "Network connection closed."),
63+
Self::AddressInvalid => write!(f, "The given address is invalid."),
64+
Self::PublicKeyInvalid => write!(f, "The given public key is invalid."),
65+
Self::PaymentHashInvalid => write!(f, "The given payment hash is invalid."),
66+
Self::PaymentPreimageInvalid => write!(f, "The given payment preimage is invalid."),
67+
Self::PaymentSecretInvalid => write!(f, "The given payment secret is invalid."),
5168
Self::NonUniquePaymentHash => write!(f, "An invoice must not get payed twice."),
5269
Self::InvalidAmount => write!(f, "The given amount is invalid."),
5370
Self::InvalidInvoice => write!(f, "The given invoice is invalid."),
@@ -56,6 +73,8 @@ impl fmt::Display for Error {
5673
write!(f, "There are insufficient funds to complete the given operation.")
5774
}
5875
Self::PaymentFailed => write!(f, "Failed to send the given payment."),
76+
Self::ChannelIdInvalid => write!(f, "The given channel ID is invalid."),
77+
Self::NetworkInvalid => write!(f, "The given network is invalid."),
5978
Self::PeerInfoParseFailed => write!(f, "Failed to parse the given peer information."),
6079
Self::ChannelCreationFailed => write!(f, "Failed to create channel."),
6180
Self::ChannelClosingFailed => write!(f, "Failed to close channel."),

src/event.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
2-
hex_utils, ChannelManager, Config, Error, KeysManager, NetworkGraph, PaymentDirection,
3-
PaymentInfo, PaymentInfoStorage, PaymentStatus, Wallet,
2+
hex_utils, ChannelId, ChannelManager, Config, Error, KeysManager, NetworkGraph,
3+
PaymentDirection, PaymentInfo, PaymentInfoStorage, PaymentStatus, UserChannelId, Wallet,
44
};
55

66
use crate::io::{KVStore, EVENT_QUEUE_PERSISTENCE_KEY, EVENT_QUEUE_PERSISTENCE_NAMESPACE};
@@ -48,16 +48,16 @@ pub enum Event {
4848
/// A channel is ready to be used.
4949
ChannelReady {
5050
/// The `channel_id` of the channel.
51-
channel_id: [u8; 32],
51+
channel_id: ChannelId,
5252
/// The `user_channel_id` of the channel.
53-
user_channel_id: u128,
53+
user_channel_id: UserChannelId,
5454
},
5555
/// A channel has been closed.
5656
ChannelClosed {
5757
/// The `channel_id` of the channel.
58-
channel_id: [u8; 32],
58+
channel_id: ChannelId,
5959
/// The `user_channel_id` of the channel.
60-
user_channel_id: u128,
60+
user_channel_id: UserChannelId,
6161
},
6262
}
6363

@@ -562,7 +562,10 @@ where
562562
counterparty_node_id,
563563
);
564564
self.event_queue
565-
.add_event(Event::ChannelReady { channel_id, user_channel_id })
565+
.add_event(Event::ChannelReady {
566+
channel_id: ChannelId(channel_id),
567+
user_channel_id: UserChannelId(user_channel_id),
568+
})
566569
.expect("Failed to push to event queue");
567570
}
568571
LdkEvent::ChannelClosed { channel_id, reason, user_channel_id } => {
@@ -573,7 +576,10 @@ where
573576
reason
574577
);
575578
self.event_queue
576-
.add_event(Event::ChannelClosed { channel_id, user_channel_id })
579+
.add_event(Event::ChannelClosed {
580+
channel_id: ChannelId(channel_id),
581+
user_channel_id: UserChannelId(user_channel_id),
582+
})
577583
.expect("Failed to push to event queue");
578584
}
579585
LdkEvent::DiscardFunding { .. } => {}
@@ -593,7 +599,10 @@ mod tests {
593599
let logger = Arc::new(TestLogger::new());
594600
let event_queue = EventQueue::new(Arc::clone(&store), Arc::clone(&logger));
595601

596-
let expected_event = Event::ChannelReady { channel_id: [23u8; 32], user_channel_id: 2323 };
602+
let expected_event = Event::ChannelReady {
603+
channel_id: ChannelId([23u8; 32]),
604+
user_channel_id: UserChannelId(2323),
605+
};
597606
event_queue.add_event(expected_event.clone()).unwrap();
598607
assert!(store.get_and_clear_did_persist());
599608

0 commit comments

Comments
 (0)