Skip to content

Commit

Permalink
Fix and add tests for LUD-09
Browse files Browse the repository at this point in the history
  • Loading branch information
lsunsi committed Dec 4, 2023
1 parent ed3dcb5 commit 6d8128c
Show file tree
Hide file tree
Showing 7 changed files with 203 additions and 97 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ suspicious = "deny"
name = "lud06"
required-features = ["client", "server"]

[[test]]
name = "lud09"
required-features = ["client", "server"]

[[test]]
name = "lud11"
required-features = ["client", "server"]
Expand Down
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 ⚠️ 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-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-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-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-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-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
- [LUD-20](https://github.com/lnurl/luds/blob/luds/20.md): core client server ⚠️ tests

- ###### Soon. ™

Expand Down
182 changes: 98 additions & 84 deletions src/core/pay_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,13 @@ pub struct PayRequest {
pub callback: url::Url,
pub short_description: String,
pub long_description: Option<String>,
pub success_action: Option<SuccessAction>,
pub jpeg: Option<Vec<u8>>,
pub png: Option<Vec<u8>>,
pub comment_size: u64,
pub min: u64,
pub max: u64,
}

#[derive(Clone, Debug)]
pub enum SuccessAction {
Url(url::Url, String),
Message(String),
}

impl std::str::FromStr for PayRequest {
type Err = &'static str;

Expand All @@ -28,18 +21,8 @@ impl std::str::FromStr for PayRequest {

let p: de::QueryResponse =
miniserde::json::from_str(s).map_err(|_| "deserialize failed")?;
let comment_size = p.comment_allowed.unwrap_or(0);

let success_action = p
.success_action
.and_then(|sa| match sa.get("tag")? as &str {
"message" => Some(SuccessAction::Message(sa.get("message")?.to_owned())),
"url" => {
let url = url::Url::parse(sa.get("url")?).ok()?;
Some(SuccessAction::Url(url, sa.get("description")?.to_owned()))
}
_ => None,
});
let comment_size = p.comment_allowed.unwrap_or(0);

let metadata = miniserde::json::from_str::<Vec<(String, Value)>>(&p.metadata)
.map_err(|_| "deserialize metadata failed")?;
Expand Down Expand Up @@ -83,7 +66,6 @@ impl std::str::FromStr for PayRequest {
max: p.max_sendable,
short_description,
long_description,
success_action,
comment_size,
jpeg,
png,
Expand Down Expand Up @@ -113,30 +95,13 @@ impl std::fmt::Display for PayRequest {
.collect::<Vec<_>>(),
);

let success_action = self.success_action.as_ref().map(|sa| {
let mut map = std::collections::BTreeMap::new();

match sa {
SuccessAction::Message(m) => {
map.insert("message", m.into());
}
SuccessAction::Url(u, d) => {
map.insert("description", d.into());
map.insert("url", u.to_string().into());
}
}

map
});

f.write_str(&miniserde::json::to_string(&ser::QueryResponse {
tag: TAG,
metadata,
callback: &crate::serde::Url(self.callback.clone()),
min_sendable: self.min,
max_sendable: self.max,
comment_allowed: self.comment_size,
success_action,
}))
}
}
Expand Down Expand Up @@ -164,6 +129,13 @@ impl PayRequest {
pub struct CallbackResponse {
pub pr: String,
pub disposable: bool,
pub success_action: Option<SuccessAction>,
}

#[derive(Clone, Debug)]
pub enum SuccessAction {
Url(url::Url, String),
Message(String),
}

impl std::str::FromStr for CallbackResponse {
Expand All @@ -173,16 +145,47 @@ impl std::str::FromStr for CallbackResponse {
let a: de::CallbackResponse =
miniserde::json::from_str(s).map_err(|_| "deserialize failed")?;

let success_action = a
.success_action
.and_then(|sa| match sa.get("tag")? as &str {
"message" => Some(SuccessAction::Message(sa.get("message")?.to_owned())),
"url" => {
let url = url::Url::parse(sa.get("url")?).ok()?;
Some(SuccessAction::Url(url, sa.get("description")?.to_owned()))
}
_ => None,
});

Ok(Self {
pr: a.pr,
disposable: a.disposable.unwrap_or(true),
success_action,
})
}
}

impl std::fmt::Display for CallbackResponse {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let success_action = self.success_action.as_ref().map(|sa| {
let mut map = std::collections::BTreeMap::new();

match sa {
SuccessAction::Message(m) => {
map.insert("tag", "message".into());
map.insert("message", m.into());
}
SuccessAction::Url(u, d) => {
map.insert("tag", "url".into());
map.insert("description", d.into());
map.insert("url", u.to_string().into());
}
}

map
});

let cr = ser::CallbackResponse {
success_action,
disposable: self.disposable,
pr: &self.pr,
};
Expand All @@ -207,14 +210,14 @@ mod ser {
pub max_sendable: u64,
#[serde(rename = "commentAllowed")]
pub comment_allowed: u64,
#[serde(rename = "successAction")]
pub success_action: Option<BTreeMap<&'static str, std::borrow::Cow<'a, str>>>,
}

#[derive(Serialize)]
pub(super) struct CallbackResponse<'a> {
pub pr: &'a str,
pub disposable: bool,
#[serde(rename = "successAction")]
pub success_action: Option<BTreeMap<&'static str, std::borrow::Cow<'a, str>>>,
}
}

Expand All @@ -233,14 +236,14 @@ mod de {
pub max_sendable: u64,
#[serde(rename = "commentAllowed")]
pub comment_allowed: Option<u64>,
#[serde(rename = "successAction")]
pub success_action: Option<BTreeMap<String, String>>,
}

#[derive(Deserialize)]
pub(super) struct CallbackResponse {
pub pr: String,
pub disposable: Option<bool>,
#[serde(rename = "successAction")]
pub success_action: Option<BTreeMap<String, String>>,
}
}

Expand All @@ -266,7 +269,6 @@ mod tests {

assert_eq!(parsed.comment_size, 0);
assert!(parsed.long_description.is_none());
assert!(parsed.success_action.is_none());
assert!(parsed.jpeg.is_none());
assert!(parsed.png.is_none());
}
Expand Down Expand Up @@ -322,71 +324,83 @@ mod tests {
}

#[test]
fn parse_success_actions() {
fn callback() {
let input = r#"
{
"callback": "https://yuri?o=callback",
"metadata": "[[\"text/plain\", \"boneco do steve magal\"]]",
"maxSendable": 315,
"minSendable": 314,
"successAction": {
"tag": "message",
"message": "obrigado!"
}
"minSendable": 314
}
"#;

let parsed = input.parse::<super::PayRequest>().expect("parse");
let Some(super::SuccessAction::Message(m)) = parsed.success_action else {
panic!("bad success action");
};

assert_eq!(m, "obrigado!");
assert_eq!(
parsed.clone().callback("comentario", 314).to_string(),
"https://yuri/?o=callback&comment=comentario&amount=314"
);

assert_eq!(
parsed.callback("", 314).to_string(),
"https://yuri/?o=callback&amount=314"
);
}

#[test]
fn callback_parse_base() {
let input = r#"
{
"callback": "https://yuri?o=callback",
"metadata": "[[\"text/plain\", \"boneco do steve magal\"]]",
"maxSendable": 315,
"minSendable": 314,
"successAction": {
"tag": "url",
"description": "valeu demais",
"url": "http://uerre.ele"
}
}
{ "pr": "pierre" }
"#;

let parsed = input.parse::<super::PayRequest>().expect("parse");
let Some(super::SuccessAction::Url(u, d)) = parsed.success_action else {
panic!("bad success action");
};
let parsed = input.parse::<super::CallbackResponse>().expect("parse");
assert!(parsed.success_action.is_none());
assert_eq!(parsed.pr, "pierre");
assert!(parsed.disposable);
}

assert_eq!(u.to_string(), "http://uerre.ele/");
assert_eq!(d, "valeu demais");
#[test]
fn callback_parse_disposable() {
let input = r#"
{ "pr": "", "disposable": true }
"#;

let parsed = input.parse::<super::CallbackResponse>().expect("parse");
assert!(parsed.disposable);

let input = r#"
{ "pr": "", "disposable": false }
"#;

let parsed = input.parse::<super::CallbackResponse>().expect("parse");
assert!(!parsed.disposable);
}

#[test]
fn callback() {
fn callback_parse_success_actions() {
let input = r#"
{
"callback": "https://yuri?o=callback",
"metadata": "[[\"text/plain\", \"boneco do steve magal\"]]",
"maxSendable": 315,
"minSendable": 314
}
{ "pr": "", "successAction": { "tag": "message", "message": "obrigado!" } }
"#;

let parsed = input.parse::<super::PayRequest>().expect("parse");
let parsed = input.parse::<super::CallbackResponse>().expect("parse");

assert_eq!(
parsed.clone().callback("comentario", 314).to_string(),
"https://yuri/?o=callback&comment=comentario&amount=314"
);
let Some(super::SuccessAction::Message(m)) = parsed.success_action else {
panic!("bad success action");
};

assert_eq!(
parsed.callback("", 314).to_string(),
"https://yuri/?o=callback&amount=314"
);
assert_eq!(m, "obrigado!");

let input = r#"
{ "pr": "", "successAction": { "tag": "url", "description": "valeu demais", "url": "http://eh.nois" } }
"#;

let parsed = input.parse::<super::CallbackResponse>().expect("parse");

let Some(super::SuccessAction::Url(u, d)) = parsed.success_action else {
panic!("bad success action");
};

assert_eq!(u.to_string(), "http://eh.nois/");
assert_eq!(d, "valeu demais");
}
}
2 changes: 1 addition & 1 deletion tests/lud06.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ async fn test() {
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,
Expand All @@ -31,6 +30,7 @@ async fn test() {
Ok(lnurlkit::core::pay_request::CallbackResponse {
pr: format!("pierre:{amount}"),
disposable: false,
success_action: None,
})
},
)
Expand Down
Loading

0 comments on commit 6d8128c

Please sign in to comment.