Skip to content

Commit

Permalink
refactor: use request types on server callbacks
Browse files Browse the repository at this point in the history
  • Loading branch information
lsunsi committed Dec 8, 2023
1 parent 8b9c77e commit 3ce765b
Showing 10 changed files with 142 additions and 108 deletions.
24 changes: 12 additions & 12 deletions src/client.rs
Original file line number Diff line number Diff line change
@@ -6,18 +6,18 @@ impl Client {
///
/// Returns errors on network or deserialization failures.
pub async fn query(&self, s: &str) -> Result<Query, &'static str> {
let url = crate::core::resolve(s)?;
let url = crate::resolve(s)?;

let client = &self.0;
let response = client.get(url).send().await.map_err(|_| "request failed")?;
let text = response.text().await.map_err(|_| "body failed")?;

text.parse::<crate::core::Query>()
text.parse::<crate::Query>()
.map_err(|_| "parse failed")
.map(|query| match query {
crate::core::Query::Channel(core) => Query::Channel(Channel { client, core }),
crate::core::Query::Pay(core) => Query::Pay(Pay { client, core }),
crate::core::Query::Withdraw(core) => Query::Withdraw(Withdraw { client, core }),
crate::Query::Channel(core) => Query::Channel(Channel { client, core }),
crate::Query::Pay(core) => Query::Pay(Pay { client, core }),
crate::Query::Withdraw(core) => Query::Withdraw(Withdraw { client, core }),
})
}
}
@@ -32,19 +32,19 @@ pub enum Query<'a> {
#[derive(Clone, Debug)]
pub struct Channel<'a> {
client: &'a reqwest::Client,
pub core: crate::core::channel::Query,
pub core: crate::channel::Query,
}

#[derive(Clone, Debug)]
pub struct Pay<'a> {
client: &'a reqwest::Client,
pub core: crate::core::pay::Query,
pub core: crate::pay::Query,
}

#[derive(Clone, Debug)]
pub struct Withdraw<'a> {
client: &'a reqwest::Client,
pub core: crate::core::withdraw::Query,
pub core: crate::withdraw::Query,
}

impl Channel<'_> {
@@ -55,7 +55,7 @@ impl Channel<'_> {
self,
remoteid: String,
private: bool,
) -> Result<crate::core::channel::CallbackResponse, &'static str> {
) -> Result<crate::channel::CallbackResponse, &'static str> {
let callback = self.core.callback_accept(remoteid, private).url();

let response = self
@@ -75,7 +75,7 @@ impl Channel<'_> {
pub async fn callback_cancel(
self,
remoteid: String,
) -> Result<crate::core::channel::CallbackResponse, &'static str> {
) -> Result<crate::channel::CallbackResponse, &'static str> {
let callback = self.core.callback_cancel(remoteid).url();

let response = self
@@ -98,7 +98,7 @@ impl Pay<'_> {
self,
millisatoshis: u64,
comment: String,
) -> Result<crate::core::pay::CallbackResponse, &'static str> {
) -> Result<crate::pay::CallbackResponse, &'static str> {
let callback = self.core.callback(millisatoshis, comment).url();

let response = self
@@ -120,7 +120,7 @@ impl Withdraw<'_> {
pub async fn callback(
self,
pr: String,
) -> Result<crate::core::withdraw::CallbackResponse, &'static str> {
) -> Result<crate::withdraw::CallbackResponse, &'static str> {
let callback = self.core.callback(pr).url();

let response = self
6 changes: 0 additions & 6 deletions src/core/channel.rs
Original file line number Diff line number Diff line change
@@ -104,12 +104,6 @@ impl CallbackRequest {
}
}

#[derive(Debug)]
pub enum CallbackAction {
Accept { private: bool },
Cancel,
}

#[derive(Debug)]
pub enum CallbackResponse {
Error(String),
147 changes: 91 additions & 56 deletions src/server.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
use axum::{extract::Path, extract::RawQuery, http::StatusCode, routing::get, Router};
use axum::{
extract::{Path, RawQuery},
http::StatusCode,
http::Uri,
routing::get,
Router,
};
use std::future::Future;

pub struct Server<CQ, CC, PQ, PC, WQ, WC> {
base: String,
channel_query: CQ,
channel_callback: CC,
pay_query: PQ,
@@ -10,24 +17,24 @@ pub struct Server<CQ, CC, PQ, PC, WQ, WC> {
withdraw_callback: WC,
}

impl Default
for Server<
impl
Server<
// Channel Request
unimplemented::Handler<(), crate::core::channel::Query>,
unimplemented::Handler<
(String, String, crate::core::channel::CallbackAction),
crate::core::channel::CallbackResponse,
>,
unimplemented::Handler<(), crate::channel::Query>,
unimplemented::Handler<crate::channel::CallbackRequest, crate::channel::CallbackResponse>,
// Pay Request
unimplemented::Handler<Option<String>, crate::core::pay::Query>,
unimplemented::Handler<(u64, Option<String>), crate::core::pay::CallbackResponse>,
unimplemented::Handler<Option<String>, crate::pay::Query>,
unimplemented::Handler<crate::pay::CallbackRequest, crate::pay::CallbackResponse>,
// Withdraw Request
unimplemented::Handler<(), crate::core::withdraw::Query>,
unimplemented::Handler<(String, String), crate::core::withdraw::CallbackResponse>,
unimplemented::Handler<(), crate::withdraw::Query>,
unimplemented::Handler<crate::withdraw::CallbackRequest, crate::withdraw::CallbackResponse>,
>
{
fn default() -> Self {
#[must_use]
pub fn new(base: String) -> Self {
Server {
base,

channel_query: unimplemented::handler,
channel_callback: unimplemented::handler,

@@ -47,6 +54,7 @@ impl<CQ, CC, PQ, PC, WQ, WC> Server<CQ, CC, PQ, PC, WQ, WC> {
channel_callback: CC2,
) -> Server<CQ2, CC2, PQ, PC, WQ, WC> {
Server {
base: self.base,
channel_query,
channel_callback,
pay_query: self.pay_query,
@@ -62,6 +70,7 @@ impl<CQ, CC, PQ, PC, WQ, WC> Server<CQ, CC, PQ, PC, WQ, WC> {
pay_callback: PC2,
) -> Server<CQ, CC, PQ2, PC2, WQ, WC> {
Server {
base: self.base,
channel_query: self.channel_query,
channel_callback: self.channel_callback,
pay_query,
@@ -77,6 +86,7 @@ impl<CQ, CC, PQ, PC, WQ, WC> Server<CQ, CC, PQ, PC, WQ, WC> {
withdraw_callback: WC2,
) -> Server<CQ, CC, PQ, PC, WQ2, WC2> {
Server {
base: self.base,
channel_query: self.channel_query,
channel_callback: self.channel_callback,
pay_query: self.pay_query,
@@ -91,28 +101,29 @@ impl<CQ, CQFut, CC, CCFut, PQ, PQFut, PC, PCFut, WQ, WQFut, WC, WCFut>
Server<CQ, CC, PQ, PC, WQ, WC>
where
CQ: 'static + Send + Clone + Fn(()) -> CQFut,
CQFut: Send + Future<Output = Result<crate::core::channel::Query, StatusCode>>,
CQFut: Send + Future<Output = Result<crate::channel::Query, StatusCode>>,

CC: 'static
+ Send
+ Clone
+ Fn((String, String, crate::core::channel::CallbackAction)) -> CCFut,
CCFut: Send + Future<Output = Result<crate::core::channel::CallbackResponse, StatusCode>>,
CC: 'static + Send + Clone + Fn(crate::channel::CallbackRequest) -> CCFut,
CCFut: Send + Future<Output = Result<crate::channel::CallbackResponse, StatusCode>>,

PQ: 'static + Send + Clone + Fn(Option<String>) -> PQFut,
PQFut: Send + Future<Output = Result<crate::core::pay::Query, StatusCode>>,
PQFut: Send + Future<Output = Result<crate::pay::Query, StatusCode>>,

PC: 'static + Send + Clone + Fn((u64, Option<String>)) -> PCFut,
PCFut: Send + Future<Output = Result<crate::core::pay::CallbackResponse, StatusCode>>,
PC: 'static + Send + Clone + Fn(crate::pay::CallbackRequest) -> PCFut,
PCFut: Send + Future<Output = Result<crate::pay::CallbackResponse, StatusCode>>,

WQ: 'static + Send + Clone + Fn(()) -> WQFut,
WQFut: Send + Future<Output = Result<crate::core::withdraw::Query, StatusCode>>,
WQFut: Send + Future<Output = Result<crate::withdraw::Query, StatusCode>>,

WC: 'static + Send + Clone + Fn((String, String)) -> WCFut,
WCFut: Send + Future<Output = Result<crate::core::withdraw::CallbackResponse, StatusCode>>,
WC: 'static + Send + Clone + Fn(crate::withdraw::CallbackRequest) -> WCFut,
WCFut: Send + Future<Output = Result<crate::withdraw::CallbackResponse, StatusCode>>,
{
#[allow(clippy::too_many_lines)]
pub fn build(self) -> Router<()> {
let base_c = self.base.clone();
let base_p = self.base.clone();
let base_w = self.base.clone();

Router::new()
.route(
"/lnurlc",
@@ -123,36 +134,44 @@ where
)
.route(
"/lnurlc/callback",
get(move |RawQuery(q): RawQuery| {
get(move |uri: Uri, RawQuery(q): RawQuery| {
let cc = self.channel_callback.clone();
async move {
let url = url::Url::parse(&format!("https://{base_c}{}", uri.path()))
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

let q = q.ok_or(StatusCode::BAD_REQUEST)?;
let qs = q
.split('&')
.filter_map(|s| s.split_once('='))
.collect::<std::collections::BTreeMap<_, _>>();

let k1 = qs.get("k1").ok_or(StatusCode::BAD_REQUEST)?;
let remoteid = qs.get("remoteid").ok_or(StatusCode::BAD_REQUEST)?;
let action = qs
.get("cancel")
.filter(|v| **v == "1")
.map(|_| crate::core::channel::CallbackAction::Cancel)
.or_else(|| {
qs.get("private").and_then(|v| match *v {
"0" => Some(crate::core::channel::CallbackAction::Accept {
private: false,
}),
"1" => Some(crate::core::channel::CallbackAction::Accept {
private: true,
}),
_ => None,
})
})
.ok_or(StatusCode::BAD_REQUEST)?;
let k1 = String::from(*qs.get("k1").ok_or(StatusCode::BAD_REQUEST)?);
let remoteid =
String::from(*qs.get("remoteid").ok_or(StatusCode::BAD_REQUEST)?);

let param = (String::from(*k1), String::from(*remoteid), action);
cc(param).await.map(|a| a.to_string())
let req = if qs.get("cancel").copied() == Some("1") {
Some(crate::channel::CallbackRequest::Cancel { url, remoteid, k1 })
} else {
match qs.get("private").copied() {
Some("0") => Some(crate::channel::CallbackRequest::Accept {
url,
remoteid,
k1,
private: false,
}),
Some("1") => Some(crate::channel::CallbackRequest::Accept {
url,
remoteid,
k1,
private: true,
}),
_ => None,
}
}
.ok_or(StatusCode::BAD_REQUEST)?;

cc(req).await.map(|a| a.to_string())
}
}),
)
@@ -175,23 +194,35 @@ where
)
.route(
"/lnurlp/callback",
get(move |RawQuery(q): RawQuery| {
get(move |uri: Uri, RawQuery(q): RawQuery| {
let pc = self.pay_callback.clone();
async move {
let url = url::Url::parse(&format!("https://{base_p}{}", uri.path()))
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

let q = q.ok_or(StatusCode::BAD_REQUEST)?;
let qs = q
.split('&')
.filter_map(|s| s.split_once('='))
.collect::<std::collections::BTreeMap<_, _>>();

let amount = qs
let millisatoshis = qs
.get("amount")
.and_then(|s| s.parse().ok())
.ok_or(StatusCode::BAD_REQUEST)?;

let comment = qs.get("comment").map(|c| String::from(*c));
let comment = qs
.get("comment")
.map(|c| String::from(*c))
.unwrap_or_default();

pc((amount, comment)).await.map(|a| a.to_string())
pc(crate::pay::CallbackRequest {
url,
comment,
millisatoshis,
})
.await
.map(|a| a.to_string())
}
}),
)
@@ -204,20 +235,24 @@ where
)
.route(
"/lnurlw/callback",
get(move |RawQuery(q): RawQuery| {
get(move |uri: Uri, RawQuery(q): RawQuery| {
let wc = self.withdraw_callback.clone();
async move {
let url = url::Url::parse(&format!("https://{base_w}{}", uri.path()))
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

let q = q.ok_or(StatusCode::BAD_REQUEST)?;
let qs = q
.split('&')
.filter_map(|s| s.split_once('='))
.collect::<std::collections::BTreeMap<_, _>>();

let k1 = qs.get("k1").ok_or(StatusCode::BAD_REQUEST)?;
let pr = qs.get("pr").ok_or(StatusCode::BAD_REQUEST)?;
let k1 = String::from(*qs.get("k1").ok_or(StatusCode::BAD_REQUEST)?);
let pr = String::from(*qs.get("pr").ok_or(StatusCode::BAD_REQUEST)?);

let param = (String::from(*k1), String::from(*pr));
wc(param).await.map(|a| a.to_string())
wc(crate::withdraw::CallbackRequest { url, k1, pr })
.await
.map(|a| a.to_string())
}
}),
)
@@ -253,6 +288,6 @@ mod unimplemented {
mod tests {
#[test]
fn default_builds() {
drop(super::Server::default().build());
drop(super::Server::new(String::from("base:31415")).build());
}
}
Loading

0 comments on commit 3ce765b

Please sign in to comment.