notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

note.rs (2941B)


      1 use crate::{Error, Pubkey};
      2 
      3 use serde::{Deserialize, Deserializer, Serialize, Serializer};
      4 use std::hash::{Hash, Hasher};
      5 
      6 #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
      7 pub struct NoteId([u8; 32]);
      8 
      9 impl NoteId {
     10     pub fn new(bytes: [u8; 32]) -> Self {
     11         NoteId(bytes)
     12     }
     13 
     14     pub fn bytes(&self) -> &[u8; 32] {
     15         &self.0
     16     }
     17 
     18     pub fn hex(&self) -> String {
     19         hex::encode(self.bytes())
     20     }
     21 
     22     pub fn from_hex(hex_str: &str) -> Result<Self, Error> {
     23         let evid = NoteId(hex::decode(hex_str)?.as_slice().try_into().unwrap());
     24         Ok(evid)
     25     }
     26 }
     27 
     28 /// Event is the struct used to represent a Nostr event
     29 #[derive(Serialize, Deserialize, Debug, Clone)]
     30 pub struct Note {
     31     /// 32-bytes sha256 of the the serialized event data
     32     pub id: NoteId,
     33     /// 32-bytes hex-encoded public key of the event creator
     34     pub pubkey: Pubkey,
     35     /// unix timestamp in seconds
     36     pub created_at: u64,
     37     /// integer
     38     /// 0: NostrEvent
     39     pub kind: u64,
     40     /// Tags
     41     pub tags: Vec<Vec<String>>,
     42     /// arbitrary string
     43     pub content: String,
     44     /// 64-bytes signature of the sha256 hash of the serialized event data, which is the same as the "id" field
     45     pub sig: String,
     46 }
     47 
     48 // Implement Hash trait
     49 impl Hash for Note {
     50     fn hash<H: Hasher>(&self, state: &mut H) {
     51         self.id.0.hash(state);
     52     }
     53 }
     54 
     55 impl PartialEq for Note {
     56     fn eq(&self, other: &Self) -> bool {
     57         self.id == other.id
     58     }
     59 }
     60 
     61 impl Eq for Note {}
     62 
     63 impl Note {
     64     pub fn from_json(s: &str) -> Result<Self, Error> {
     65         serde_json::from_str(s).map_err(Into::into)
     66     }
     67 
     68     pub fn verify(&self) -> Result<Self, Error> {
     69         Err(Error::InvalidSignature)
     70     }
     71 
     72     /// This is just for serde sanity checking
     73     #[allow(dead_code)]
     74     pub(crate) fn new_dummy(
     75         id: &str,
     76         pubkey: &str,
     77         created_at: u64,
     78         kind: u64,
     79         tags: Vec<Vec<String>>,
     80         content: &str,
     81         sig: &str,
     82     ) -> Result<Self, Error> {
     83         Ok(Note {
     84             id: NoteId::from_hex(id)?,
     85             pubkey: Pubkey::from_hex(pubkey)?,
     86             created_at,
     87             kind,
     88             tags,
     89             content: content.to_string(),
     90             sig: sig.to_string(),
     91         })
     92     }
     93 }
     94 
     95 impl std::str::FromStr for Note {
     96     type Err = Error;
     97 
     98     fn from_str(s: &str) -> Result<Self, Error> {
     99         Note::from_json(s)
    100     }
    101 }
    102 
    103 // Custom serialize function for Pubkey
    104 impl Serialize for NoteId {
    105     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    106     where
    107         S: Serializer,
    108     {
    109         serializer.serialize_str(&self.hex())
    110     }
    111 }
    112 
    113 // Custom deserialize function for Pubkey
    114 impl<'de> Deserialize<'de> for NoteId {
    115     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    116     where
    117         D: Deserializer<'de>,
    118     {
    119         let s = String::deserialize(deserializer)?;
    120         NoteId::from_hex(&s).map_err(serde::de::Error::custom)
    121     }
    122 }