Skip to content

Commit 1d702ed

Browse files
authored
Merge pull request #5 from G8XSU/impl-s1-apis
Implement first set of Api's
2 parents 06f986c + 92d3361 commit 1d702ed

15 files changed

+228
-19
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

protos/src/lib.rs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,15 +87,8 @@ pub struct Bolt11SendRequest {
8787
#[derive(Clone, PartialEq, ::prost::Message)]
8888
pub struct Bolt11SendResponse {
8989
/// An identifier used to uniquely identify a payment.
90-
#[prost(message, optional, tag = "1")]
91-
pub payment_id: ::core::option::Option<PaymentId>,
92-
}
93-
/// An identifier used to uniquely identify a payment.
94-
#[allow(clippy::derive_partial_eq_without_eq)]
95-
#[derive(Clone, PartialEq, ::prost::Message)]
96-
pub struct PaymentId {
9790
#[prost(bytes = "bytes", tag = "1")]
98-
pub data: ::prost::bytes::Bytes,
91+
pub payment_id: ::prost::bytes::Bytes,
9992
}
10093
/// Returns a BOLT12 offer for the given amount, if specified.
10194
///
@@ -148,8 +141,8 @@ pub struct Bolt12SendRequest {
148141
#[derive(Clone, PartialEq, ::prost::Message)]
149142
pub struct Bolt12SendResponse {
150143
/// An identifier used to uniquely identify a payment.
151-
#[prost(message, optional, tag = "1")]
152-
pub payment_id: ::core::option::Option<PaymentId>,
144+
#[prost(bytes = "bytes", tag = "1")]
145+
pub payment_id: ::prost::bytes::Bytes,
153146
}
154147
/// Creates a new outbound channel to the given remote node.
155148
/// See more: <https://docs.rs/ldk-node/latest/ldk_node/struct.Node.html#method.connect_open_channel>

protos/src/proto/ldk_node_server.proto

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,7 @@ message Bolt11SendRequest {
8585
message Bolt11SendResponse {
8686

8787
// An identifier used to uniquely identify a payment.
88-
PaymentId payment_id = 1;
89-
}
90-
91-
// An identifier used to uniquely identify a payment.
92-
message PaymentId {
93-
94-
bytes data = 1;
88+
bytes payment_id = 1;
9589
}
9690

9791
// Returns a BOLT12 offer for the given amount, if specified.
@@ -141,7 +135,7 @@ message Bolt12SendRequest {
141135
message Bolt12SendResponse {
142136

143137
// An identifier used to uniquely identify a payment.
144-
PaymentId payment_id = 1;
138+
bytes payment_id = 1;
145139
}
146140

147141
// Creates a new outbound channel to the given remote node.

server/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ hyper-util = { version = "0.1", default-features = false, features = ["server-gr
1313
tokio = { version = "1.38.0", default-features = false, features = ["time", "signal", "rt-multi-thread"] }
1414
prost = { version = "0.11.6", default-features = false, features = ["std"] }
1515
protos = { path = "../protos" }
16+
bytes = "1.4.0"

server/src/api/bolt11_receive.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
use ldk_node::Node;
2+
use protos::{Bolt11ReceiveRequest, Bolt11ReceiveResponse};
3+
use std::sync::Arc;
4+
5+
pub(crate) const BOLT11_RECEIVE_PATH: &str = "Bolt11Receive";
6+
7+
pub(crate) fn handle_bolt11_receive_request(
8+
node: Arc<Node>, request: Bolt11ReceiveRequest,
9+
) -> Result<Bolt11ReceiveResponse, ldk_node::NodeError> {
10+
let invoice = match request.amount_msat {
11+
Some(amount_msat) => {
12+
node.bolt11_payment().receive(amount_msat, &request.description, request.expiry_secs)?
13+
},
14+
None => node
15+
.bolt11_payment()
16+
.receive_variable_amount(&request.description, request.expiry_secs)?,
17+
};
18+
19+
let response = Bolt11ReceiveResponse { invoice: invoice.to_string() };
20+
Ok(response)
21+
}

server/src/api/bolt11_send.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use bytes::Bytes;
2+
use ldk_node::lightning_invoice::Bolt11Invoice;
3+
use ldk_node::Node;
4+
use protos::{Bolt11SendRequest, Bolt11SendResponse};
5+
use std::str::FromStr;
6+
use std::sync::Arc;
7+
8+
pub(crate) const BOLT11_SEND_PATH: &str = "Bolt11Send";
9+
10+
pub(crate) fn handle_bolt11_send_request(
11+
node: Arc<Node>, request: Bolt11SendRequest,
12+
) -> Result<Bolt11SendResponse, ldk_node::NodeError> {
13+
let invoice = Bolt11Invoice::from_str(&request.invoice.as_str())
14+
.map_err(|_| ldk_node::NodeError::InvalidInvoice)?;
15+
16+
let payment_id = match request.amount_msat {
17+
None => node.bolt11_payment().send(&invoice),
18+
Some(amount_msat) => node.bolt11_payment().send_using_amount(&invoice, amount_msat),
19+
}?;
20+
21+
let response = Bolt11SendResponse { payment_id: Bytes::from(payment_id.0.to_vec()) };
22+
Ok(response)
23+
}

server/src/api/bolt12_receive.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use ldk_node::Node;
2+
use protos::{Bolt12ReceiveRequest, Bolt12ReceiveResponse};
3+
use std::sync::Arc;
4+
5+
pub(crate) const BOLT12_RECEIVE_PATH: &str = "Bolt12Receive";
6+
7+
pub(crate) fn handle_bolt12_receive_request(
8+
node: Arc<Node>, request: Bolt12ReceiveRequest,
9+
) -> Result<Bolt12ReceiveResponse, ldk_node::NodeError> {
10+
let offer = match request.amount_msat {
11+
Some(amount_msat) => node.bolt12_payment().receive(amount_msat, &request.description)?,
12+
None => node.bolt12_payment().receive_variable_amount(&request.description)?,
13+
};
14+
15+
let response = Bolt12ReceiveResponse { offer: offer.to_string() };
16+
Ok(response)
17+
}

server/src/api/bolt12_send.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use bytes::Bytes;
2+
use ldk_node::lightning::offers::offer::Offer;
3+
use ldk_node::Node;
4+
use protos::{Bolt12SendRequest, Bolt12SendResponse};
5+
use std::str::FromStr;
6+
use std::sync::Arc;
7+
8+
pub(crate) const BOLT12_SEND_PATH: &str = "Bolt12Send";
9+
10+
pub(crate) fn handle_bolt12_send_request(
11+
node: Arc<Node>, request: Bolt12SendRequest,
12+
) -> Result<Bolt12SendResponse, ldk_node::NodeError> {
13+
let offer =
14+
Offer::from_str(&request.offer.as_str()).map_err(|_| ldk_node::NodeError::InvalidOffer)?;
15+
16+
let payment_id = match request.amount_msat {
17+
None => node.bolt12_payment().send(&offer, request.payer_note),
18+
Some(amount_msat) => {
19+
node.bolt12_payment().send_using_amount(&offer, request.payer_note, amount_msat)
20+
},
21+
}?;
22+
23+
let response = Bolt12SendResponse { payment_id: Bytes::from(payment_id.0.to_vec()) };
24+
Ok(response)
25+
}

server/src/api/close_channel.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use ldk_node::bitcoin::secp256k1::PublicKey;
2+
use ldk_node::{Node, UserChannelId};
3+
use protos::{CloseChannelRequest, CloseChannelResponse};
4+
use std::str::FromStr;
5+
use std::sync::Arc;
6+
7+
pub(crate) const CLOSE_CHANNEL_PATH: &str = "CloseChannel";
8+
9+
pub(crate) fn handle_close_channel_request(
10+
node: Arc<Node>, request: CloseChannelRequest,
11+
) -> Result<CloseChannelResponse, ldk_node::NodeError> {
12+
//TODO: Should this be string?
13+
let mut user_channel_id_bytes = [0u8; 16];
14+
user_channel_id_bytes.copy_from_slice(&request.user_channel_id);
15+
let user_channel_id = UserChannelId(u128::from_be_bytes(user_channel_id_bytes));
16+
let counterparty_node_id = PublicKey::from_str(&request.counterparty_node_id)
17+
.map_err(|_| ldk_node::NodeError::InvalidPublicKey)?;
18+
19+
match request.force_close {
20+
Some(true) => node.force_close_channel(&user_channel_id, counterparty_node_id)?,
21+
_ => node.close_channel(&user_channel_id, counterparty_node_id)?,
22+
};
23+
24+
let response = CloseChannelResponse {};
25+
Ok(response)
26+
}

server/src/api/mod.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
pub(crate) mod bolt11_receive;
2+
pub(crate) mod bolt11_send;
3+
pub(crate) mod bolt12_receive;
4+
pub(crate) mod bolt12_send;
5+
pub(crate) mod close_channel;
6+
pub(crate) mod onchain_receive;
7+
pub(crate) mod onchain_send;
8+
pub(crate) mod open_channel;

server/src/api/onchain_receive.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use ldk_node::Node;
2+
use protos::{OnchainReceiveRequest, OnchainReceiveResponse};
3+
use std::sync::Arc;
4+
5+
pub(crate) const ONCHAIN_RECEIVE_PATH: &str = "OnchainReceive";
6+
pub(crate) fn handle_onchain_receive_request(
7+
node: Arc<Node>, _request: OnchainReceiveRequest,
8+
) -> Result<OnchainReceiveResponse, ldk_node::NodeError> {
9+
let response =
10+
OnchainReceiveResponse { address: node.onchain_payment().new_address()?.to_string() };
11+
Ok(response)
12+
}

server/src/api/onchain_send.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use ldk_node::bitcoin::Address;
2+
use ldk_node::Node;
3+
use protos::{OnchainSendRequest, OnchainSendResponse};
4+
use std::str::FromStr;
5+
use std::sync::Arc;
6+
7+
pub(crate) const ONCHAIN_SEND_PATH: &str = "OnchainSend";
8+
9+
pub(crate) fn handle_onchain_send_request(
10+
node: Arc<Node>, request: OnchainSendRequest,
11+
) -> Result<OnchainSendResponse, ldk_node::NodeError> {
12+
let address = Address::from_str(&request.address)
13+
.map_err(|_| ldk_node::NodeError::InvalidAddress)?
14+
.require_network(node.config().network)
15+
.map_err(|_| ldk_node::NodeError::InvalidAddress)?;
16+
let txid = match (request.amount_sats, request.send_all) {
17+
(Some(amount_sats), None) => {
18+
node.onchain_payment().send_to_address(&address, amount_sats)?
19+
},
20+
(None, Some(true)) => node.onchain_payment().send_all_to_address(&address)?,
21+
_ => return Err(ldk_node::NodeError::InvalidAmount),
22+
};
23+
let response = OnchainSendResponse { txid: txid.to_string() };
24+
Ok(response)
25+
}

server/src/api/open_channel.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
use bytes::Bytes;
2+
use ldk_node::bitcoin::secp256k1::PublicKey;
3+
use ldk_node::lightning::ln::msgs::SocketAddress;
4+
use ldk_node::Node;
5+
use protos::{OpenChannelRequest, OpenChannelResponse};
6+
use std::str::FromStr;
7+
use std::sync::Arc;
8+
9+
pub(crate) const OPEN_CHANNEL_PATH: &str = "OpenChannel";
10+
11+
pub(crate) fn handle_open_channel(
12+
node: Arc<Node>, request: OpenChannelRequest,
13+
) -> Result<OpenChannelResponse, ldk_node::NodeError> {
14+
let node_id = PublicKey::from_str(&request.node_pubkey)
15+
.map_err(|_| ldk_node::NodeError::InvalidPublicKey)?;
16+
let address = SocketAddress::from_str(&request.address)
17+
.map_err(|_| ldk_node::NodeError::InvalidSocketAddress)?;
18+
let user_channel_id = node.connect_open_channel(
19+
node_id,
20+
address,
21+
request.channel_amount_sats,
22+
request.push_to_counterparty_msat,
23+
// TODO: Allow setting ChannelConfig in open-channel.
24+
None,
25+
request.announce_channel,
26+
)?;
27+
let response = OpenChannelResponse {
28+
user_channel_id: Bytes::from(user_channel_id.0.to_be_bytes().to_vec()),
29+
};
30+
Ok(response)
31+
}

server/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
mod api;
12
mod service;
23

34
use crate::service::NodeService;

server/src/service.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,23 @@ use std::future::Future;
1111
use std::pin::Pin;
1212
use std::sync::Arc;
1313

14+
use crate::api::bolt11_receive::handle_bolt11_receive_request;
15+
use crate::api::bolt11_receive::BOLT11_RECEIVE_PATH;
16+
use crate::api::bolt11_send::handle_bolt11_send_request;
17+
use crate::api::bolt11_send::BOLT11_SEND_PATH;
18+
use crate::api::bolt12_receive::handle_bolt12_receive_request;
19+
use crate::api::bolt12_receive::BOLT12_RECEIVE_PATH;
20+
use crate::api::bolt12_send::handle_bolt12_send_request;
21+
use crate::api::bolt12_send::BOLT12_SEND_PATH;
22+
use crate::api::close_channel::handle_close_channel_request;
23+
use crate::api::close_channel::CLOSE_CHANNEL_PATH;
24+
use crate::api::onchain_receive::handle_onchain_receive_request;
25+
use crate::api::onchain_receive::ONCHAIN_RECEIVE_PATH;
26+
use crate::api::onchain_send::handle_onchain_send_request;
27+
use crate::api::onchain_send::ONCHAIN_SEND_PATH;
28+
use crate::api::open_channel::handle_open_channel;
29+
use crate::api::open_channel::OPEN_CHANNEL_PATH;
30+
1431
#[derive(Clone)]
1532
pub struct NodeService {
1633
node: Arc<Node>,
@@ -28,8 +45,22 @@ impl Service<Request<Incoming>> for NodeService {
2845
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
2946

3047
fn call(&self, req: Request<Incoming>) -> Self::Future {
31-
let _node = Arc::clone(&self.node);
48+
let node = Arc::clone(&self.node);
3249
match req.uri().path() {
50+
ONCHAIN_RECEIVE_PATH => {
51+
Box::pin(handle_request(node, req, handle_onchain_receive_request))
52+
},
53+
ONCHAIN_SEND_PATH => Box::pin(handle_request(node, req, handle_onchain_send_request)),
54+
BOLT11_RECEIVE_PATH => {
55+
Box::pin(handle_request(node, req, handle_bolt11_receive_request))
56+
},
57+
BOLT11_SEND_PATH => Box::pin(handle_request(node, req, handle_bolt11_send_request)),
58+
BOLT12_RECEIVE_PATH => {
59+
Box::pin(handle_request(node, req, handle_bolt12_receive_request))
60+
},
61+
BOLT12_SEND_PATH => Box::pin(handle_request(node, req, handle_bolt12_send_request)),
62+
OPEN_CHANNEL_PATH => Box::pin(handle_request(node, req, handle_open_channel)),
63+
CLOSE_CHANNEL_PATH => Box::pin(handle_request(node, req, handle_close_channel_request)),
3364
path => {
3465
let error = format!("Unknown request: {}", path).into_bytes();
3566
Box::pin(async {

0 commit comments

Comments
 (0)