Skip to content

Commit b7c4862

Browse files
authored
Merge pull request #270 from tnull/2024-03-payment-api-refactor
Refactor and modularize payment APIs
2 parents e14b70e + 1fab656 commit b7c4862

File tree

19 files changed

+1703
-1093
lines changed

19 files changed

+1703
-1093
lines changed

README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ A ready-to-go Lightning node library built using [LDK][ldk] and [BDK][bdk].
1111
LDK Node is a self-custodial Lightning node in library form. Its central goal is to provide a small, simple, and straightforward interface that enables users to easily set up and run a Lightning node with an integrated on-chain wallet. While minimalism is at its core, LDK Node aims to be sufficiently modular and configurable to be useful for a variety of use cases.
1212

1313
## Getting Started
14-
The primary abstraction of the library is the [`Node`][api_docs_node], which can be retrieved by setting up and configuring a [`Builder`][api_docs_builder] to your liking and calling one of the `build` methods. `Node` can then be controlled via commands such as `start`, `stop`, `connect_open_channel`, `send_payment`, etc.
14+
The primary abstraction of the library is the [`Node`][api_docs_node], which can be retrieved by setting up and configuring a [`Builder`][api_docs_builder] to your liking and calling one of the `build` methods. `Node` can then be controlled via commands such as `start`, `stop`, `connect_open_channel`, `send`, etc.
1515

1616
```rust
1717
use ldk_node::Builder;
@@ -31,7 +31,7 @@ fn main() {
3131

3232
node.start().unwrap();
3333

34-
let funding_address = node.new_onchain_address();
34+
let funding_address = node.onchain_payment().new_address();
3535

3636
// .. fund address ..
3737

@@ -44,7 +44,7 @@ fn main() {
4444
node.event_handled();
4545

4646
let invoice = Bolt11Invoice::from_str("INVOICE_STR").unwrap();
47-
node.send_payment(&invoice).unwrap();
47+
node.bolt11_payment().send(&invoice).unwrap();
4848

4949
node.stop().unwrap();
5050
}

bindings/kotlin/ldk-node-android/lib/src/androidTest/kotlin/org/lightningdevkit/ldknode/AndroidLibTest.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,10 @@ class AndroidLibTest {
5151
val nodeId2 = node2.nodeId()
5252
println("Node Id 2: $nodeId2")
5353

54-
val address1 = node1.newOnchainAddress()
54+
val address1 = node1.onchain_payment().newOnchainAddress()
5555
println("Funding address 1: $address1")
5656

57-
val address2 = node2.newOnchainAddress()
57+
val address2 = node2.onchain_payment().newOnchainAddress()
5858
println("Funding address 2: $address2")
5959

6060
node1.stop()

bindings/kotlin/ldk-node-jvm/lib/src/test/kotlin/org/lightningdevkit/ldknode/LibraryTest.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,10 @@ class LibraryTest {
146146
val nodeId2 = node2.nodeId()
147147
println("Node Id 2: $nodeId2")
148148

149-
val address1 = node1.newOnchainAddress()
149+
val address1 = node1.onchainPayment().newAddress()
150150
println("Funding address 1: $address1")
151151

152-
val address2 = node2.newOnchainAddress()
152+
val address2 = node2.onchainPayment().newAddress()
153153
println("Funding address 2: $address2")
154154

155155
val txid1 = sendToAddress(address1, 100000u)
@@ -222,9 +222,9 @@ class LibraryTest {
222222
else -> return
223223
}
224224

225-
val invoice = node2.receivePayment(2500000u, "asdf", 9217u)
225+
val invoice = node2.bolt11Payment().receive(2500000u, "asdf", 9217u)
226226

227-
node1.sendPayment(invoice)
227+
node1.bolt11Payment().send(invoice)
228228

229229
val paymentSuccessfulEvent = node1.waitNextEvent()
230230
println("Got event: $paymentSuccessfulEvent")

bindings/ldk_node.udl

+53-31
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,9 @@ interface Node {
5353
void event_handled();
5454
PublicKey node_id();
5555
sequence<SocketAddress>? listening_addresses();
56-
[Throws=NodeError]
57-
Address new_onchain_address();
58-
[Throws=NodeError]
59-
Txid send_to_onchain_address([ByRef]Address address, u64 amount_msat);
60-
[Throws=NodeError]
61-
Txid send_all_to_onchain_address([ByRef]Address address);
56+
Bolt11Payment bolt11_payment();
57+
SpontaneousPayment spontaneous_payment();
58+
OnchainPayment onchain_payment();
6259
[Throws=NodeError]
6360
void connect(PublicKey node_id, SocketAddress address, boolean persist);
6461
[Throws=NodeError]
@@ -71,36 +68,51 @@ interface Node {
7168
void update_channel_config([ByRef]UserChannelId user_channel_id, PublicKey counterparty_node_id, ChannelConfig channel_config);
7269
[Throws=NodeError]
7370
void sync_wallets();
71+
PaymentDetails? payment([ByRef]PaymentId payment_id);
7472
[Throws=NodeError]
75-
PaymentHash send_payment([ByRef]Bolt11Invoice invoice);
73+
void remove_payment([ByRef]PaymentId payment_id);
74+
BalanceDetails list_balances();
75+
sequence<PaymentDetails> list_payments();
76+
sequence<PeerDetails> list_peers();
77+
sequence<ChannelDetails> list_channels();
7678
[Throws=NodeError]
77-
PaymentHash send_payment_using_amount([ByRef]Bolt11Invoice invoice, u64 amount_msat);
79+
string sign_message([ByRef]sequence<u8> msg);
80+
boolean verify_signature([ByRef]sequence<u8> msg, [ByRef]string sig, [ByRef]PublicKey pkey);
81+
};
82+
83+
interface Bolt11Payment {
7884
[Throws=NodeError]
79-
PaymentHash send_spontaneous_payment(u64 amount_msat, PublicKey node_id);
85+
PaymentId send([ByRef]Bolt11Invoice invoice);
8086
[Throws=NodeError]
81-
void send_payment_probes([ByRef]Bolt11Invoice invoice);
87+
PaymentId send_using_amount([ByRef]Bolt11Invoice invoice, u64 amount_msat);
8288
[Throws=NodeError]
83-
void send_spontaneous_payment_probes(u64 amount_msat, PublicKey node_id);
89+
void send_probes([ByRef]Bolt11Invoice invoice);
8490
[Throws=NodeError]
85-
void send_payment_probes_using_amount([ByRef]Bolt11Invoice invoice, u64 amount_msat);
91+
void send_probes_using_amount([ByRef]Bolt11Invoice invoice, u64 amount_msat);
8692
[Throws=NodeError]
87-
Bolt11Invoice receive_payment(u64 amount_msat, [ByRef]string description, u32 expiry_secs);
93+
Bolt11Invoice receive(u64 amount_msat, [ByRef]string description, u32 expiry_secs);
8894
[Throws=NodeError]
89-
Bolt11Invoice receive_variable_amount_payment([ByRef]string description, u32 expiry_secs);
95+
Bolt11Invoice receive_variable_amount([ByRef]string description, u32 expiry_secs);
9096
[Throws=NodeError]
91-
Bolt11Invoice receive_payment_via_jit_channel(u64 amount_msat, [ByRef]string description, u32 expiry_secs, u64? max_lsp_fee_limit_msat);
97+
Bolt11Invoice receive_via_jit_channel(u64 amount_msat, [ByRef]string description, u32 expiry_secs, u64? max_lsp_fee_limit_msat);
9298
[Throws=NodeError]
93-
Bolt11Invoice receive_variable_amount_payment_via_jit_channel([ByRef]string description, u32 expiry_secs, u64? max_proportional_lsp_fee_limit_ppm_msat);
94-
PaymentDetails? payment([ByRef]PaymentHash payment_hash);
99+
Bolt11Invoice receive_variable_amount_via_jit_channel([ByRef]string description, u32 expiry_secs, u64? max_proportional_lsp_fee_limit_ppm_msat);
100+
};
101+
102+
interface SpontaneousPayment {
95103
[Throws=NodeError]
96-
void remove_payment([ByRef]PaymentHash payment_hash);
97-
BalanceDetails list_balances();
98-
sequence<PaymentDetails> list_payments();
99-
sequence<PeerDetails> list_peers();
100-
sequence<ChannelDetails> list_channels();
104+
PaymentId send(u64 amount_msat, PublicKey node_id);
101105
[Throws=NodeError]
102-
string sign_message([ByRef]sequence<u8> msg);
103-
boolean verify_signature([ByRef]sequence<u8> msg, [ByRef]string sig, [ByRef]PublicKey pkey);
106+
void send_probes(u64 amount_msat, PublicKey node_id);
107+
};
108+
109+
interface OnchainPayment {
110+
[Throws=NodeError]
111+
Address new_address();
112+
[Throws=NodeError]
113+
Txid send_to_address([ByRef]Address address, u64 amount_msat);
114+
[Throws=NodeError]
115+
Txid send_all_to_address([ByRef]Address address);
104116
};
105117

106118
[Error]
@@ -127,6 +139,7 @@ enum NodeError {
127139
"InvalidSocketAddress",
128140
"InvalidPublicKey",
129141
"InvalidSecretKey",
142+
"InvalidPaymentId",
130143
"InvalidPaymentHash",
131144
"InvalidPaymentPreimage",
132145
"InvalidPaymentSecret",
@@ -173,9 +186,9 @@ enum BuildError {
173186

174187
[Enum]
175188
interface Event {
176-
PaymentSuccessful(PaymentHash payment_hash, u64? fee_paid_msat);
177-
PaymentFailed(PaymentHash payment_hash, PaymentFailureReason? reason);
178-
PaymentReceived(PaymentHash payment_hash, u64 amount_msat);
189+
PaymentSuccessful(PaymentId? payment_id, PaymentHash payment_hash, u64? fee_paid_msat);
190+
PaymentFailed(PaymentId? payment_id, PaymentHash payment_hash, PaymentFailureReason? reason);
191+
PaymentReceived(PaymentId? payment_id, PaymentHash payment_hash, u64 amount_msat);
179192
ChannelPending(ChannelId channel_id, UserChannelId user_channel_id, ChannelId former_temporary_channel_id, PublicKey counterparty_node_id, OutPoint funding_txo);
180193
ChannelReady(ChannelId channel_id, UserChannelId user_channel_id, PublicKey? counterparty_node_id);
181194
ChannelClosed(ChannelId channel_id, UserChannelId user_channel_id, PublicKey? counterparty_node_id, ClosureReason? reason);
@@ -207,6 +220,14 @@ interface ClosureReason {
207220
HTLCsTimedOut();
208221
};
209222

223+
[Enum]
224+
interface PaymentKind {
225+
Onchain();
226+
Bolt11(PaymentHash hash, PaymentPreimage? preimage, PaymentSecret? secret);
227+
Bolt11Jit(PaymentHash hash, PaymentPreimage? preimage, PaymentSecret? secret, LSPFeeLimits lsp_fee_limits);
228+
Spontaneous(PaymentHash hash, PaymentPreimage? preimage);
229+
};
230+
210231
enum PaymentDirection {
211232
"Inbound",
212233
"Outbound",
@@ -224,13 +245,11 @@ dictionary LSPFeeLimits {
224245
};
225246

226247
dictionary PaymentDetails {
227-
PaymentHash hash;
228-
PaymentPreimage? preimage;
229-
PaymentSecret? secret;
248+
PaymentId id;
249+
PaymentKind kind;
230250
u64? amount_msat;
231251
PaymentDirection direction;
232252
PaymentStatus status;
233-
LSPFeeLimits? lsp_fee_limits;
234253
};
235254

236255
[NonExhaustive]
@@ -352,6 +371,9 @@ typedef string Address;
352371
[Custom]
353372
typedef string Bolt11Invoice;
354373

374+
[Custom]
375+
typedef string PaymentId;
376+
355377
[Custom]
356378
typedef string PaymentHash;
357379

bindings/python/src/ldk_node/test_ldk_node.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,9 @@ def test_channel_full_cycle(self):
125125
node_id_2 = node_2.node_id()
126126
print("Node ID 2:", node_id_2)
127127

128-
address_1 = node_1.new_onchain_address()
128+
address_1 = node_1.onchain_payment().new_address()
129129
txid_1 = send_to_address(address_1, 100000)
130-
address_2 = node_2.new_onchain_address()
130+
address_2 = node_2.onchain_payment().new_address()
131131
txid_2 = send_to_address(address_2, 100000)
132132

133133
wait_for_tx(esplora_endpoint, txid_1)
@@ -185,8 +185,8 @@ def test_channel_full_cycle(self):
185185
print("EVENT:", channel_ready_event_2)
186186
node_2.event_handled()
187187

188-
invoice = node_2.receive_payment(2500000, "asdf", 9217)
189-
node_1.send_payment(invoice)
188+
invoice = node_2.bolt11_payment().receive(2500000, "asdf", 9217)
189+
node_1.bolt11_payment().send(invoice)
190190

191191
payment_successful_event_1 = node_1.wait_next_event()
192192
assert isinstance(payment_successful_event_1, Event.PAYMENT_SUCCESSFUL)

src/builder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::io::sqlite_store::SqliteStore;
1111
use crate::liquidity::LiquiditySource;
1212
use crate::logger::{log_error, log_info, FilesystemLogger, Logger};
1313
use crate::message_handler::NodeCustomMessageHandler;
14-
use crate::payment_store::PaymentStore;
14+
use crate::payment::store::PaymentStore;
1515
use crate::peer_store::PeerStore;
1616
use crate::tx_broadcaster::TransactionBroadcaster;
1717
use crate::types::{

src/error.rs

+3
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ pub enum Error {
4747
InvalidPublicKey,
4848
/// The given secret key is invalid.
4949
InvalidSecretKey,
50+
/// The given payment id is invalid.
51+
InvalidPaymentId,
5052
/// The given payment hash is invalid.
5153
InvalidPaymentHash,
5254
/// The given payment pre-image is invalid.
@@ -100,6 +102,7 @@ impl fmt::Display for Error {
100102
Self::InvalidSocketAddress => write!(f, "The given network address is invalid."),
101103
Self::InvalidPublicKey => write!(f, "The given public key is invalid."),
102104
Self::InvalidSecretKey => write!(f, "The given secret key is invalid."),
105+
Self::InvalidPaymentId => write!(f, "The given payment id is invalid."),
103106
Self::InvalidPaymentHash => write!(f, "The given payment hash is invalid."),
104107
Self::InvalidPaymentPreimage => write!(f, "The given payment preimage is invalid."),
105108
Self::InvalidPaymentSecret => write!(f, "The given payment secret is invalid."),

0 commit comments

Comments
 (0)