diff --git a/Cargo.toml b/Cargo.toml index 5f6ec5c..743ab7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,8 +22,9 @@ axum = { version = "0.7.0", default-features = false, optional = true } reqwest = { version = "0.11.0", default-features = false, optional = true } [dev-dependencies] +axum = { version = "0.7.0", features = ["tokio", "http1"], default-features = false } reqwest = { version = "0.11.0", features = ["rustls-tls-webpki-roots"], default-features = false } -tokio = { version = "1.0.0", features = ["rt", "macros"], default-features = false } +tokio = { version = "1.0.0", features = ["macros"], default-features = false } [features] client = ["dep:reqwest"] @@ -41,10 +42,6 @@ perf = "deny" style = "deny" suspicious = "deny" -[[example]] +[[test]] name = "lud06" -required-features = ["client"] - -[[example]] -name = "lud16" -required-features = ["client"] +required-features = ["client", "server"] diff --git a/README.md b/README.md index 07b70d3..3a25a5d 100644 --- a/README.md +++ b/README.md @@ -9,26 +9,26 @@ This library works as a toolkit so you can serve and make your LNURL requests wi ## Current support -- [LUD-01](https://github.com/lnurl/luds/blob/luds/01.md): 🆘 core ⚠️ client 🆘 server ⚠️ example 🆘 test -- [LUD-02](https://github.com/lnurl/luds/blob/luds/02.md): 🆘 core ⚠️ client 🆘 server 🆘 example 🆘 test -- [LUD-03](https://github.com/lnurl/luds/blob/luds/03.md): 🆘 core ⚠️ client 🆘 server 🆘 example 🆘 test -- [LUD-04](https://github.com/lnurl/luds/blob/luds/04.md): 🆘 core 🆘 client 🆘 server 🆘 example 🆘 test -- [LUD-05](https://github.com/lnurl/luds/blob/luds/05.md): 🆘 core 🆘 client 🆘 server 🆘 example 🆘 test -- [LUD-06](https://github.com/lnurl/luds/blob/luds/06.md): 🆘 core ⚠️ client 🆘 server ⚠️ example 🆘 test -- [LUD-07](https://github.com/lnurl/luds/blob/luds/07.md): 🆘 core 🆘 client 🆘 server 🆘 example 🆘 test -- [LUD-08](https://github.com/lnurl/luds/blob/luds/08.md): 🆘 core 🆘 client 🆘 server 🆘 example 🆘 test -- [LUD-09](https://github.com/lnurl/luds/blob/luds/09.md): 🆘 core ⚠️ client 🆘 server 🆘 example 🆘 test -- [LUD-10](https://github.com/lnurl/luds/blob/luds/10.md): 🆘 core 🆘 client 🆘 server 🆘 example 🆘 test -- [LUD-11](https://github.com/lnurl/luds/blob/luds/11.md): 🆘 core ⚠️ client 🆘 server 🆘 example 🆘 test -- [LUD-12](https://github.com/lnurl/luds/blob/luds/12.md): 🆘 core ⚠️ client 🆘 server 🆘 example 🆘 test -- [LUD-13](https://github.com/lnurl/luds/blob/luds/13.md): 🆘 core 🆘 client 🆘 server 🆘 example 🆘 test -- [LUD-14](https://github.com/lnurl/luds/blob/luds/14.md): 🆘 core 🆘 client 🆘 server 🆘 example 🆘 test -- [LUD-15](https://github.com/lnurl/luds/blob/luds/15.md): 🆘 core 🆘 client 🆘 server 🆘 example 🆘 test -- [LUD-16](https://github.com/lnurl/luds/blob/luds/16.md): 🆘 core ⚠️ client 🆘 server ⚠️ example 🆘 test -- [LUD-17](https://github.com/lnurl/luds/blob/luds/17.md): 🆘 core 🆘 client 🆘 server 🆘 example 🆘 test -- [LUD-18](https://github.com/lnurl/luds/blob/luds/18.md): 🆘 core 🆘 client 🆘 server 🆘 example 🆘 test -- [LUD-19](https://github.com/lnurl/luds/blob/luds/19.md): 🆘 core 🆘 client 🆘 server 🆘 example 🆘 test -- [LUD-20](https://github.com/lnurl/luds/blob/luds/20.md): 🆘 core ⚠️ client 🆘 server 🆘 example 🆘 test +- [LUD-01](https://github.com/lnurl/luds/blob/luds/01.md): ⚠️ core ⚠️ client ⚠️ server 🆘 tests +- [LUD-02](https://github.com/lnurl/luds/blob/luds/02.md): ⚠️ core ⚠️ client 🆘 server 🆘 tests +- [LUD-03](https://github.com/lnurl/luds/blob/luds/03.md): ⚠️ core ⚠️ client 🆘 server 🆘 tests +- [LUD-04](https://github.com/lnurl/luds/blob/luds/04.md): 🆘 core 🆘 client 🆘 server 🆘 tests +- [LUD-05](https://github.com/lnurl/luds/blob/luds/05.md): 🆘 core 🆘 client 🆘 server 🆘 tests +- [LUD-06](https://github.com/lnurl/luds/blob/luds/06.md): ✅ core ⚠️ client ⚠️ server ⚠️ tests +- [LUD-07](https://github.com/lnurl/luds/blob/luds/07.md): 🆘 core 🆘 client 🆘 server 🆘 tests +- [LUD-08](https://github.com/lnurl/luds/blob/luds/08.md): 🆘 core 🆘 client 🆘 server 🆘 tests +- [LUD-09](https://github.com/lnurl/luds/blob/luds/09.md): ⚠️ core ⚠️ client 🆘 server 🆘 tests +- [LUD-10](https://github.com/lnurl/luds/blob/luds/10.md): 🆘 core 🆘 client 🆘 server 🆘 tests +- [LUD-11](https://github.com/lnurl/luds/blob/luds/11.md): ⚠️ core ⚠️ client 🆘 server 🆘 tests +- [LUD-12](https://github.com/lnurl/luds/blob/luds/12.md): ⚠️ core ⚠️ client 🆘 server 🆘 tests +- [LUD-13](https://github.com/lnurl/luds/blob/luds/13.md): 🆘 core 🆘 client 🆘 server 🆘 tests +- [LUD-14](https://github.com/lnurl/luds/blob/luds/14.md): 🆘 core 🆘 client 🆘 server 🆘 tests +- [LUD-15](https://github.com/lnurl/luds/blob/luds/15.md): 🆘 core 🆘 client 🆘 server 🆘 tests +- [LUD-16](https://github.com/lnurl/luds/blob/luds/16.md): ⚠️ core ⚠️ client 🆘 server 🆘 tests +- [LUD-17](https://github.com/lnurl/luds/blob/luds/17.md): 🆘 core 🆘 client 🆘 server 🆘 tests +- [LUD-18](https://github.com/lnurl/luds/blob/luds/18.md): 🆘 core 🆘 client 🆘 server 🆘 tests +- [LUD-19](https://github.com/lnurl/luds/blob/luds/19.md): 🆘 core 🆘 client 🆘 server 🆘 tests +- [LUD-20](https://github.com/lnurl/luds/blob/luds/20.md): ⚠️ core ⚠️ client 🆘 server 🆘 tests - ###### Soon. ™ diff --git a/examples/lud06.rs b/examples/lud06.rs deleted file mode 100644 index af2d88e..0000000 --- a/examples/lud06.rs +++ /dev/null @@ -1,19 +0,0 @@ -#[tokio::main(flavor = "current_thread")] -async fn main() { - let client = lnurlkit::client::Client::default(); - - let queried = client - .query("lnurl1dp68gurn8ghj7cnfwpsjuctswqhjuam9d3kz66mwdamkutmvde6hymrs9a4k2mn4cdry4t") - .await - .expect("query"); - - println!("{queried:?}"); - - let lnurlkit::client::Query::PayRequest(pr) = queried else { - panic!("not pay request"); - }; - - let invoice = pr.callback("comment", 123000).await.expect("callback"); - - println!("{invoice:?}"); -} diff --git a/examples/lud16.rs b/examples/lud16.rs deleted file mode 100644 index 23e5062..0000000 --- a/examples/lud16.rs +++ /dev/null @@ -1,16 +0,0 @@ -#[tokio::main(flavor = "current_thread")] -async fn main() { - let client = lnurlkit::client::Client::default(); - - let queried = client.query("kenu@bipa.app").await.expect("address"); - - println!("{queried:?}"); - - let lnurlkit::client::Query::PayRequest(pr) = queried else { - panic!("not pay request"); - }; - - let invoice = pr.callback("comment", 123000).await.expect("callback"); - - println!("{invoice:?}"); -} diff --git a/src/client.rs b/src/client.rs index 35e3d76..ec24606 100644 --- a/src/client.rs +++ b/src/client.rs @@ -38,19 +38,19 @@ pub enum Query<'a> { #[derive(Clone, Debug)] pub struct PayRequest<'a> { client: &'a reqwest::Client, - core: crate::core::pay_request::PayRequest, + pub core: crate::core::pay_request::PayRequest, } #[derive(Clone, Debug)] pub struct ChannelRequest<'a> { client: &'a reqwest::Client, - core: crate::core::channel_request::ChannelRequest, + pub core: crate::core::channel_request::ChannelRequest, } #[derive(Clone, Debug)] pub struct WithdrawalRequest<'a> { client: &'a reqwest::Client, - core: crate::core::withdrawal_request::WithdrawalRequest, + pub core: crate::core::withdrawal_request::WithdrawalRequest, } impl PayRequest<'_> { diff --git a/src/core/pay_request.rs b/src/core/pay_request.rs index c40555e..d640e41 100644 --- a/src/core/pay_request.rs +++ b/src/core/pay_request.rs @@ -2,7 +2,7 @@ pub const TAG: &str = "payRequest"; #[derive(Clone, Debug)] pub struct PayRequest { - callback: crate::serde::Url, + pub callback: url::Url, pub short_description: String, pub long_description: Option, pub success_action: Option, @@ -78,7 +78,7 @@ impl std::str::FromStr for PayRequest { }); Ok(PayRequest { - callback: p.callback, + callback: p.callback.0, min: p.min_sendable, max: p.max_sendable, short_description, @@ -130,8 +130,9 @@ impl std::fmt::Display for PayRequest { }); f.write_str(&miniserde::json::to_string(&ser::QueryResponse { + tag: TAG, metadata, - callback: &self.callback, + callback: &crate::serde::Url(self.callback.clone()), min_sendable: self.min, max_sendable: self.max, comment_allowed: self.comment_size, @@ -146,7 +147,7 @@ impl PayRequest { /// Returns errors on network or deserialization failures. #[must_use] pub fn callback(mut self, comment: &str, millisatoshis: u64) -> url::Url { - self.callback.0.query_pairs_mut().extend_pairs( + self.callback.query_pairs_mut().extend_pairs( [ (!comment.is_empty()).then_some(("comment", comment)), Some(("amount", &millisatoshis.to_string())), @@ -155,7 +156,7 @@ impl PayRequest { .flatten(), ); - self.callback.0 + self.callback } } @@ -186,6 +187,7 @@ mod ser { #[derive(Serialize)] pub(super) struct QueryResponse<'a> { + pub tag: &'static str, pub metadata: String, pub callback: &'a Url, #[serde(rename = "minSendable")] diff --git a/src/server.rs b/src/server.rs index d1f9605..7e55239 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,6 +1,10 @@ use axum::{http::StatusCode, routing::get, Router}; use std::future::Future; +pub fn builder

() -> Server

{ + Server { pay_request: None } +} + pub struct Server

{ pub pay_request: Option

, } diff --git a/tests/lud06.rs b/tests/lud06.rs new file mode 100644 index 0000000..b4ba913 --- /dev/null +++ b/tests/lud06.rs @@ -0,0 +1,65 @@ +#[tokio::test] +async fn test() { + let listener = tokio::net::TcpListener::bind("0.0.0.0:0") + .await + .expect("net"); + + let addr = listener.local_addr().expect("addr"); + + let query_url = format!("http://{addr}/lnurlp"); + let callback_url = url::Url::parse(&format!("http://{addr}/lnurlp/callback")).expect("url"); + + let router = { + let mut router = lnurlkit::server::builder(); + + router.pay_request = Some(move || { + let callback = callback_url.clone(); + + async { + Ok(lnurlkit::core::pay_request::PayRequest { + callback, + short_description: String::from("today i become death"), + long_description: Some(String::from("the destroyer of worlds")), + success_action: None, + jpeg: None, + png: None, + comment_size: 0, + min: 314, + max: 315, + }) + } + }); + + router.build() + }; + + tokio::spawn(async move { + axum::serve(listener, router).await.expect("serve"); + }); + + let client = lnurlkit::client::Client::default(); + + let lnurl = bech32::encode( + "lnurl", + bech32::ToBase32::to_base32(&query_url), + bech32::Variant::Bech32, + ) + .expect("lnurl"); + + let queried = client.query(&lnurl).await.expect("query"); + + println!("{queried:?}"); + + let lnurlkit::client::Query::PayRequest(pr) = queried else { + panic!("not pay request"); + }; + + assert_eq!(pr.core.min, 314); + assert_eq!(pr.core.max, 315); + assert_eq!(pr.core.short_description, "today i become death"); + assert_eq!(pr.core.long_description.unwrap(), "the destroyer of worlds"); + + // let invoice = pr.callback("comment", 123000).await.expect("callback"); + + // println!("{invoice:?}"); +}