diff --git a/bindings/nostr-js/src/event/builder.rs b/bindings/nostr-js/src/event/builder.rs index 40d04cd98..026a1c384 100644 --- a/bindings/nostr-js/src/event/builder.rs +++ b/bindings/nostr-js/src/event/builder.rs @@ -3,13 +3,22 @@ // Distributed under the MIT software license use core::ops::Deref; +use std::str::FromStr; use nostr::prelude::*; use wasm_bindgen::prelude::*; +use super::tag::{JsImageDimensions, JsThumbnails}; use super::{JsEvent, JsEventId, JsTag, JsUnsignedEvent}; use crate::error::{into_err, Result}; use crate::key::{JsKeys, JsPublicKey}; +use crate::nips::nip15::{JsProductData, JsStallData}; +use crate::nips::nip53::JsLiveEvent; +use crate::nips::nip57::JsZapRequestData; +use crate::nips::nip65::JsRelayListItem; +use crate::nips::nip90::JsDataVendingMachineStatus; +use crate::nips::nip94::JsFileMetadata; +use crate::nips::nip98::JsHttpData; use crate::types::{JsContact, JsMetadata, JsTimestamp}; #[wasm_bindgen(js_name = EventBuilder)] @@ -89,6 +98,13 @@ impl JsEventBuilder { } } + #[wasm_bindgen(js_name = relayList)] + pub fn relay_list(relays: Vec) -> Self { + Self { + builder: EventBuilder::relay_list(relays.into_iter().map(|r| r.into())), + } + } + #[wasm_bindgen(js_name = textNote)] pub fn text_note(content: &str, tags: Vec) -> Self { Self { @@ -96,6 +112,13 @@ impl JsEventBuilder { } } + #[wasm_bindgen(js_name = longFormTextNote)] + pub fn long_form_text_note(content: &str, tags: Vec) -> Self { + Self { + builder: EventBuilder::long_form_text_note(content, tags.into_iter().map(|t| t.into())), + } + } + #[wasm_bindgen(js_name = contactList)] pub fn contact_list(list: Vec) -> Self { let list = list.into_iter().map(|c| c.inner()); @@ -201,6 +224,180 @@ impl JsEventBuilder { }) } + #[wasm_bindgen(js_name = liveEvent)] + pub fn live_event(live_event: JsLiveEvent) -> Self { + Self { + builder: EventBuilder::live_event(live_event.into()), + } + } + + #[wasm_bindgen(js_name = liveEventMsg)] + pub fn live_event_msg( + live_event_id: String, + live_event_host: JsPublicKey, + content: String, + relay_url: Option, + tags: Vec, + ) -> Result { + Ok(Self { + builder: EventBuilder::live_event_msg( + live_event_id, + live_event_host.deref().to_owned(), + content, + match relay_url { + Some(url) => Some(Url::from_str(&url).map_err(into_err)?), + None => None, + }, + tags.into_iter().map(|t| t.into()).collect(), + ), + }) + } + + #[wasm_bindgen] + pub fn report(tags: Vec, content: String) -> Self { + Self { + builder: EventBuilder::report(tags.into_iter().map(|t| t.into()), content), + } + } + + #[wasm_bindgen(js_name = publicZapRequest)] + pub fn public_zap_request(data: JsZapRequestData) -> Self { + Self { + builder: EventBuilder::public_zap_request(data.deref().clone()), + } + } + + #[wasm_bindgen(js_name = zapReceipt)] + pub fn zap_receipt(bolt11: String, preimage: Option, zap_request: JsEvent) -> Self { + Self { + builder: EventBuilder::zap_receipt(bolt11, preimage, zap_request.deref().to_owned()), + } + } + + #[wasm_bindgen(js_name = defineBadge)] + pub fn define_badge( + badge_id: String, + name: Option, + description: Option, + image: Option, + image_dimensions: Option, + thumbnails: Vec, + ) -> Self { + Self { + builder: EventBuilder::define_badge( + badge_id, + name, + description, + image.map(UncheckedUrl::from), + image_dimensions.map(|i| i.into()), + thumbnails.into_iter().map(|t| t.into()).collect(), + ), + } + } + + #[wasm_bindgen(js_name = awardBadge)] + pub fn award_badge( + badge_definition: &JsEvent, + awarded_pubkeys: Vec, + ) -> Result { + Ok(Self { + builder: EventBuilder::award_badge( + badge_definition.deref(), + awarded_pubkeys.into_iter().map(|t| t.into()), + ) + .map_err(into_err)?, + }) + } + + #[wasm_bindgen(js_name = profileBadges)] + pub fn profile_badges( + badge_definitions: Vec, + badge_awards: Vec, + pubkey_awarded: &JsPublicKey, + ) -> Result { + Ok(Self { + builder: EventBuilder::profile_badges( + badge_definitions.into_iter().map(|e| e.into()).collect(), + badge_awards.into_iter().map(|e| e.into()).collect(), + pubkey_awarded.deref(), + ) + .map_err(into_err)?, + }) + } + + #[wasm_bindgen(js_name = jobRequest)] + pub fn job_request(kind: f64, tags: Vec) -> Result { + Ok(Self { + builder: EventBuilder::job_request(kind.into(), tags.into_iter().map(|t| t.into())) + .map_err(into_err)?, + }) + } + + #[wasm_bindgen(js_name = jobResult)] + pub fn job_result( + job_request: &JsEvent, + amount_millisats: f64, + bolt11: Option, + ) -> Result { + Ok(Self { + builder: EventBuilder::job_result( + job_request.deref().clone(), + amount_millisats as u64, + bolt11, + ) + .map_err(into_err)?, + }) + } + + #[wasm_bindgen(js_name = jobFeedback)] + pub fn job_feedback( + job_request: &JsEvent, + status: JsDataVendingMachineStatus, + extra_info: Option, + amount_millisats: u64, + bolt11: Option, + payload: Option, + ) -> Self { + Self { + builder: EventBuilder::job_feedback( + job_request.deref(), + status.into(), + extra_info, + amount_millisats, + bolt11, + payload, + ), + } + } + + #[wasm_bindgen(js_name = fileMetadata)] + pub fn file_metadata(description: String, metadata: JsFileMetadata) -> Self { + Self { + builder: EventBuilder::file_metadata(description, metadata.deref().clone()), + } + } + + #[wasm_bindgen(js_name = httpAuth)] + pub fn http_auth(data: JsHttpData) -> Self { + Self { + builder: EventBuilder::http_auth(data.into()), + } + } + + #[wasm_bindgen(js_name = stallData)] + pub fn stall_data(data: &JsStallData) -> Self { + Self { + builder: EventBuilder::stall_data(data.deref().clone()), + } + } + + #[wasm_bindgen(js_name = productData)] + pub fn product_data(data: JsProductData) -> Self { + Self { + builder: EventBuilder::product_data(data.into()), + } + } + /// Gift Wrap from seal /// /// diff --git a/bindings/nostr-js/src/event/mod.rs b/bindings/nostr-js/src/event/mod.rs index b8af9448b..bf75babae 100644 --- a/bindings/nostr-js/src/event/mod.rs +++ b/bindings/nostr-js/src/event/mod.rs @@ -9,7 +9,7 @@ use wasm_bindgen::prelude::*; mod builder; mod id; -mod tag; +pub mod tag; mod unsigned; pub use self::builder::JsEventBuilder; diff --git a/bindings/nostr-js/src/event/tag.rs b/bindings/nostr-js/src/event/tag.rs index 0ad18a373..ac7a6d1ea 100644 --- a/bindings/nostr-js/src/event/tag.rs +++ b/bindings/nostr-js/src/event/tag.rs @@ -2,11 +2,115 @@ // Copyright (c) 2023-2024 Rust Nostr Developers // Distributed under the MIT software license -use nostr::Tag; +use nostr::prelude::*; use wasm_bindgen::prelude::*; use crate::error::{into_err, Result}; +#[wasm_bindgen(js_name = HttpMethod)] +pub enum JsHttpMethod { + GET, + POST, + PUT, + PATCH, +} + +impl From for JsHttpMethod { + fn from(value: HttpMethod) -> Self { + match value { + HttpMethod::GET => Self::GET, + HttpMethod::POST => Self::POST, + HttpMethod::PUT => Self::PUT, + HttpMethod::PATCH => Self::PATCH, + } + } +} + +impl From for HttpMethod { + fn from(value: JsHttpMethod) -> Self { + match value { + JsHttpMethod::GET => Self::GET, + JsHttpMethod::POST => Self::POST, + JsHttpMethod::PUT => Self::PUT, + JsHttpMethod::PATCH => Self::PATCH, + } + } +} + +#[wasm_bindgen(js_name = Thumbnails)] +pub struct JsThumbnails { + #[wasm_bindgen(getter_with_clone)] + pub url: String, + pub dimensions: Option, +} + +impl From for (UncheckedUrl, Option) { + fn from(value: JsThumbnails) -> Self { + ( + UncheckedUrl::from(value.url), + value.dimensions.map(|r| r.into()), + ) + } +} + +#[wasm_bindgen(js_class = Thumbnails)] +impl JsThumbnails { + #[wasm_bindgen(constructor)] + pub fn new(url: String, dimensions: Option) -> Self { + Self { url, dimensions } + } +} + +#[derive(Clone, Copy)] +#[wasm_bindgen(js_name = ImageDimensions)] +pub struct JsImageDimensions { + pub width: u64, + pub height: u64, +} + +impl From for JsImageDimensions { + fn from(value: ImageDimensions) -> Self { + Self { + width: value.width, + height: value.height, + } + } +} + +impl From for ImageDimensions { + fn from(value: JsImageDimensions) -> Self { + Self { + width: value.width, + height: value.height, + } + } +} + +#[derive(Clone, Copy)] +#[wasm_bindgen(js_name = RelayMetadata)] +pub enum JsRelayMetadata { + Read, + Write, +} + +impl From for JsRelayMetadata { + fn from(value: RelayMetadata) -> Self { + match value { + RelayMetadata::Read => Self::Read, + RelayMetadata::Write => Self::Write, + } + } +} + +impl From for RelayMetadata { + fn from(value: JsRelayMetadata) -> Self { + match value { + JsRelayMetadata::Read => Self::Read, + JsRelayMetadata::Write => Self::Write, + } + } +} + #[wasm_bindgen(js_name = Tag)] pub struct JsTag { inner: Tag, @@ -33,6 +137,10 @@ impl JsTag { }) } + pub fn kind(&self) -> String { + self.inner.kind().to_string() + } + /// Get tag as vector of string #[wasm_bindgen(js_name = asVec)] pub fn as_vec(&self) -> Vec { diff --git a/bindings/nostr-js/src/key/public_key.rs b/bindings/nostr-js/src/key/public_key.rs index 4db33e854..fde2786cc 100644 --- a/bindings/nostr-js/src/key/public_key.rs +++ b/bindings/nostr-js/src/key/public_key.rs @@ -9,6 +9,7 @@ use wasm_bindgen::prelude::*; use crate::error::{into_err, Result}; +#[derive(Clone, Copy)] #[wasm_bindgen(js_name = PublicKey)] pub struct JsPublicKey { pub(crate) inner: PublicKey, diff --git a/bindings/nostr-js/src/nips/mod.rs b/bindings/nostr-js/src/nips/mod.rs index 45abfd6ea..cd1cabc13 100644 --- a/bindings/nostr-js/src/nips/mod.rs +++ b/bindings/nostr-js/src/nips/mod.rs @@ -2,14 +2,21 @@ // Copyright (c) 2023-2024 Rust Nostr Developers // Distributed under the MIT software license +pub mod nip01; pub mod nip04; pub mod nip05; pub mod nip07; pub mod nip11; +pub mod nip15; pub mod nip19; pub mod nip26; pub mod nip44; pub mod nip46; pub mod nip47; pub mod nip49; +pub mod nip53; pub mod nip57; +pub mod nip65; +pub mod nip90; +pub mod nip94; +pub mod nip98; diff --git a/bindings/nostr-js/src/nips/nip01.rs b/bindings/nostr-js/src/nips/nip01.rs new file mode 100644 index 000000000..4f3d40842 --- /dev/null +++ b/bindings/nostr-js/src/nips/nip01.rs @@ -0,0 +1,69 @@ +// Copyright (c) 2023-2024 Rust Nostr Developers +// Distributed under the MIT software license + +use std::ops::Deref; + +use nostr::nips::nip01::Coordinate; +use nostr::Kind; +use wasm_bindgen::prelude::*; + +use crate::key::JsPublicKey; + +#[wasm_bindgen(js_name = Coordinate)] +pub struct JsCoordinate { + inner: Coordinate, +} + +impl Deref for JsCoordinate { + type Target = Coordinate; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl From for JsCoordinate { + fn from(inner: Coordinate) -> Self { + Self { inner } + } +} + +#[wasm_bindgen(js_class = Coordinate)] +impl JsCoordinate { + #[wasm_bindgen(constructor)] + pub fn new( + kind: f64, + public_key: &JsPublicKey, + identifier: Option, + relays: Option>, + ) -> Self { + Self { + inner: Coordinate { + kind: Kind::from(kind), + public_key: **public_key, + identifier: identifier.unwrap_or_default(), + relays: relays.unwrap_or_default(), + }, + } + } + + #[wasm_bindgen(getter)] + pub fn kind(&self) -> f64 { + self.inner.kind.as_f64() + } + + #[wasm_bindgen(getter, js_name = publicKey)] + pub fn public_key(&self) -> JsPublicKey { + self.inner.public_key.into() + } + + #[wasm_bindgen(getter)] + pub fn identifier(&self) -> String { + self.inner.identifier.clone() + } + + #[wasm_bindgen(getter)] + pub fn relays(&self) -> Vec { + self.inner.relays.clone() + } +} diff --git a/bindings/nostr-js/src/nips/nip15.rs b/bindings/nostr-js/src/nips/nip15.rs new file mode 100644 index 000000000..abaebda45 --- /dev/null +++ b/bindings/nostr-js/src/nips/nip15.rs @@ -0,0 +1,241 @@ +// Copyright (c) 2023-2024 Rust Nostr Developers +// Distributed under the MIT software license + +use std::ops::Deref; + +use js_sys::Array; +use nostr::nips::nip15::{ProductData, ShippingCost, ShippingMethod, StallData}; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(typescript_type = "string[]")] + pub type JsStringArray; +} + +#[wasm_bindgen(js_name = ShippingCost)] +pub struct JsShippingCost { + inner: ShippingCost, +} + +impl From for JsShippingCost { + fn from(inner: ShippingCost) -> Self { + Self { inner } + } +} + +#[wasm_bindgen(js_class = ShippingCost)] +impl JsShippingCost { + #[wasm_bindgen(getter)] + pub fn id(&self) -> String { + self.inner.id.clone() + } + + #[wasm_bindgen(getter)] + pub fn cost(&self) -> f64 { + self.inner.cost + } +} + +#[wasm_bindgen(js_name = ShippingMethod)] +pub struct JsShippingMethod { + inner: ShippingMethod, +} + +impl From for JsShippingMethod { + fn from(inner: ShippingMethod) -> Self { + Self { inner } + } +} + +impl Deref for JsShippingMethod { + type Target = ShippingMethod; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +#[wasm_bindgen(js_class = ShippingMethod)] +impl JsShippingMethod { + #[wasm_bindgen(constructor)] + pub fn new(id: &str, cost: f64) -> Self { + ShippingMethod::new(id, cost).into() + } + + #[wasm_bindgen(js_name = getShuppingCost)] + pub fn get_shipping_cost(&self) -> JsShippingCost { + ShippingMethod::get_shipping_cost(self.deref()).into() + } + + #[wasm_bindgen(getter)] + pub fn id(&self) -> String { + self.inner.id.clone() + } + + #[wasm_bindgen(getter)] + pub fn name(&self) -> Option { + self.inner.name.clone() + } + + #[wasm_bindgen(getter)] + pub fn cost(&self) -> f64 { + self.inner.cost + } + + #[wasm_bindgen(getter)] + pub fn regions(&self) -> Vec { + self.inner.regions.clone() + } +} + +#[wasm_bindgen(js_name = StallData)] +pub struct JsStallData { + inner: StallData, +} + +impl From for JsStallData { + fn from(inner: StallData) -> Self { + Self { inner } + } +} + +impl Deref for JsStallData { + type Target = StallData; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +#[wasm_bindgen(js_class = StallData)] +impl JsStallData { + #[wasm_bindgen(constructor)] + pub fn new(id: &str, name: &str, currency: &str) -> Self { + StallData::new(id, name, currency).into() + } + + #[wasm_bindgen(getter)] + pub fn id(&self) -> String { + self.inner.id.clone() + } + + #[wasm_bindgen(getter)] + pub fn name(&self) -> String { + self.inner.name.clone() + } + + #[wasm_bindgen(getter)] + pub fn description(&self) -> Option { + self.inner.description.clone() + } + + #[wasm_bindgen(getter)] + pub fn currency(&self) -> String { + self.inner.currency.clone() + } + + #[wasm_bindgen(getter)] + pub fn shipping(&self) -> Vec { + self.inner + .shipping + .clone() + .into_iter() + .map(|s| s.into()) + .collect() + } +} + +#[wasm_bindgen(js_name = ProductData)] +pub struct JsProductData { + inner: ProductData, +} + +impl From for JsProductData { + fn from(inner: ProductData) -> Self { + Self { inner } + } +} + +impl From for ProductData { + fn from(value: JsProductData) -> Self { + value.inner + } +} + +#[wasm_bindgen(js_class = ProductData)] +impl JsProductData { + #[wasm_bindgen(constructor)] + pub fn new(id: &str, stall_id: &str, name: &str, currency: &str) -> Self { + ProductData::new(id, stall_id, name, currency).into() + } + + #[wasm_bindgen(getter)] + pub fn id(&self) -> String { + self.inner.id.clone() + } + + #[wasm_bindgen(getter, js_name = stallId)] + pub fn stall_id(&self) -> String { + self.inner.stall_id.clone() + } + + #[wasm_bindgen(getter)] + pub fn name(&self) -> String { + self.inner.name.clone() + } + + #[wasm_bindgen(getter)] + pub fn description(&self) -> Option { + self.inner.description.clone() + } + + #[wasm_bindgen(getter)] + pub fn images(&self) -> Option> { + self.inner.images.clone() + } + + #[wasm_bindgen(getter)] + pub fn currency(&self) -> String { + self.inner.currency.clone() + } + + #[wasm_bindgen(getter)] + pub fn price(&self) -> f64 { + self.inner.price + } + + #[wasm_bindgen(getter)] + pub fn quantity(&self) -> f64 { + self.inner.quantity as f64 + } + + #[wasm_bindgen(getter)] + pub fn specs(&self) -> Option> { + self.inner.specs.clone().map(|v| { + v.into_iter() + .map(|s| { + s.into_iter() + .map(JsValue::from) + .collect::() + .unchecked_into() + }) + .collect() + }) + } + + #[wasm_bindgen(getter)] + pub fn shipping(&self) -> Vec { + self.inner + .shipping + .clone() + .into_iter() + .map(|s| s.into()) + .collect() + } + + #[wasm_bindgen(getter)] + pub fn categories(&self) -> Option> { + self.inner.categories.clone() + } +} diff --git a/bindings/nostr-js/src/nips/nip47.rs b/bindings/nostr-js/src/nips/nip47.rs index 99b170db5..4f17d412b 100644 --- a/bindings/nostr-js/src/nips/nip47.rs +++ b/bindings/nostr-js/src/nips/nip47.rs @@ -28,6 +28,7 @@ impl Deref for JsNostrWalletConnectURI { #[wasm_bindgen(js_class = NostrWalletConnectURI)] impl JsNostrWalletConnectURI { /// Create new Nostr Wallet Connect URI + #[wasm_bindgen(constructor)] pub fn new( public_key: &JsPublicKey, relay_url: &str, diff --git a/bindings/nostr-js/src/nips/nip53.rs b/bindings/nostr-js/src/nips/nip53.rs new file mode 100644 index 000000000..57d2d3170 --- /dev/null +++ b/bindings/nostr-js/src/nips/nip53.rs @@ -0,0 +1,258 @@ +// Copyright (c) 2023-2024 Rust Nostr Developers +// Distributed under the MIT software license + +use std::ops::Deref; + +use nostr::nips::nip53::{LiveEvent, LiveEventHost, LiveEventStatus}; +use nostr::{ImageDimensions, PublicKey, UncheckedUrl}; +use wasm_bindgen::prelude::*; + +use crate::event::tag::JsImageDimensions; +use crate::key::JsPublicKey; + +#[wasm_bindgen(js_name = Image)] +pub struct JsImage { + #[wasm_bindgen(getter_with_clone)] + pub url: String, + pub dimensions: Option, +} + +impl From<(UncheckedUrl, Option)> for JsImage { + fn from(value: (UncheckedUrl, Option)) -> Self { + Self { + url: value.0.to_string(), + dimensions: value.1.map(|d| d.into()), + } + } +} + +#[wasm_bindgen(js_class = Image)] +impl JsImage { + #[wasm_bindgen(constructor)] + pub fn new(url: String, dimensions: Option) -> Self { + Self { url, dimensions } + } +} + +#[wasm_bindgen(js_name = User)] +pub struct JsUser { + #[wasm_bindgen(js_name = publicKey)] + pub public_key: JsPublicKey, + #[wasm_bindgen(getter_with_clone)] + pub url: Option, +} + +impl From<(PublicKey, Option)> for JsUser { + fn from(value: (PublicKey, Option)) -> Self { + Self { + public_key: value.0.into(), + url: value.1.map(|url| url.to_string()), + } + } +} + +#[wasm_bindgen(js_class = User)] +impl JsUser { + #[wasm_bindgen(constructor)] + pub fn new(public_key: JsPublicKey, url: Option) -> Self { + Self { public_key, url } + } +} + +#[wasm_bindgen(js_name = LiveEventStatus)] +pub struct JsLiveEventStatus { + inner: LiveEventStatus, +} + +impl From for JsLiveEventStatus { + fn from(inner: LiveEventStatus) -> Self { + Self { inner } + } +} + +impl Deref for JsLiveEventStatus { + type Target = LiveEventStatus; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +#[wasm_bindgen(js_class = LiveEventStatus)] +impl JsLiveEventStatus { + pub fn planned() -> Self { + Self { + inner: LiveEventStatus::Planned, + } + } + + pub fn live() -> Self { + Self { + inner: LiveEventStatus::Live, + } + } + + pub fn ended() -> Self { + Self { + inner: LiveEventStatus::Ended, + } + } + + pub fn custom(string: String) -> Self { + Self { + inner: LiveEventStatus::Custom(string), + } + } +} + +#[wasm_bindgen(js_name = LiveEventHost)] +pub struct JsLiveEventHost { + inner: LiveEventHost, +} + +impl From for JsLiveEventHost { + fn from(inner: LiveEventHost) -> Self { + Self { inner } + } +} + +impl Deref for JsLiveEventHost { + type Target = LiveEventHost; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +#[wasm_bindgen(js_class = LiveEventHost)] +impl JsLiveEventHost { + #[wasm_bindgen(getter, js_name = publicKey)] + pub fn public_key(&self) -> JsPublicKey { + self.inner.public_key.into() + } + + #[wasm_bindgen(getter, js_name = relayUrl)] + pub fn relay_url(&self) -> Option { + self.inner.relay_url.clone().map(|url| url.to_string()) + } + + #[wasm_bindgen(getter)] + pub fn proof(&self) -> Option { + self.inner.proof.map(|s| s.to_string()) + } +} + +#[wasm_bindgen(js_name = LiveEvent)] +pub struct JsLiveEvent { + inner: LiveEvent, +} + +impl From for JsLiveEvent { + fn from(inner: LiveEvent) -> Self { + Self { inner } + } +} + +impl From for LiveEvent { + fn from(value: JsLiveEvent) -> Self { + value.inner + } +} + +#[wasm_bindgen(js_class = LiveEvent)] +impl JsLiveEvent { + #[wasm_bindgen(getter)] + pub fn id(&self) -> String { + self.inner.id.clone() + } + + #[wasm_bindgen(getter)] + pub fn title(&self) -> Option { + self.inner.title.clone() + } + + #[wasm_bindgen(getter)] + pub fn summary(&self) -> Option { + self.inner.summary.clone() + } + + #[wasm_bindgen(getter)] + pub fn image(&self) -> Option { + self.inner.image.clone().map(|i| i.into()) + } + + #[wasm_bindgen(getter)] + pub fn hashtags(&self) -> Vec { + self.inner.hashtags.clone() + } + + #[wasm_bindgen(getter)] + pub fn streaming(&self) -> Option { + self.inner.streaming.clone().map(|url| url.to_string()) + } + + #[wasm_bindgen(getter)] + pub fn recording(&self) -> Option { + self.inner.recording.clone().map(|url| url.to_string()) + } + + #[wasm_bindgen(getter)] + pub fn starts(&self) -> Option { + self.inner.starts.map(|t| t.as_i64() as f64) + } + + #[wasm_bindgen(getter)] + pub fn ends(&self) -> Option { + self.inner.ends.map(|t| t.as_i64() as f64) + } + + #[wasm_bindgen(getter)] + pub fn status(&self) -> Option { + self.inner.status.clone().map(|s| s.into()) + } + + #[wasm_bindgen(getter, js_name = currentPartecipants)] + pub fn current_participants(&self) -> Option { + self.inner.current_participants.map(|s| s as f64) + } + + #[wasm_bindgen(getter, js_name = totalPartecipants)] + pub fn total_participants(&self) -> Option { + self.inner.total_participants.map(|s| s as f64) + } + + #[wasm_bindgen(getter)] + pub fn relays(&self) -> Vec { + self.inner + .relays + .clone() + .into_iter() + .map(|url| url.to_string()) + .collect() + } + + #[wasm_bindgen(getter)] + pub fn host(&self) -> Option { + self.inner.host.clone().map(|s| s.into()) + } + + #[wasm_bindgen(getter)] + pub fn speakers(&self) -> Vec { + self.inner + .speakers + .clone() + .into_iter() + .map(|u| u.into()) + .collect() + } + + #[wasm_bindgen(getter)] + pub fn participants(&self) -> Vec { + self.inner + .participants + .clone() + .into_iter() + .map(|u| u.into()) + .collect() + } +} diff --git a/bindings/nostr-js/src/nips/nip57.rs b/bindings/nostr-js/src/nips/nip57.rs index 614b8feff..6ed6cdf2b 100644 --- a/bindings/nostr-js/src/nips/nip57.rs +++ b/bindings/nostr-js/src/nips/nip57.rs @@ -2,9 +2,16 @@ // Copyright (c) 2023-2024 Rust Nostr Developers // Distributed under the MIT software license -use nostr::nips::nip57::ZapType; +use std::ops::Deref; + +use nostr::nips::nip57::{ZapRequestData, ZapType}; +use nostr::UncheckedUrl; use wasm_bindgen::prelude::*; +use super::nip01::JsCoordinate; +use crate::event::JsEventId; +use crate::key::JsPublicKey; + #[wasm_bindgen(js_name = ZapType)] pub enum JsZapType { /// Public @@ -34,3 +41,88 @@ impl From for JsZapType { } } } + +#[wasm_bindgen(js_name = ZapRequestData)] +pub struct JsZapRequestData { + inner: ZapRequestData, +} + +impl From for JsZapRequestData { + fn from(inner: ZapRequestData) -> Self { + Self { inner } + } +} + +impl Deref for JsZapRequestData { + type Target = ZapRequestData; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +#[wasm_bindgen(js_class = ZapRequestData)] +impl JsZapRequestData { + #[wasm_bindgen(constructor)] + pub fn new( + public_key: &JsPublicKey, + relays: Vec, + message: String, + amount: Option, + lnurl: Option, + event_id: Option, + event_coordinate: Option, + ) -> Self { + Self { + inner: ZapRequestData { + public_key: **public_key, + relays: relays.into_iter().map(|r| UncheckedUrl::from(&r)).collect(), + message, + amount: amount.map(|n| n as u64), + lnurl, + event_id: event_id.map(|e| *e.deref()), + event_coordinate: event_coordinate.map(|e| e.deref().clone()), + }, + } + } + + #[wasm_bindgen(getter, js_name = publicKey)] + pub fn public_key(&self) -> JsPublicKey { + self.inner.public_key.into() + } + + #[wasm_bindgen(getter)] + pub fn relays(&self) -> Vec { + self.inner + .relays + .clone() + .into_iter() + .map(|url| url.to_string()) + .collect() + } + + #[wasm_bindgen(getter)] + pub fn message(&self) -> String { + self.inner.message.clone() + } + + #[wasm_bindgen(getter)] + pub fn amount(&self) -> Option { + self.inner.amount.map(|n| n as f64) + } + + #[wasm_bindgen(getter)] + pub fn lnurl(&self) -> Option { + self.inner.lnurl.clone() + } + + #[wasm_bindgen(getter, js_name = eventID)] + pub fn event_id(&self) -> Option { + self.inner.event_id.map(|e| e.into()) + } + + #[wasm_bindgen(getter, js_name = eventCoordinate)] + pub fn event_coordinate(&self) -> Option { + self.inner.event_coordinate.clone().map(|e| e.into()) + } +} diff --git a/bindings/nostr-js/src/nips/nip65.rs b/bindings/nostr-js/src/nips/nip65.rs new file mode 100644 index 000000000..7d18c8a96 --- /dev/null +++ b/bindings/nostr-js/src/nips/nip65.rs @@ -0,0 +1,46 @@ +// Copyright (c) 2023-2024 Rust Nostr Developers +// Distributed under the MIT software license + +use std::ops::Deref; + +use nostr::nips::nip65; +use nostr::{RelayMetadata, UncheckedUrl}; +use wasm_bindgen::prelude::*; + +use crate::event::tag::JsRelayMetadata; +use crate::event::JsEvent; + +#[wasm_bindgen(js_name = RelayListItem)] +pub struct JsRelayListItem { + #[wasm_bindgen(getter_with_clone)] + pub url: String, + pub metadata: Option, +} + +impl From for (UncheckedUrl, Option) { + fn from(value: JsRelayListItem) -> Self { + ( + UncheckedUrl::from(value.url), + value.metadata.map(|r| r.into()), + ) + } +} + +#[wasm_bindgen(js_class = RelayListItem)] +impl JsRelayListItem { + #[wasm_bindgen(constructor)] + pub fn new(url: String, metadata: Option) -> Self { + Self { url, metadata } + } +} + +#[wasm_bindgen(js_name = extractRelayList)] +pub fn extract_relay_list(event: &JsEvent) -> Vec { + nip65::extract_relay_list(event.deref()) + .into_iter() + .map(|(s, r)| JsRelayListItem { + url: s.to_string(), + metadata: r.map(|r| r.into()), + }) + .collect() +} diff --git a/bindings/nostr-js/src/nips/nip90.rs b/bindings/nostr-js/src/nips/nip90.rs new file mode 100644 index 000000000..79f30b7bd --- /dev/null +++ b/bindings/nostr-js/src/nips/nip90.rs @@ -0,0 +1,38 @@ +// Copyright (c) 2023-2024 Rust Nostr Developers +// Distributed under the MIT software license + +use nostr::nips::nip90::DataVendingMachineStatus; +use wasm_bindgen::prelude::*; + +#[wasm_bindgen(js_name = DataVendingMachineStatus)] +pub enum JsDataVendingMachineStatus { + PaymentRequired, + Processing, + Error, + Success, + Partial, +} + +impl From for JsDataVendingMachineStatus { + fn from(value: DataVendingMachineStatus) -> Self { + match value { + DataVendingMachineStatus::PaymentRequired => Self::PaymentRequired, + DataVendingMachineStatus::Processing => Self::Processing, + DataVendingMachineStatus::Error => Self::Error, + DataVendingMachineStatus::Success => Self::Success, + DataVendingMachineStatus::Partial => Self::Partial, + } + } +} + +impl From for DataVendingMachineStatus { + fn from(value: JsDataVendingMachineStatus) -> Self { + match value { + JsDataVendingMachineStatus::PaymentRequired => Self::PaymentRequired, + JsDataVendingMachineStatus::Processing => Self::Processing, + JsDataVendingMachineStatus::Error => Self::Error, + JsDataVendingMachineStatus::Success => Self::Success, + JsDataVendingMachineStatus::Partial => Self::Partial, + } + } +} diff --git a/bindings/nostr-js/src/nips/nip94.rs b/bindings/nostr-js/src/nips/nip94.rs new file mode 100644 index 000000000..e14f6b7a6 --- /dev/null +++ b/bindings/nostr-js/src/nips/nip94.rs @@ -0,0 +1,117 @@ +// Copyright (c) 2023-2024 Rust Nostr Developers +// Distributed under the MIT software license + +use std::ops::Deref; +use std::str::FromStr; + +use nostr::hashes::sha256::Hash as Sha256Hash; +use nostr::nips::nip94::FileMetadata; +use nostr::Url; +use wasm_bindgen::prelude::*; + +use crate::error::{into_err, Result}; +use crate::event::tag::JsImageDimensions; + +#[wasm_bindgen(js_name = Aes256Gcm)] +pub struct JsAes256Gcm { + #[wasm_bindgen(getter_with_clone)] + pub key: String, + #[wasm_bindgen(getter_with_clone)] + pub iv: String, +} + +impl From for (String, String) { + fn from(value: JsAes256Gcm) -> Self { + (value.key, value.iv) + } +} + +impl From<(String, String)> for JsAes256Gcm { + fn from(value: (String, String)) -> Self { + Self { + key: value.0, + iv: value.1, + } + } +} + +#[wasm_bindgen(js_class = Aes256Gcm)] +impl JsAes256Gcm { + #[wasm_bindgen(constructor)] + pub fn new(key: String, iv: String) -> Self { + Self { key, iv } + } +} + +#[wasm_bindgen(js_name = FileMetadata)] +pub struct JsFileMetadata { + inner: FileMetadata, +} + +impl From for JsFileMetadata { + fn from(inner: FileMetadata) -> Self { + Self { inner } + } +} + +impl Deref for JsFileMetadata { + type Target = FileMetadata; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +#[wasm_bindgen(js_class = FileMetadata)] +impl JsFileMetadata { + #[wasm_bindgen(constructor)] + pub fn new(url: &str, mime_type: String, hash: &str) -> Result { + Ok(Self { + inner: FileMetadata::new( + Url::from_str(url).map_err(into_err)?, + mime_type, + Sha256Hash::from_str(hash).map_err(into_err)?, + ), + }) + } + + #[wasm_bindgen(getter)] + pub fn urls(&self) -> String { + self.inner.url.to_string() + } + + #[wasm_bindgen(getter, js_name = mimeType)] + pub fn mime_type(&self) -> String { + self.inner.mime_type.clone() + } + + #[wasm_bindgen(getter)] + pub fn hash(&self) -> String { + self.inner.hash.to_string() + } + + #[wasm_bindgen(getter, js_name = aes256Gcm)] + pub fn aes_256_gcm(&self) -> Option { + self.inner.aes_256_gcm.clone().map(|t| t.into()) + } + + #[wasm_bindgen(getter)] + pub fn size(&self) -> Option { + self.inner.size.map(|n| n as f64) + } + + #[wasm_bindgen(getter)] + pub fn dim(&self) -> Option { + self.inner.dim.map(|i| i.into()) + } + + #[wasm_bindgen(getter)] + pub fn magnet(&self) -> Option { + self.inner.magnet.clone() + } + + #[wasm_bindgen(getter)] + pub fn blurhash(&self) -> Option { + self.inner.blurhash.clone() + } +} diff --git a/bindings/nostr-js/src/nips/nip98.rs b/bindings/nostr-js/src/nips/nip98.rs new file mode 100644 index 000000000..d535e3b3e --- /dev/null +++ b/bindings/nostr-js/src/nips/nip98.rs @@ -0,0 +1,48 @@ +// Copyright (c) 2023-2024 Rust Nostr Developers +// Distributed under the MIT software license + +use nostr::nips::nip98::HttpData; +use nostr::UncheckedUrl; +use wasm_bindgen::prelude::*; + +use crate::event::tag::JsHttpMethod; + +#[wasm_bindgen(js_name = HttpData)] +pub struct JsHttpData { + inner: HttpData, +} + +impl From for JsHttpData { + fn from(inner: HttpData) -> Self { + Self { inner } + } +} + +impl From for HttpData { + fn from(value: JsHttpData) -> Self { + value.inner + } +} + +#[wasm_bindgen(js_class = HttpData)] +impl JsHttpData { + #[wasm_bindgen(constructor)] + pub fn new(url: &str, method: JsHttpMethod) -> Self { + HttpData::new(UncheckedUrl::from(url), method.into()).into() + } + + #[wasm_bindgen(getter)] + pub fn urls(&self) -> String { + self.inner.url.to_string() + } + + #[wasm_bindgen(getter)] + pub fn method(&self) -> JsHttpMethod { + self.inner.method.clone().into() + } + + #[wasm_bindgen(getter)] + pub fn payload(&self) -> Option { + self.inner.payload.map(|s| s.to_string()) + } +} diff --git a/crates/nostr/src/nips/nip53.rs b/crates/nostr/src/nips/nip53.rs index f2ca3d68b..85ee5a34f 100644 --- a/crates/nostr/src/nips/nip53.rs +++ b/crates/nostr/src/nips/nip53.rs @@ -104,6 +104,7 @@ where } /// Live Event Host +#[derive(Clone)] pub struct LiveEventHost { /// Host public key pub public_key: PublicKey,