nut10.rs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. //! NUT-10: Spending conditions
  2. //!
  3. //! <https://github.com/cashubtc/nuts/blob/main/10.md>
  4. use std::str::FromStr;
  5. use serde::ser::SerializeTuple;
  6. use serde::{Deserialize, Serialize, Serializer};
  7. use thiserror::Error;
  8. /// NUT13 Error
  9. #[derive(Debug, Error)]
  10. pub enum Error {
  11. /// Secret error
  12. #[error(transparent)]
  13. Secret(#[from] crate::secret::Error),
  14. /// Serde Json error
  15. #[error(transparent)]
  16. SerdeJsonError(#[from] serde_json::Error),
  17. }
  18. /// NUT10 Secret Kind
  19. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
  20. pub enum Kind {
  21. /// NUT-11 P2PK
  22. P2PK,
  23. /// NUT-14 HTLC
  24. HTLC,
  25. }
  26. /// Secert Date
  27. #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
  28. pub struct SecretData {
  29. /// Unique random string
  30. pub nonce: String,
  31. /// Expresses the spending condition specific to each kind
  32. pub data: String,
  33. /// Additional data committed to and can be used for feature extensions
  34. #[serde(skip_serializing_if = "Option::is_none")]
  35. pub tags: Option<Vec<Vec<String>>>,
  36. }
  37. /// NUT10 Secret
  38. #[derive(Debug, Clone, PartialEq, Eq, Hash, Deserialize)]
  39. pub struct Secret {
  40. /// Kind of the spending condition
  41. pub kind: Kind,
  42. /// Secret Data
  43. pub secret_data: SecretData,
  44. }
  45. impl Secret {
  46. /// Create new [`Secret`]
  47. pub fn new<S, V>(kind: Kind, data: S, tags: Option<V>) -> Self
  48. where
  49. S: Into<String>,
  50. V: Into<Vec<Vec<String>>>,
  51. {
  52. let nonce = crate::secret::Secret::generate().to_string();
  53. let secret_data = SecretData {
  54. nonce,
  55. data: data.into(),
  56. tags: tags.map(|v| v.into()),
  57. };
  58. Self { kind, secret_data }
  59. }
  60. }
  61. impl Serialize for Secret {
  62. fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  63. where
  64. S: Serializer,
  65. {
  66. // Create a tuple representing the struct fields
  67. let secret_tuple = (&self.kind, &self.secret_data);
  68. // Serialize the tuple as a JSON array
  69. let mut s = serializer.serialize_tuple(2)?;
  70. s.serialize_element(&secret_tuple.0)?;
  71. s.serialize_element(&secret_tuple.1)?;
  72. s.end()
  73. }
  74. }
  75. impl TryFrom<Secret> for crate::secret::Secret {
  76. type Error = Error;
  77. fn try_from(secret: Secret) -> Result<crate::secret::Secret, Self::Error> {
  78. Ok(crate::secret::Secret::from_str(&serde_json::to_string(
  79. &secret,
  80. )?)?)
  81. }
  82. }
  83. #[cfg(test)]
  84. mod tests {
  85. use std::assert_eq;
  86. use super::*;
  87. #[test]
  88. fn test_secret_serialize() {
  89. let secret = Secret {
  90. kind: Kind::P2PK,
  91. secret_data: SecretData {
  92. nonce: "5d11913ee0f92fefdc82a6764fd2457a".to_string(),
  93. data: "026562efcfadc8e86d44da6a8adf80633d974302e62c850774db1fb36ff4cc7198"
  94. .to_string(),
  95. tags: Some(vec![vec![
  96. "key".to_string(),
  97. "value1".to_string(),
  98. "value2".to_string(),
  99. ]]),
  100. },
  101. };
  102. let secret_str = r#"["P2PK",{"nonce":"5d11913ee0f92fefdc82a6764fd2457a","data":"026562efcfadc8e86d44da6a8adf80633d974302e62c850774db1fb36ff4cc7198","tags":[["key","value1","value2"]]}]"#;
  103. assert_eq!(serde_json::to_string(&secret).unwrap(), secret_str);
  104. }
  105. }