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 }