notedeck

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

note.rs (3301B)


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