note.rs (3648B)
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, "NoteId({})", self.hex()) 13 } 14 } 15 16 static HRP_NOTE: bech32::Hrp = 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()?); 33 Ok(evid) 34 } 35 36 pub fn to_bech(&self) -> Option<String> { 37 bech32::encode::<bech32::Bech32>(HRP_NOTE, &self.0).ok() 38 } 39 40 pub fn from_bech(bech: &str) -> Option<Self> { 41 let (hrp, data) = bech32::decode(bech).ok()?; 42 43 if hrp != HRP_NOTE { 44 return None; 45 } 46 47 Some(NoteId::new(data.try_into().ok()?)) 48 } 49 } 50 51 /// Event is the struct used to represent a Nostr event 52 #[derive(Serialize, Deserialize, Debug, Clone)] 53 pub struct Note { 54 /// 32-bytes sha256 of the the serialized event data 55 pub id: NoteId, 56 /// 32-bytes hex-encoded public key of the event creator 57 pub pubkey: Pubkey, 58 /// unix timestamp in seconds 59 pub created_at: u64, 60 /// integer 61 /// 0: NostrEvent 62 pub kind: u64, 63 /// Tags 64 pub tags: Vec<Vec<String>>, 65 /// arbitrary string 66 pub content: String, 67 /// 64-bytes signature of the sha256 hash of the serialized event data, which is the same as the "id" field 68 pub sig: String, 69 } 70 71 // Implement Hash trait 72 impl Hash for Note { 73 fn hash<H: Hasher>(&self, state: &mut H) { 74 self.id.0.hash(state); 75 } 76 } 77 78 impl PartialEq for Note { 79 fn eq(&self, other: &Self) -> bool { 80 self.id == other.id 81 } 82 } 83 84 impl Eq for Note {} 85 86 impl Note { 87 pub fn from_json(s: &str) -> Result<Self, Error> { 88 serde_json::from_str(s).map_err(Into::into) 89 } 90 91 pub fn verify(&self) -> Result<Self, Error> { 92 Err(Error::InvalidSignature) 93 } 94 95 /// This is just for serde sanity checking 96 #[allow(dead_code)] 97 pub(crate) fn new_dummy( 98 id: &str, 99 pubkey: &str, 100 created_at: u64, 101 kind: u64, 102 tags: Vec<Vec<String>>, 103 content: &str, 104 sig: &str, 105 ) -> Result<Self, Error> { 106 Ok(Note { 107 id: NoteId::from_hex(id)?, 108 pubkey: Pubkey::from_hex(pubkey)?, 109 created_at, 110 kind, 111 tags, 112 content: content.to_string(), 113 sig: sig.to_string(), 114 }) 115 } 116 } 117 118 impl std::str::FromStr for Note { 119 type Err = Error; 120 121 fn from_str(s: &str) -> Result<Self, Error> { 122 Note::from_json(s) 123 } 124 } 125 126 // Custom serialize function for Pubkey 127 impl Serialize for NoteId { 128 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 129 where 130 S: Serializer, 131 { 132 serializer.serialize_str(&self.hex()) 133 } 134 } 135 136 // Custom deserialize function for Pubkey 137 impl<'de> Deserialize<'de> for NoteId { 138 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 139 where 140 D: Deserializer<'de>, 141 { 142 let s = String::deserialize(deserializer)?; 143 NoteId::from_hex(&s).map_err(serde::de::Error::custom) 144 } 145 } 146 147 impl hashbrown::Equivalent<NoteId> for &[u8; 32] { 148 fn equivalent(&self, key: &NoteId) -> bool { 149 self.as_slice() == key.bytes() 150 } 151 }