rhi

Coordinated trade for connected markets
git clone https://radroots.dev/git/rhi.git
Log | Files | Refs | README | LICENSE

event.rs (4253B)


      1 use core::fmt;
      2 
      3 use nostr::{Event, Kind};
      4 use radroots_event_codec::decode::job::{JobEventBorrow, JobEventLike};
      5 
      6 #[derive(Clone)]
      7 pub struct NostrEventAdapter<'a> {
      8     evt: &'a Event,
      9     id_hex: String,
     10     author_hex: String,
     11 }
     12 
     13 impl fmt::Debug for NostrEventAdapter<'_> {
     14     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
     15         formatter.write_str("NostrEventAdapter([redacted])")
     16     }
     17 }
     18 
     19 impl<'a> NostrEventAdapter<'a> {
     20     #[inline]
     21     pub fn new(evt: &'a Event) -> Self {
     22         Self {
     23             evt,
     24             id_hex: evt.id.to_hex(),
     25             author_hex: evt.pubkey.to_string(),
     26         }
     27     }
     28 
     29     #[inline]
     30     fn tags_as_slices(&self) -> Vec<Vec<String>> {
     31         self.evt
     32             .tags
     33             .iter()
     34             .map(|t| t.as_slice().to_vec())
     35             .collect()
     36     }
     37 }
     38 
     39 impl<'a> JobEventBorrow<'a> for NostrEventAdapter<'a> {
     40     #[inline]
     41     fn raw_id(&'a self) -> String {
     42         self.id_hex.clone()
     43     }
     44     #[inline]
     45     fn raw_author(&'a self) -> String {
     46         self.author_hex.clone()
     47     }
     48     #[inline]
     49     fn raw_content(&'a self) -> &'a str {
     50         &self.evt.content
     51     }
     52     #[inline]
     53     fn raw_kind(&'a self) -> u32 {
     54         match self.evt.kind {
     55             Kind::Custom(v) => v as u32,
     56             _ => 0,
     57         }
     58     }
     59 }
     60 
     61 impl JobEventLike for NostrEventAdapter<'_> {
     62     fn raw_id(&self) -> String {
     63         self.id_hex.clone()
     64     }
     65     fn raw_author(&self) -> String {
     66         self.author_hex.clone()
     67     }
     68     fn raw_published_at(&self) -> u64 {
     69         self.evt.created_at.as_secs()
     70     }
     71     fn raw_kind(&self) -> u32 {
     72         match self.evt.kind {
     73             Kind::Custom(v) => v as u32,
     74             _ => 0,
     75         }
     76     }
     77     fn raw_content(&self) -> String {
     78         self.evt.content.clone()
     79     }
     80     fn raw_tags(&self) -> Vec<Vec<String>> {
     81         self.tags_as_slices()
     82     }
     83     fn raw_sig(&self) -> String {
     84         self.evt.sig.to_string()
     85     }
     86 }
     87 
     88 #[cfg(test)]
     89 #[cfg_attr(coverage_nightly, coverage(off))]
     90 mod tests {
     91     use super::NostrEventAdapter;
     92     use nostr::{Event, Keys, Kind, Tag, TagKind};
     93     use radroots_event_codec::decode::job::{JobEventBorrow, JobEventLike};
     94     use radroots_nostr::event::GenericBuilder;
     95 
     96     fn build_event(keys: &Keys, kind: Kind, tags: Vec<Tag>) -> Event {
     97         GenericBuilder::new(kind, "content")
     98             .tags(tags)
     99             .sign_with_keys(keys)
    100             .expect("event must sign")
    101     }
    102 
    103     #[test]
    104     fn adapter_exposes_borrow_and_owned_fields_for_custom_kind() {
    105         let keys = Keys::generate();
    106         let recipient = Keys::generate();
    107         let recipient_hex = recipient.public_key().to_hex();
    108         let tags = vec![Tag::custom(TagKind::p(), vec![recipient_hex.clone()])];
    109         let event = build_event(&keys, Kind::Custom(5322), tags);
    110         let adapter = NostrEventAdapter::new(&event);
    111         assert_eq!(format!("{adapter:?}"), "NostrEventAdapter([redacted])");
    112 
    113         assert_eq!(JobEventBorrow::raw_id(&adapter), event.id.to_hex());
    114         assert_eq!(
    115             JobEventBorrow::raw_author(&adapter),
    116             event.pubkey.to_string()
    117         );
    118         assert_eq!(JobEventBorrow::raw_content(&adapter), "content");
    119         assert_eq!(JobEventBorrow::raw_kind(&adapter), 5322);
    120 
    121         assert_eq!(JobEventLike::raw_id(&adapter), event.id.to_hex());
    122         assert_eq!(JobEventLike::raw_author(&adapter), event.pubkey.to_string());
    123         assert_eq!(JobEventLike::raw_content(&adapter), "content".to_string());
    124         assert_eq!(JobEventLike::raw_kind(&adapter), 5322);
    125         assert_eq!(
    126             JobEventLike::raw_tags(&adapter),
    127             vec![vec!["p".to_string(), recipient_hex]]
    128         );
    129         assert_eq!(JobEventLike::raw_sig(&adapter), event.sig.to_string());
    130     }
    131 
    132     #[test]
    133     fn adapter_maps_non_custom_kind_to_zero() {
    134         let keys = Keys::generate();
    135         let event = build_event(&keys, Kind::Repost, Vec::new());
    136         let adapter = NostrEventAdapter::new(&event);
    137 
    138         assert_eq!(JobEventBorrow::raw_kind(&adapter), 0);
    139         assert_eq!(JobEventLike::raw_kind(&adapter), 0);
    140         assert_eq!(
    141             JobEventLike::raw_published_at(&adapter),
    142             event.created_at.as_secs()
    143         );
    144     }
    145 }