From 5eefdde6483abfc01e8eece317fc192a1f98671b Mon Sep 17 00:00:00 2001 From: Rusted Moon Date: Sun, 28 Jan 2024 14:55:02 +0100 Subject: [PATCH 01/18] js(nostr): add `EventBuilder::long_form_text_note` --- bindings/nostr-js/src/event/builder.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bindings/nostr-js/src/event/builder.rs b/bindings/nostr-js/src/event/builder.rs index 40d04cd98..0d6ba36eb 100644 --- a/bindings/nostr-js/src/event/builder.rs +++ b/bindings/nostr-js/src/event/builder.rs @@ -96,6 +96,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()); From 220437df0f697e3f4c4ce4495712e376c49a85f9 Mon Sep 17 00:00:00 2001 From: Rusted Moon Date: Wed, 31 Jan 2024 10:41:05 +0100 Subject: [PATCH 02/18] js(nostr): add `EventBuilder::report` --- bindings/nostr-js/src/event/builder.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bindings/nostr-js/src/event/builder.rs b/bindings/nostr-js/src/event/builder.rs index 0d6ba36eb..535c2b74e 100644 --- a/bindings/nostr-js/src/event/builder.rs +++ b/bindings/nostr-js/src/event/builder.rs @@ -208,6 +208,13 @@ impl JsEventBuilder { }) } + #[wasm_bindgen] + pub fn report(tags: Vec, content: String) -> Self { + Self { + builder: EventBuilder::report(tags.into_iter().map(|t| t.into()), content), + } + } + /// Gift Wrap from seal /// /// From db0236b6930bbf8d305ce7bc43c17e37e7a05b1d Mon Sep 17 00:00:00 2001 From: Rusted Moon Date: Wed, 31 Jan 2024 12:24:05 +0100 Subject: [PATCH 03/18] js(nostr): add `EventBuilder::public_zap_request` --- bindings/nostr-js/src/event/builder.rs | 8 +++ bindings/nostr-js/src/nips/mod.rs | 1 + bindings/nostr-js/src/nips/nip01.rs | 68 +++++++++++++++++++ bindings/nostr-js/src/nips/nip57.rs | 93 +++++++++++++++++++++++++- 4 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 bindings/nostr-js/src/nips/nip01.rs diff --git a/bindings/nostr-js/src/event/builder.rs b/bindings/nostr-js/src/event/builder.rs index 535c2b74e..a25e15efc 100644 --- a/bindings/nostr-js/src/event/builder.rs +++ b/bindings/nostr-js/src/event/builder.rs @@ -10,6 +10,7 @@ use wasm_bindgen::prelude::*; use super::{JsEvent, JsEventId, JsTag, JsUnsignedEvent}; use crate::error::{into_err, Result}; use crate::key::{JsKeys, JsPublicKey}; +use crate::nips::nip57::JsZapRequestData; use crate::types::{JsContact, JsMetadata, JsTimestamp}; #[wasm_bindgen(js_name = EventBuilder)] @@ -215,6 +216,13 @@ impl JsEventBuilder { } } + #[wasm_bindgen(js_name = publicZapRequest)] + pub fn public_zap_request(data: JsZapRequestData) -> Self { + Self { + builder: EventBuilder::public_zap_request(data.deref().clone()), + } + } + /// Gift Wrap from seal /// /// diff --git a/bindings/nostr-js/src/nips/mod.rs b/bindings/nostr-js/src/nips/mod.rs index 45abfd6ea..9ea8323ef 100644 --- a/bindings/nostr-js/src/nips/mod.rs +++ b/bindings/nostr-js/src/nips/mod.rs @@ -2,6 +2,7 @@ // 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; diff --git a/bindings/nostr-js/src/nips/nip01.rs b/bindings/nostr-js/src/nips/nip01.rs new file mode 100644 index 000000000..341ce7861 --- /dev/null +++ b/bindings/nostr-js/src/nips/nip01.rs @@ -0,0 +1,68 @@ +// 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 { + 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/nip57.rs b/bindings/nostr-js/src/nips/nip57.rs index 614b8feff..574a48e9c 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,87 @@ 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 { + 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().clone()), + 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()) + } +} From b0923e872750b96ffc9e1ce2da1e80e843bad943 Mon Sep 17 00:00:00 2001 From: Rusted Moon Date: Wed, 31 Jan 2024 12:29:25 +0100 Subject: [PATCH 04/18] js(nostr): add `EventBuilder::zap_receipt` --- bindings/nostr-js/src/event/builder.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bindings/nostr-js/src/event/builder.rs b/bindings/nostr-js/src/event/builder.rs index a25e15efc..d1ed8b7cf 100644 --- a/bindings/nostr-js/src/event/builder.rs +++ b/bindings/nostr-js/src/event/builder.rs @@ -223,6 +223,13 @@ impl JsEventBuilder { } } + #[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()), + } + } + /// Gift Wrap from seal /// /// From 5bf572f11b7cb347d30090e26dd694e66a4b3294 Mon Sep 17 00:00:00 2001 From: Rusted Moon Date: Wed, 31 Jan 2024 13:39:29 +0100 Subject: [PATCH 05/18] js(nostr): add `EventBuilder::relay_list` --- bindings/nostr-js/src/event/builder.rs | 8 ++++ bindings/nostr-js/src/event/mod.rs | 2 +- bindings/nostr-js/src/event/tag.rs | 31 ++++++++++++++- bindings/nostr-js/src/nips/mod.rs | 1 + bindings/nostr-js/src/nips/nip65.rs | 54 ++++++++++++++++++++++++++ 5 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 bindings/nostr-js/src/nips/nip65.rs diff --git a/bindings/nostr-js/src/event/builder.rs b/bindings/nostr-js/src/event/builder.rs index d1ed8b7cf..deb1cd4f3 100644 --- a/bindings/nostr-js/src/event/builder.rs +++ b/bindings/nostr-js/src/event/builder.rs @@ -11,6 +11,7 @@ use super::{JsEvent, JsEventId, JsTag, JsUnsignedEvent}; use crate::error::{into_err, Result}; use crate::key::{JsKeys, JsPublicKey}; use crate::nips::nip57::JsZapRequestData; +use crate::nips::nip65::JsRelayListItem; use crate::types::{JsContact, JsMetadata, JsTimestamp}; #[wasm_bindgen(js_name = EventBuilder)] @@ -90,6 +91,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 { 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..8ecf2def4 100644 --- a/bindings/nostr-js/src/event/tag.rs +++ b/bindings/nostr-js/src/event/tag.rs @@ -2,11 +2,36 @@ // 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}; +#[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 +58,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/nips/mod.rs b/bindings/nostr-js/src/nips/mod.rs index 9ea8323ef..18dd133af 100644 --- a/bindings/nostr-js/src/nips/mod.rs +++ b/bindings/nostr-js/src/nips/mod.rs @@ -14,3 +14,4 @@ pub mod nip46; pub mod nip47; pub mod nip49; pub mod nip57; +pub mod nip65; diff --git a/bindings/nostr-js/src/nips/nip65.rs b/bindings/nostr-js/src/nips/nip65.rs new file mode 100644 index 000000000..e57dc7687 --- /dev/null +++ b/bindings/nostr-js/src/nips/nip65.rs @@ -0,0 +1,54 @@ +// 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 { + url: String, + 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 { + pub fn new(url: String, metadata: Option) -> Self { + Self { url, metadata } + } + + #[wasm_bindgen(getter)] + pub fn url(&self) -> String { + self.url.clone() + } + + #[wasm_bindgen(getter)] + pub fn metadata(&self) -> Option { + self.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() +} From 6071a4f0f2e6b7c61028a809d0ddafb6bbfa521f Mon Sep 17 00:00:00 2001 From: Rusted Moon Date: Wed, 31 Jan 2024 16:39:17 +0100 Subject: [PATCH 06/18] js(nostr): add `EventBuilder::define_badge` --- bindings/nostr-js/src/event/builder.rs | 22 +++++++++++++++ bindings/nostr-js/src/event/tag.rs | 39 ++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) diff --git a/bindings/nostr-js/src/event/builder.rs b/bindings/nostr-js/src/event/builder.rs index deb1cd4f3..e7668fc3f 100644 --- a/bindings/nostr-js/src/event/builder.rs +++ b/bindings/nostr-js/src/event/builder.rs @@ -7,6 +7,7 @@ use core::ops::Deref; 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}; @@ -238,6 +239,27 @@ impl JsEventBuilder { } } + #[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(|url| UncheckedUrl::from(url)), + image_dimensions.map(|i| i.into()), + thumbnails.into_iter().map(|t| t.into()).collect(), + ), + } + } + /// Gift Wrap from seal /// /// diff --git a/bindings/nostr-js/src/event/tag.rs b/bindings/nostr-js/src/event/tag.rs index 8ecf2def4..2a056997b 100644 --- a/bindings/nostr-js/src/event/tag.rs +++ b/bindings/nostr-js/src/event/tag.rs @@ -7,6 +7,45 @@ use wasm_bindgen::prelude::*; use crate::error::{into_err, Result}; +#[wasm_bindgen(js_name = Thumbnails)] +pub struct JsThumbnails { + url: String, + 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_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 { From 90c5eedcb508b9e669dde7ca779589eade105456 Mon Sep 17 00:00:00 2001 From: Rusted Moon Date: Wed, 31 Jan 2024 16:45:12 +0100 Subject: [PATCH 07/18] js(nostr): add `EventBuilder::award_badge` --- bindings/nostr-js/src/event/builder.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/bindings/nostr-js/src/event/builder.rs b/bindings/nostr-js/src/event/builder.rs index e7668fc3f..4292528ba 100644 --- a/bindings/nostr-js/src/event/builder.rs +++ b/bindings/nostr-js/src/event/builder.rs @@ -260,6 +260,20 @@ impl JsEventBuilder { } } + #[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)?, + }) + } + /// Gift Wrap from seal /// /// From bb33a6e4449a098e81b4ff924219d2c33379b219 Mon Sep 17 00:00:00 2001 From: Rusted Moon Date: Wed, 31 Jan 2024 17:03:46 +0100 Subject: [PATCH 08/18] js(nostr): add `EventBuilder::profile_badges` --- bindings/nostr-js/src/event/builder.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/bindings/nostr-js/src/event/builder.rs b/bindings/nostr-js/src/event/builder.rs index 4292528ba..4496ee60e 100644 --- a/bindings/nostr-js/src/event/builder.rs +++ b/bindings/nostr-js/src/event/builder.rs @@ -274,6 +274,22 @@ impl JsEventBuilder { }) } + #[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)?, + }) + } + /// Gift Wrap from seal /// /// From 82622ade64e8a68e77b67d89c1b35ab5980ded8a Mon Sep 17 00:00:00 2001 From: Rusted Moon Date: Wed, 31 Jan 2024 17:13:33 +0100 Subject: [PATCH 09/18] js(nostr): add `EventBuilder::job_request` --- bindings/nostr-js/src/event/builder.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/bindings/nostr-js/src/event/builder.rs b/bindings/nostr-js/src/event/builder.rs index 4496ee60e..6eedda53e 100644 --- a/bindings/nostr-js/src/event/builder.rs +++ b/bindings/nostr-js/src/event/builder.rs @@ -290,6 +290,14 @@ impl JsEventBuilder { }) } + #[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)?, + }) + } + /// Gift Wrap from seal /// /// From 6f7f33b89bca98bf2428b9cbb33877459d8327ad Mon Sep 17 00:00:00 2001 From: Rusted Moon Date: Wed, 31 Jan 2024 17:22:20 +0100 Subject: [PATCH 10/18] js(nostr): add `EventBuilder::job_result` --- bindings/nostr-js/src/event/builder.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/bindings/nostr-js/src/event/builder.rs b/bindings/nostr-js/src/event/builder.rs index 6eedda53e..4ac8e0058 100644 --- a/bindings/nostr-js/src/event/builder.rs +++ b/bindings/nostr-js/src/event/builder.rs @@ -298,6 +298,22 @@ impl JsEventBuilder { }) } + #[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)?, + }) + } + /// Gift Wrap from seal /// /// From 3ee64a170d91483422372d6f20fd859fc62d4510 Mon Sep 17 00:00:00 2001 From: Rusted Moon Date: Wed, 31 Jan 2024 17:27:54 +0100 Subject: [PATCH 11/18] js(nostr): add `EventBuilder::job_feedback` --- bindings/nostr-js/src/event/builder.rs | 22 +++++++++++++++ bindings/nostr-js/src/nips/mod.rs | 1 + bindings/nostr-js/src/nips/nip90.rs | 38 ++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 bindings/nostr-js/src/nips/nip90.rs diff --git a/bindings/nostr-js/src/event/builder.rs b/bindings/nostr-js/src/event/builder.rs index 4ac8e0058..090ba9f5b 100644 --- a/bindings/nostr-js/src/event/builder.rs +++ b/bindings/nostr-js/src/event/builder.rs @@ -13,6 +13,7 @@ use crate::error::{into_err, Result}; use crate::key::{JsKeys, JsPublicKey}; use crate::nips::nip57::JsZapRequestData; use crate::nips::nip65::JsRelayListItem; +use crate::nips::nip90::JsDataVendingMachineStatus; use crate::types::{JsContact, JsMetadata, JsTimestamp}; #[wasm_bindgen(js_name = EventBuilder)] @@ -314,6 +315,27 @@ impl JsEventBuilder { }) } + #[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, + ), + } + } + /// Gift Wrap from seal /// /// diff --git a/bindings/nostr-js/src/nips/mod.rs b/bindings/nostr-js/src/nips/mod.rs index 18dd133af..d46749395 100644 --- a/bindings/nostr-js/src/nips/mod.rs +++ b/bindings/nostr-js/src/nips/mod.rs @@ -15,3 +15,4 @@ pub mod nip47; pub mod nip49; pub mod nip57; pub mod nip65; +pub mod nip90; 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, + } + } +} From 4ece12fc5c5cb5b5df6d9e9ab3e12fe58afccbb2 Mon Sep 17 00:00:00 2001 From: Rusted Moon Date: Thu, 1 Feb 2024 16:56:14 +0100 Subject: [PATCH 12/18] js(nostr): add `EventBuilder::file_metadata` --- bindings/nostr-js/src/event/builder.rs | 8 ++ bindings/nostr-js/src/nips/mod.rs | 1 + bindings/nostr-js/src/nips/nip94.rs | 112 +++++++++++++++++++++++++ 3 files changed, 121 insertions(+) create mode 100644 bindings/nostr-js/src/nips/nip94.rs diff --git a/bindings/nostr-js/src/event/builder.rs b/bindings/nostr-js/src/event/builder.rs index 090ba9f5b..d260db8d9 100644 --- a/bindings/nostr-js/src/event/builder.rs +++ b/bindings/nostr-js/src/event/builder.rs @@ -14,6 +14,7 @@ use crate::key::{JsKeys, JsPublicKey}; use crate::nips::nip57::JsZapRequestData; use crate::nips::nip65::JsRelayListItem; use crate::nips::nip90::JsDataVendingMachineStatus; +use crate::nips::nip94::JsFileMetadata; use crate::types::{JsContact, JsMetadata, JsTimestamp}; #[wasm_bindgen(js_name = EventBuilder)] @@ -336,6 +337,13 @@ impl JsEventBuilder { } } + #[wasm_bindgen(js_name = fileMetadata)] + pub fn file_metadata(description: String, metadata: JsFileMetadata) -> Self { + Self { + builder: EventBuilder::file_metadata(description, metadata.deref().clone()), + } + } + /// Gift Wrap from seal /// /// diff --git a/bindings/nostr-js/src/nips/mod.rs b/bindings/nostr-js/src/nips/mod.rs index d46749395..0f4fb48c0 100644 --- a/bindings/nostr-js/src/nips/mod.rs +++ b/bindings/nostr-js/src/nips/mod.rs @@ -16,3 +16,4 @@ pub mod nip49; pub mod nip57; pub mod nip65; pub mod nip90; +pub mod nip94; diff --git a/bindings/nostr-js/src/nips/nip94.rs b/bindings/nostr-js/src/nips/nip94.rs new file mode 100644 index 000000000..d228b61d9 --- /dev/null +++ b/bindings/nostr-js/src/nips/nip94.rs @@ -0,0 +1,112 @@ +// 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 { + key: String, + 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, + } + } +} + +impl JsAes256Gcm { + 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 { + 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() + } +} From edd3513457ab9450298e41db07d73b132fd772c7 Mon Sep 17 00:00:00 2001 From: Rusted Moon Date: Fri, 2 Feb 2024 12:04:52 +0100 Subject: [PATCH 13/18] js(nostr): add `EventBuilder::http_auth` --- bindings/nostr-js/src/event/builder.rs | 8 +++++ bindings/nostr-js/src/event/tag.rs | 30 ++++++++++++++++ bindings/nostr-js/src/nips/mod.rs | 1 + bindings/nostr-js/src/nips/nip98.rs | 47 ++++++++++++++++++++++++++ 4 files changed, 86 insertions(+) create mode 100644 bindings/nostr-js/src/nips/nip98.rs diff --git a/bindings/nostr-js/src/event/builder.rs b/bindings/nostr-js/src/event/builder.rs index d260db8d9..58362e92e 100644 --- a/bindings/nostr-js/src/event/builder.rs +++ b/bindings/nostr-js/src/event/builder.rs @@ -15,6 +15,7 @@ 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)] @@ -344,6 +345,13 @@ impl JsEventBuilder { } } + #[wasm_bindgen(js_name = httpAuth)] + pub fn http_auth(data: JsHttpData) -> Self { + Self { + builder: EventBuilder::http_auth(data.into()), + } + } + /// Gift Wrap from seal /// /// diff --git a/bindings/nostr-js/src/event/tag.rs b/bindings/nostr-js/src/event/tag.rs index 2a056997b..e505aaf2f 100644 --- a/bindings/nostr-js/src/event/tag.rs +++ b/bindings/nostr-js/src/event/tag.rs @@ -7,6 +7,36 @@ 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 { url: String, diff --git a/bindings/nostr-js/src/nips/mod.rs b/bindings/nostr-js/src/nips/mod.rs index 0f4fb48c0..69fcbfe73 100644 --- a/bindings/nostr-js/src/nips/mod.rs +++ b/bindings/nostr-js/src/nips/mod.rs @@ -17,3 +17,4 @@ pub mod nip57; pub mod nip65; pub mod nip90; pub mod nip94; +pub mod nip98; diff --git a/bindings/nostr-js/src/nips/nip98.rs b/bindings/nostr-js/src/nips/nip98.rs new file mode 100644 index 000000000..111af579f --- /dev/null +++ b/bindings/nostr-js/src/nips/nip98.rs @@ -0,0 +1,47 @@ +// 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 { + 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()) + } +} From 1e55287a3ec4e24b1f61c6e0916a8bb231a6cac9 Mon Sep 17 00:00:00 2001 From: Rusted Moon Date: Fri, 2 Feb 2024 16:55:51 +0100 Subject: [PATCH 14/18] js(nostr): add `EventBuilder::stall_data` --- bindings/nostr-js/src/event/builder.rs | 8 ++ bindings/nostr-js/src/nips/mod.rs | 1 + bindings/nostr-js/src/nips/nip15.rs | 137 +++++++++++++++++++++++++ 3 files changed, 146 insertions(+) create mode 100644 bindings/nostr-js/src/nips/nip15.rs diff --git a/bindings/nostr-js/src/event/builder.rs b/bindings/nostr-js/src/event/builder.rs index 58362e92e..f0d3c27f6 100644 --- a/bindings/nostr-js/src/event/builder.rs +++ b/bindings/nostr-js/src/event/builder.rs @@ -11,6 +11,7 @@ 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::JsStallData; use crate::nips::nip57::JsZapRequestData; use crate::nips::nip65::JsRelayListItem; use crate::nips::nip90::JsDataVendingMachineStatus; @@ -352,6 +353,13 @@ impl JsEventBuilder { } } + #[wasm_bindgen(js_name = stallData)] + pub fn stall_data(data: JsStallData) -> Self { + Self { + builder: EventBuilder::stall_data(data.deref().clone()), + } + } + /// Gift Wrap from seal /// /// diff --git a/bindings/nostr-js/src/nips/mod.rs b/bindings/nostr-js/src/nips/mod.rs index 69fcbfe73..1682621a6 100644 --- a/bindings/nostr-js/src/nips/mod.rs +++ b/bindings/nostr-js/src/nips/mod.rs @@ -7,6 +7,7 @@ pub mod nip04; pub mod nip05; pub mod nip07; pub mod nip11; +pub mod nip15; pub mod nip19; pub mod nip26; pub mod nip44; diff --git a/bindings/nostr-js/src/nips/nip15.rs b/bindings/nostr-js/src/nips/nip15.rs new file mode 100644 index 000000000..ae372df8f --- /dev/null +++ b/bindings/nostr-js/src/nips/nip15.rs @@ -0,0 +1,137 @@ +// Copyright (c) 2023-2024 Rust Nostr Developers +// Distributed under the MIT software license + +use std::ops::Deref; + +use nostr::nips::nip15::{ShippingCost, ShippingMethod, StallData}; +use wasm_bindgen::prelude::*; + +#[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 { + pub fn new(id: &str, cost: f64) -> Self { + ShippingMethod::new(id, cost).into() + } + + 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 { + 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() + } +} From f88794141a9c3b3f2af566d2c6226110b496906b Mon Sep 17 00:00:00 2001 From: Rusted Moon Date: Fri, 2 Feb 2024 17:55:57 +0100 Subject: [PATCH 15/18] js(nostr): add `EventBuilder::product_data` --- bindings/nostr-js/src/event/builder.rs | 9 ++- bindings/nostr-js/src/nips/nip15.rs | 102 ++++++++++++++++++++++++- 2 files changed, 109 insertions(+), 2 deletions(-) diff --git a/bindings/nostr-js/src/event/builder.rs b/bindings/nostr-js/src/event/builder.rs index f0d3c27f6..e08f90a9f 100644 --- a/bindings/nostr-js/src/event/builder.rs +++ b/bindings/nostr-js/src/event/builder.rs @@ -11,7 +11,7 @@ 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::JsStallData; +use crate::nips::nip15::{JsProductData, JsStallData}; use crate::nips::nip57::JsZapRequestData; use crate::nips::nip65::JsRelayListItem; use crate::nips::nip90::JsDataVendingMachineStatus; @@ -360,6 +360,13 @@ impl JsEventBuilder { } } + #[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/nips/nip15.rs b/bindings/nostr-js/src/nips/nip15.rs index ae372df8f..3369ec56e 100644 --- a/bindings/nostr-js/src/nips/nip15.rs +++ b/bindings/nostr-js/src/nips/nip15.rs @@ -3,9 +3,16 @@ use std::ops::Deref; -use nostr::nips::nip15::{ShippingCost, ShippingMethod, StallData}; +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, @@ -135,3 +142,96 @@ impl JsStallData { .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 { + 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() + } +} From 2d40b805b36dc6df3ee4f1f5745a36c482555a29 Mon Sep 17 00:00:00 2001 From: Rusted Moon Date: Thu, 22 Feb 2024 10:39:24 +0100 Subject: [PATCH 16/18] js(nostr): add `EventBuilder::live_event` --- bindings/nostr-js/src/event/builder.rs | 8 + bindings/nostr-js/src/event/tag.rs | 1 + bindings/nostr-js/src/nips/mod.rs | 1 + bindings/nostr-js/src/nips/nip53.rs | 259 +++++++++++++++++++++++++ crates/nostr/src/nips/nip53.rs | 1 + 5 files changed, 270 insertions(+) create mode 100644 bindings/nostr-js/src/nips/nip53.rs diff --git a/bindings/nostr-js/src/event/builder.rs b/bindings/nostr-js/src/event/builder.rs index e08f90a9f..487821af4 100644 --- a/bindings/nostr-js/src/event/builder.rs +++ b/bindings/nostr-js/src/event/builder.rs @@ -12,6 +12,7 @@ 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; @@ -222,6 +223,13 @@ 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] pub fn report(tags: Vec, content: String) -> Self { Self { diff --git a/bindings/nostr-js/src/event/tag.rs b/bindings/nostr-js/src/event/tag.rs index e505aaf2f..eed2e69ca 100644 --- a/bindings/nostr-js/src/event/tag.rs +++ b/bindings/nostr-js/src/event/tag.rs @@ -52,6 +52,7 @@ impl From for (UncheckedUrl, Option) { } } +#[derive(Clone, Copy)] #[wasm_bindgen(js_name = ImageDimensions)] pub struct JsImageDimensions { pub width: u64, diff --git a/bindings/nostr-js/src/nips/mod.rs b/bindings/nostr-js/src/nips/mod.rs index 1682621a6..cd1cabc13 100644 --- a/bindings/nostr-js/src/nips/mod.rs +++ b/bindings/nostr-js/src/nips/mod.rs @@ -14,6 +14,7 @@ pub mod nip44; pub mod nip46; pub mod nip47; pub mod nip49; +pub mod nip53; pub mod nip57; pub mod nip65; pub mod nip90; diff --git a/bindings/nostr-js/src/nips/nip53.rs b/bindings/nostr-js/src/nips/nip53.rs new file mode 100644 index 000000000..1d9dc7ddd --- /dev/null +++ b/bindings/nostr-js/src/nips/nip53.rs @@ -0,0 +1,259 @@ +// 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 Image { + url: String, + dimensions: Option, +} + +impl From<(UncheckedUrl, Option)> for Image { + fn from(value: (UncheckedUrl, Option)) -> Self { + Self { + url: value.0.to_string(), + dimensions: value.1.map(|d| d.into()), + } + } +} + +impl Image { + pub fn url(&self) -> String { + self.url.to_string() + } + + pub fn dimensions(&self) -> Option { + self.dimensions.clone().map(|d| d.into()) + } +} + +#[wasm_bindgen(js_name = User)] +pub struct User { + public_key: JsPublicKey, + url: Option, +} + +impl From<(PublicKey, Option)> for User { + fn from(value: (PublicKey, Option)) -> Self { + Self { + public_key: value.0.into(), + url: value.1.map(|url| url.to_string()), + } + } +} + +impl User { + pub fn public_key(&self) -> JsPublicKey { + self.public_key.clone().into() + } + + pub fn url(&self) -> Option { + self.url.clone() + } +} + +#[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.clone().map(|t| t.as_i64() as f64) + } + + #[wasm_bindgen(getter)] + pub fn ends(&self) -> Option { + self.inner.ends.clone().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/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, From d07c06ec173e9fd86f4aa2f817a724fa2bc942cc Mon Sep 17 00:00:00 2001 From: Rusted Moon Date: Wed, 28 Feb 2024 11:34:54 +0100 Subject: [PATCH 17/18] js(nostr): add `EventBuilder::live_event_msg` --- bindings/nostr-js/src/event/builder.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/bindings/nostr-js/src/event/builder.rs b/bindings/nostr-js/src/event/builder.rs index 487821af4..3d5909f11 100644 --- a/bindings/nostr-js/src/event/builder.rs +++ b/bindings/nostr-js/src/event/builder.rs @@ -3,6 +3,7 @@ // Distributed under the MIT software license use core::ops::Deref; +use std::str::FromStr; use nostr::prelude::*; use wasm_bindgen::prelude::*; @@ -230,6 +231,28 @@ impl JsEventBuilder { } } + #[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 { From 3e154860d0773adbdbf5b258eb996f2f4936e031 Mon Sep 17 00:00:00 2001 From: Rusted Moon Date: Wed, 13 Mar 2024 15:28:21 +0100 Subject: [PATCH 18/18] js(nostr): some adjustment to `EventBuilder` and related things - add missing `#[wasm_bindgen(constructor)]` - add missing `new` constructor - fix clippy --- bindings/nostr-js/src/event/builder.rs | 4 +- bindings/nostr-js/src/event/tag.rs | 13 +++++- bindings/nostr-js/src/key/public_key.rs | 1 + bindings/nostr-js/src/nips/nip01.rs | 1 + bindings/nostr-js/src/nips/nip15.rs | 4 ++ bindings/nostr-js/src/nips/nip47.rs | 1 + bindings/nostr-js/src/nips/nip53.rs | 53 ++++++++++++------------- bindings/nostr-js/src/nips/nip57.rs | 3 +- bindings/nostr-js/src/nips/nip65.rs | 16 ++------ bindings/nostr-js/src/nips/nip94.rs | 13 ++++-- bindings/nostr-js/src/nips/nip98.rs | 1 + 11 files changed, 62 insertions(+), 48 deletions(-) diff --git a/bindings/nostr-js/src/event/builder.rs b/bindings/nostr-js/src/event/builder.rs index 3d5909f11..026a1c384 100644 --- a/bindings/nostr-js/src/event/builder.rs +++ b/bindings/nostr-js/src/event/builder.rs @@ -288,7 +288,7 @@ impl JsEventBuilder { badge_id, name, description, - image.map(|url| UncheckedUrl::from(url)), + image.map(UncheckedUrl::from), image_dimensions.map(|i| i.into()), thumbnails.into_iter().map(|t| t.into()).collect(), ), @@ -385,7 +385,7 @@ impl JsEventBuilder { } #[wasm_bindgen(js_name = stallData)] - pub fn stall_data(data: JsStallData) -> Self { + pub fn stall_data(data: &JsStallData) -> Self { Self { builder: EventBuilder::stall_data(data.deref().clone()), } diff --git a/bindings/nostr-js/src/event/tag.rs b/bindings/nostr-js/src/event/tag.rs index eed2e69ca..ac7a6d1ea 100644 --- a/bindings/nostr-js/src/event/tag.rs +++ b/bindings/nostr-js/src/event/tag.rs @@ -39,8 +39,9 @@ impl From for HttpMethod { #[wasm_bindgen(js_name = Thumbnails)] pub struct JsThumbnails { - url: String, - dimensions: Option, + #[wasm_bindgen(getter_with_clone)] + pub url: String, + pub dimensions: Option, } impl From for (UncheckedUrl, Option) { @@ -52,6 +53,14 @@ impl From for (UncheckedUrl, Option) { } } +#[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 { 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/nip01.rs b/bindings/nostr-js/src/nips/nip01.rs index 341ce7861..4f3d40842 100644 --- a/bindings/nostr-js/src/nips/nip01.rs +++ b/bindings/nostr-js/src/nips/nip01.rs @@ -30,6 +30,7 @@ impl From for JsCoordinate { #[wasm_bindgen(js_class = Coordinate)] impl JsCoordinate { + #[wasm_bindgen(constructor)] pub fn new( kind: f64, public_key: &JsPublicKey, diff --git a/bindings/nostr-js/src/nips/nip15.rs b/bindings/nostr-js/src/nips/nip15.rs index 3369ec56e..abaebda45 100644 --- a/bindings/nostr-js/src/nips/nip15.rs +++ b/bindings/nostr-js/src/nips/nip15.rs @@ -58,10 +58,12 @@ impl Deref for JsShippingMethod { #[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() } @@ -108,6 +110,7 @@ impl Deref for JsStallData { #[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() } @@ -162,6 +165,7 @@ impl From for ProductData { #[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() } 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 index 1d9dc7ddd..57d2d3170 100644 --- a/bindings/nostr-js/src/nips/nip53.rs +++ b/bindings/nostr-js/src/nips/nip53.rs @@ -11,12 +11,13 @@ use crate::event::tag::JsImageDimensions; use crate::key::JsPublicKey; #[wasm_bindgen(js_name = Image)] -pub struct Image { - url: String, - dimensions: Option, +pub struct JsImage { + #[wasm_bindgen(getter_with_clone)] + pub url: String, + pub dimensions: Option, } -impl From<(UncheckedUrl, Option)> for Image { +impl From<(UncheckedUrl, Option)> for JsImage { fn from(value: (UncheckedUrl, Option)) -> Self { Self { url: value.0.to_string(), @@ -25,23 +26,23 @@ impl From<(UncheckedUrl, Option)> for Image { } } -impl Image { - pub fn url(&self) -> String { - self.url.to_string() - } - - pub fn dimensions(&self) -> Option { - self.dimensions.clone().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 User { - public_key: JsPublicKey, - url: Option, +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 User { +impl From<(PublicKey, Option)> for JsUser { fn from(value: (PublicKey, Option)) -> Self { Self { public_key: value.0.into(), @@ -50,13 +51,11 @@ impl From<(PublicKey, Option)> for User { } } -impl User { - pub fn public_key(&self) -> JsPublicKey { - self.public_key.clone().into() - } - - pub fn url(&self) -> Option { - self.url.clone() +#[wasm_bindgen(js_class = User)] +impl JsUser { + #[wasm_bindgen(constructor)] + pub fn new(public_key: JsPublicKey, url: Option) -> Self { + Self { public_key, url } } } @@ -178,7 +177,7 @@ impl JsLiveEvent { } #[wasm_bindgen(getter)] - pub fn image(&self) -> Option { + pub fn image(&self) -> Option { self.inner.image.clone().map(|i| i.into()) } @@ -199,12 +198,12 @@ impl JsLiveEvent { #[wasm_bindgen(getter)] pub fn starts(&self) -> Option { - self.inner.starts.clone().map(|t| t.as_i64() as f64) + self.inner.starts.map(|t| t.as_i64() as f64) } #[wasm_bindgen(getter)] pub fn ends(&self) -> Option { - self.inner.ends.clone().map(|t| t.as_i64() as f64) + self.inner.ends.map(|t| t.as_i64() as f64) } #[wasm_bindgen(getter)] @@ -238,7 +237,7 @@ impl JsLiveEvent { } #[wasm_bindgen(getter)] - pub fn speakers(&self) -> Vec { + pub fn speakers(&self) -> Vec { self.inner .speakers .clone() @@ -248,7 +247,7 @@ impl JsLiveEvent { } #[wasm_bindgen(getter)] - pub fn participants(&self) -> Vec { + pub fn participants(&self) -> Vec { self.inner .participants .clone() diff --git a/bindings/nostr-js/src/nips/nip57.rs b/bindings/nostr-js/src/nips/nip57.rs index 574a48e9c..6ed6cdf2b 100644 --- a/bindings/nostr-js/src/nips/nip57.rs +++ b/bindings/nostr-js/src/nips/nip57.rs @@ -63,6 +63,7 @@ impl Deref for JsZapRequestData { #[wasm_bindgen(js_class = ZapRequestData)] impl JsZapRequestData { + #[wasm_bindgen(constructor)] pub fn new( public_key: &JsPublicKey, relays: Vec, @@ -79,7 +80,7 @@ impl JsZapRequestData { message, amount: amount.map(|n| n as u64), lnurl, - event_id: event_id.map(|e| e.deref().clone()), + event_id: event_id.map(|e| *e.deref()), event_coordinate: event_coordinate.map(|e| e.deref().clone()), }, } diff --git a/bindings/nostr-js/src/nips/nip65.rs b/bindings/nostr-js/src/nips/nip65.rs index e57dc7687..7d18c8a96 100644 --- a/bindings/nostr-js/src/nips/nip65.rs +++ b/bindings/nostr-js/src/nips/nip65.rs @@ -12,8 +12,9 @@ use crate::event::JsEvent; #[wasm_bindgen(js_name = RelayListItem)] pub struct JsRelayListItem { - url: String, - metadata: Option, + #[wasm_bindgen(getter_with_clone)] + pub url: String, + pub metadata: Option, } impl From for (UncheckedUrl, Option) { @@ -27,19 +28,10 @@ impl From for (UncheckedUrl, Option) { #[wasm_bindgen(js_class = RelayListItem)] impl JsRelayListItem { + #[wasm_bindgen(constructor)] pub fn new(url: String, metadata: Option) -> Self { Self { url, metadata } } - - #[wasm_bindgen(getter)] - pub fn url(&self) -> String { - self.url.clone() - } - - #[wasm_bindgen(getter)] - pub fn metadata(&self) -> Option { - self.metadata - } } #[wasm_bindgen(js_name = extractRelayList)] diff --git a/bindings/nostr-js/src/nips/nip94.rs b/bindings/nostr-js/src/nips/nip94.rs index d228b61d9..e14f6b7a6 100644 --- a/bindings/nostr-js/src/nips/nip94.rs +++ b/bindings/nostr-js/src/nips/nip94.rs @@ -14,8 +14,10 @@ use crate::event::tag::JsImageDimensions; #[wasm_bindgen(js_name = Aes256Gcm)] pub struct JsAes256Gcm { - key: String, - iv: String, + #[wasm_bindgen(getter_with_clone)] + pub key: String, + #[wasm_bindgen(getter_with_clone)] + pub iv: String, } impl From for (String, String) { @@ -33,7 +35,9 @@ impl From<(String, String)> for JsAes256Gcm { } } +#[wasm_bindgen(js_class = Aes256Gcm)] impl JsAes256Gcm { + #[wasm_bindgen(constructor)] pub fn new(key: String, iv: String) -> Self { Self { key, iv } } @@ -60,12 +64,13 @@ impl Deref for JsFileMetadata { #[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)?, + Url::from_str(url).map_err(into_err)?, mime_type, - Sha256Hash::from_str(&hash).map_err(into_err)?, + Sha256Hash::from_str(hash).map_err(into_err)?, ), }) } diff --git a/bindings/nostr-js/src/nips/nip98.rs b/bindings/nostr-js/src/nips/nip98.rs index 111af579f..d535e3b3e 100644 --- a/bindings/nostr-js/src/nips/nip98.rs +++ b/bindings/nostr-js/src/nips/nip98.rs @@ -26,6 +26,7 @@ impl From for HttpData { #[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() }