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 }