thesimplekid vor 1 Jahr
Ursprung
Commit
ee0a60e40c
3 geänderte Dateien mit 115 neuen und 1 gelöschten Zeilen
  1. 2 1
      crates/cashu/Cargo.toml
  2. 2 0
      crates/cashu/src/nuts/mod.rs
  3. 111 0
      crates/cashu/src/nuts/nut10.rs

+ 2 - 1
crates/cashu/Cargo.toml

@@ -15,9 +15,10 @@ description = "Cashu rust wallet and mint library"
 default = ["mint", "wallet", "all-nuts"]
 mint = []
 wallet = []
-all-nuts = ["nut07", "nut08"]
+all-nuts = ["nut07", "nut08", "nut10"]
 nut07 = []
 nut08 = []
+nut10 = []
 
 
 [dependencies]

+ 2 - 0
crates/cashu/src/nuts/mod.rs

@@ -9,6 +9,8 @@ pub mod nut06;
 pub mod nut07;
 #[cfg(feature = "nut08")]
 pub mod nut08;
+#[cfg(feature = "nut10")]
+pub mod nut10;
 
 #[cfg(feature = "wallet")]
 pub use nut00::wallet::{PreMint, PreMintSecrets, Token};

+ 111 - 0
crates/cashu/src/nuts/nut10.rs

@@ -0,0 +1,111 @@
+use serde::ser::SerializeTuple;
+use serde::{Deserialize, Serialize, Serializer};
+
+#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, PartialEq, Eq)]
+pub enum Kind {
+    /// NUT-11 P2PK
+    #[default]
+    P2PK,
+}
+
+#[derive(Debug, Default, Clone, Deserialize, PartialEq, Eq, Serialize)]
+pub struct SecretData {
+    /// Unique random string
+    pub nonce: String,
+    /// Expresses the spending condition specific to each kind
+    pub data: String,
+    /// Additional data committed to and can be used for feature extensions
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub tags: Option<Vec<Vec<String>>>,
+}
+
+#[derive(Debug, Default, Clone, Deserialize, PartialEq, Eq)]
+pub struct Secret {
+    ///  Kind of the spending condition
+    pub kind: Kind,
+    pub secret_data: SecretData,
+}
+
+impl Serialize for Secret {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        // Create a tuple representing the struct fields
+        let secret_tuple = (&self.kind, &self.secret_data);
+
+        // Serialize the tuple as a JSON array
+        let mut s = serializer.serialize_tuple(2)?;
+
+        s.serialize_element(&secret_tuple.0)?;
+        s.serialize_element(&secret_tuple.1)?;
+        s.end()
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use std::assert_eq;
+
+    use super::*;
+
+    #[test]
+    fn test_secret_deserialize() {
+        let secret_str = r#"[
+  "P2PK",
+  {
+    "nonce": "5d11913ee0f92fefdc82a6764fd2457a",
+    "data": "026562efcfadc8e86d44da6a8adf80633d974302e62c850774db1fb36ff4cc7198",
+    "tags": [["key", "value1", "value2"]]
+  }
+]"#
+        .to_string();
+
+        let secret_ser: Secret = serde_json::from_str(&secret_str).unwrap();
+        let secret = Secret {
+            kind: Kind::P2PK,
+            secret_data: SecretData {
+                nonce: "5d11913ee0f92fefdc82a6764fd2457a".to_string(),
+                data: "026562efcfadc8e86d44da6a8adf80633d974302e62c850774db1fb36ff4cc7198"
+                    .to_string(),
+                tags: Some(vec![vec![
+                    "key".to_string(),
+                    "value1".to_string(),
+                    "value2".to_string(),
+                ]]),
+            },
+        };
+
+        assert_eq!(secret, secret_ser);
+    }
+
+    #[test]
+    fn test_secret_serialize() {
+        let secret = Secret {
+            kind: Kind::P2PK,
+            secret_data: SecretData {
+                nonce: "5d11913ee0f92fefdc82a6764fd2457a".to_string(),
+                data: "026562efcfadc8e86d44da6a8adf80633d974302e62c850774db1fb36ff4cc7198"
+                    .to_string(),
+                tags: Some(vec![vec![
+                    "key".to_string(),
+                    "value1".to_string(),
+                    "value2".to_string(),
+                ]]),
+            },
+        };
+
+        let secret_str = r#"["P2PK",{"nonce":"5d11913ee0f92fefdc82a6764fd2457a","data":"026562efcfadc8e86d44da6a8adf80633d974302e62c850774db1fb36ff4cc7198","tags":[["key","value1","value2"]]}]"#;
+
+        assert_eq!(serde_json::to_string(&secret).unwrap(), secret_str);
+    }
+
+    #[test]
+    fn test_secret_roundtrip() {
+        let secret_str = r#"["P2PK",{"nonce":"5d11913ee0f92fefdc82a6764fd2457a","data":"026562efcfadc8e86d44da6a8adf80633d974302e62c850774db1fb36ff4cc7198","tags":[["key","value1","value2"]]}]"#;
+
+        let secret_ser: Secret = serde_json::from_str(secret_str).unwrap();
+
+        assert_eq!(serde_json::to_string(&secret_ser).unwrap(), secret_str)
+    }
+}