lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

event.rs (4394B)


      1 //! Portable conversion between Radroots events and Nostr protocol events.
      2 //!
      3 //! Upstream protocol values remain confined to this explicit adapter boundary;
      4 //! canonical Radroots event and coordinate values cross it through validated,
      5 //! deterministic conversions.
      6 
      7 use alloc::string::ToString;
      8 
      9 use radroots_event::id::Nip01Coordinate;
     10 
     11 use crate::Error;
     12 
     13 #[cfg(feature = "events")]
     14 pub use crate::codec_adapters::{
     15     to_job_feedback_index, to_job_feedback_metadata, to_job_request_index, to_job_request_metadata,
     16     to_job_result_index, to_job_result_metadata,
     17 };
     18 #[cfg(feature = "events")]
     19 pub use crate::event_verify::{
     20     NostrSignatureVerifier as SignatureVerifier, Verification, verify_event as verify,
     21     verify_event_id as verify_id,
     22 };
     23 #[cfg(feature = "events")]
     24 pub use crate::events::{
     25     application_handler::{
     26         ApplicationHandlerSpec, build_application_handler_event as build_application_handler,
     27         metadata_has_fields,
     28     },
     29     calendar::{
     30         CalendarEventBuilder, build_calendar_date_event as build_calendar_date,
     31         build_calendar_time_event as build_calendar_time,
     32     },
     33     comment::{Nip22CommentBuilder, build_nip22_comment_event as build_nip22_comment},
     34     deletion::{
     35         Nip09DeletionRequestBuilder,
     36         build_nip09_deletion_request_event as build_nip09_deletion_request,
     37     },
     38     food_availability::{
     39         FoodAvailabilityBuilder, build_food_availability_event as build_food_availability,
     40     },
     41     jobs::{
     42         build_event_job_feedback as build_job_feedback, build_event_job_result as build_job_result,
     43     },
     44     metadata::{ProfileBuilder, build_profile_event as build_profile},
     45     post::{
     46         PostBuilder, build_ask_event as build_ask, build_photo_update_event as build_photo_update,
     47         build_update_event as build_update, post_events_filter as post_filter,
     48     },
     49     reply::{Nip10ReplyBuilder, build_nip10_reply_event as build_nip10_reply},
     50 };
     51 #[cfg(feature = "events")]
     52 pub use crate::job_adapter::EventAdapter;
     53 #[cfg(feature = "events")]
     54 pub use crate::types::{ExternalSigningRequest, GenericBuilder};
     55 #[cfg(feature = "events")]
     56 pub use crate::util::{created_at_u32_saturating, event_created_at_u32_saturating};
     57 
     58 /// Upstream Nostr coordinate used only at the explicit protocol boundary.
     59 pub type Coordinate = nostr::nips::nip01::Coordinate;
     60 /// Upstream Nostr event used only at the explicit protocol boundary.
     61 pub type Event = nostr::Event;
     62 /// Upstream Nostr event identifier used only at the explicit protocol boundary.
     63 pub type EventId = nostr::EventId;
     64 /// Upstream Nostr event kind used only at the explicit protocol boundary.
     65 pub type Kind = nostr::Kind;
     66 /// Upstream Nostr metadata used only at the explicit protocol boundary.
     67 pub type Metadata = nostr::Metadata;
     68 /// Upstream Nostr timestamp used only at the explicit protocol boundary.
     69 pub type Timestamp = nostr::Timestamp;
     70 
     71 #[cfg(feature = "events")]
     72 pub use crate::event_convert::{from_nostr, pointer_from_nostr, to_nostr};
     73 
     74 /// Converts a canonical Radroots NIP-01 coordinate to its Nostr value.
     75 pub fn coordinate_to_nostr(coordinate: &Nip01Coordinate) -> Result<Coordinate, Error> {
     76     Coordinate::from_kpi_format(coordinate.as_str()).map_err(|_| Error::CoordinateConversion)
     77 }
     78 
     79 /// Converts a Nostr coordinate to the canonical Radroots NIP-01 value.
     80 pub fn coordinate_from_nostr(coordinate: &Coordinate) -> Result<Nip01Coordinate, Error> {
     81     Nip01Coordinate::parse(coordinate.to_string()).map_err(|_| Error::CoordinateConversion)
     82 }
     83 
     84 #[cfg(test)]
     85 mod tests {
     86     use super::*;
     87 
     88     const PUBLIC_KEY: &str = "585591529da0bab31b3b1b1f986611cf5f435dca84f978c89ee8a40cca7103df";
     89 
     90     #[test]
     91     fn coordinate_round_trip_is_canonical_and_rejects_invalid_kinds() {
     92         let native = Nip01Coordinate::parse(format!("30402:{PUBLIC_KEY}:listing-1"))
     93             .expect("native coordinate");
     94         let nostr = coordinate_to_nostr(&native).expect("Nostr coordinate");
     95 
     96         assert_eq!(nostr.to_string(), native.as_str());
     97         assert_eq!(
     98             coordinate_from_nostr(&nostr).expect("native coordinate"),
     99             native
    100         );
    101 
    102         let invalid = Coordinate::new(
    103             Kind::TextNote,
    104             nostr::PublicKey::from_hex(PUBLIC_KEY).expect("public key"),
    105         );
    106         assert!(matches!(
    107             coordinate_from_nostr(&invalid),
    108             Err(Error::CoordinateConversion)
    109         ));
    110     }
    111 }