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 }