cashu/nuts/nut18/
secret.rs1use serde::{Deserialize, Serialize};
3
4use crate::nuts::nut10::Kind;
5use crate::nuts::{Nut10Secret, SpendingConditions};
6
7#[derive(Debug, Clone, Hash, PartialEq, Eq, Serialize, Deserialize)]
9pub struct Nut10SecretRequest {
10 #[serde(rename = "k")]
12 pub kind: Kind,
13 #[serde(rename = "d")]
15 pub data: String,
16 #[serde(rename = "t", skip_serializing_if = "Option::is_none")]
18 pub tags: Option<Vec<Vec<String>>>,
19}
20
21impl Nut10SecretRequest {
22 pub fn new<S, V>(kind: Kind, data: S, tags: Option<V>) -> Self
24 where
25 S: Into<String>,
26 V: Into<Vec<Vec<String>>>,
27 {
28 Self {
29 kind,
30 data: data.into(),
31 tags: tags.map(|v| v.into()),
32 }
33 }
34}
35
36impl From<Nut10Secret> for Nut10SecretRequest {
37 fn from(secret: Nut10Secret) -> Self {
38 Self {
39 kind: secret.kind(),
40 data: secret.secret_data().data().to_string(),
41 tags: secret.secret_data().tags().cloned(),
42 }
43 }
44}
45
46impl From<Nut10SecretRequest> for Nut10Secret {
47 fn from(value: Nut10SecretRequest) -> Self {
48 Self::new(value.kind, value.data, value.tags)
49 }
50}
51
52impl From<SpendingConditions> for Nut10SecretRequest {
53 fn from(conditions: SpendingConditions) -> Self {
54 match conditions {
55 SpendingConditions::P2PKConditions { data, conditions } => {
56 Self::new(Kind::P2PK, data.to_hex(), conditions)
57 }
58 SpendingConditions::HTLCConditions { data, conditions } => {
59 Self::new(Kind::HTLC, data.to_string(), conditions)
60 }
61 }
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68
69 #[test]
70 fn test_nut10_secret_request_serialization() {
71 let request = Nut10SecretRequest::new(
72 Kind::P2PK,
73 "026562efcfadc8e86d44da6a8adf80633d974302e62c850774db1fb36ff4cc7198",
74 Some(vec![vec!["key".to_string(), "value".to_string()]]),
75 );
76
77 let json = serde_json::to_string(&request).unwrap();
78
79 assert!(json.contains(r#""k":"P2PK""#));
81 assert!(json.contains(r#""d":"026562"#));
82 assert!(json.contains(r#""t":[["key","#));
83 }
84
85 #[test]
86 fn test_roundtrip_serialization() {
87 let original = Nut10SecretRequest {
88 kind: Kind::P2PK,
89 data: "test_data".into(),
90 tags: Some(vec![vec!["key".to_string(), "value".to_string()]]),
91 };
92
93 let json = serde_json::to_string(&original).unwrap();
94 let decoded: Nut10SecretRequest = serde_json::from_str(&json).unwrap();
95
96 assert_eq!(original, decoded);
97 }
98
99 #[test]
100 fn test_from_nut10_secret() {
101 let secret = Nut10Secret::new(
102 Kind::P2PK,
103 "test_data",
104 Some(vec![vec!["key".to_string(), "value".to_string()]]),
105 );
106
107 let request: Nut10SecretRequest = secret.clone().into();
108
109 assert_eq!(request.kind, secret.kind());
110 assert_eq!(request.data, secret.secret_data().data());
111 assert_eq!(request.tags, secret.secret_data().tags().cloned());
112 }
113
114 #[test]
115 fn test_into_nut10_secret() {
116 let request = Nut10SecretRequest {
117 kind: Kind::HTLC,
118 data: "test_hash".into(),
119 tags: None,
120 };
121
122 let secret: Nut10Secret = request.clone().into();
123
124 assert_eq!(secret.kind(), request.kind);
125 assert_eq!(secret.secret_data().data(), request.data);
126 assert_eq!(secret.secret_data().tags(), request.tags.as_ref());
127 }
128}