From 03cb66c8acf3a4c1b9e0f049e2c97f36cbb6d0c2 Mon Sep 17 00:00:00 2001 From: Yuki Kishimoto Date: Sat, 20 Jan 2024 16:46:18 +0100 Subject: [PATCH] js(nostr-sdk): add `JsClient::zap` --- Cargo.lock | 13 +++ bindings/nostr-js/src/nips/nip47.rs | 9 ++ bindings/nostr-sdk-js/Cargo.toml | 3 +- bindings/nostr-sdk-js/src/client/builder.rs | 5 + bindings/nostr-sdk-js/src/client/mod.rs | 17 ++- bindings/nostr-sdk-js/src/client/zapper.rs | 104 ++++++++++++++++++ .../src/client/{zapper/mod.rs => zapper.rs} | 1 + 7 files changed, 149 insertions(+), 3 deletions(-) create mode 100644 bindings/nostr-sdk-js/src/client/zapper.rs rename crates/nostr-sdk/src/client/{zapper/mod.rs => zapper.rs} (99%) diff --git a/Cargo.lock b/Cargo.lock index 5fd0aa0cf..5168b942d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1483,6 +1483,7 @@ dependencies = [ "tracing-subscriber", "wasm-bindgen", "wasm-bindgen-futures", + "webln-js", ] [[package]] @@ -2812,6 +2813,18 @@ dependencies = [ "web-sys", ] +[[package]] +name = "webln-js" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0017c99ae6460e29dd6a55166a3fa024340235c27c66743d7707934f0c5217" +dependencies = [ + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "webln", +] + [[package]] name = "webpki-roots" version = "0.25.3" diff --git a/bindings/nostr-js/src/nips/nip47.rs b/bindings/nostr-js/src/nips/nip47.rs index 3558312cb..514b313e9 100644 --- a/bindings/nostr-js/src/nips/nip47.rs +++ b/bindings/nostr-js/src/nips/nip47.rs @@ -2,6 +2,7 @@ // Copyright (c) 2023-2024 Rust Nostr Developers // Distributed under the MIT software license +use core::ops::Deref; use core::str::FromStr; use nostr::nips::nip47::NostrWalletConnectURI; @@ -16,6 +17,14 @@ pub struct JsNostrWalletConnectURI { inner: NostrWalletConnectURI, } +impl Deref for JsNostrWalletConnectURI { + type Target = NostrWalletConnectURI; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + #[wasm_bindgen(js_class = NostrWalletConnectURI)] impl JsNostrWalletConnectURI { /// Create new Nostr Wallet Connect URI diff --git a/bindings/nostr-sdk-js/Cargo.toml b/bindings/nostr-sdk-js/Cargo.toml index f7590d56d..c9029f694 100644 --- a/bindings/nostr-sdk-js/Cargo.toml +++ b/bindings/nostr-sdk-js/Cargo.toml @@ -12,11 +12,12 @@ crate-type = ["lib", "cdylib"] async-utility.workspace = true js-sys.workspace = true nostr-js = { path = "../nostr-js" } -nostr-sdk = { path = "../../crates/nostr-sdk", default-features = false, features = ["all-nips", "indexeddb"] } +nostr-sdk = { path = "../../crates/nostr-sdk", default-features = false, features = ["all-nips", "indexeddb", "webln"] } tracing.workspace = true tracing-subscriber.workspace = true wasm-bindgen.workspace = true wasm-bindgen-futures.workspace = true +webln-js = "0.1" [package.metadata.wasm-pack.profile.profiling] wasm-opt = true diff --git a/bindings/nostr-sdk-js/src/client/builder.rs b/bindings/nostr-sdk-js/src/client/builder.rs index d398fa66a..d6cf8d12e 100644 --- a/bindings/nostr-sdk-js/src/client/builder.rs +++ b/bindings/nostr-sdk-js/src/client/builder.rs @@ -10,6 +10,7 @@ use nostr_sdk::{Client, ClientBuilder}; use wasm_bindgen::prelude::*; use super::options::JsOptions; +use super::zapper::JsClientZapper; use super::{JsClient, JsClientSigner}; use crate::database::JsNostrDatabase; @@ -38,6 +39,10 @@ impl JsClientBuilder { self.inner.signer(signer.deref().clone()).into() } + pub fn zapper(self, zapper: &JsClientZapper) -> Self { + self.inner.zapper(zapper.deref().clone()).into() + } + pub fn database(self, database: &JsNostrDatabase) -> Self { let database: Arc = database.into(); self.inner.database(database).into() diff --git a/bindings/nostr-sdk-js/src/client/mod.rs b/bindings/nostr-sdk-js/src/client/mod.rs index bd120ea59..2b1854489 100644 --- a/bindings/nostr-sdk-js/src/client/mod.rs +++ b/bindings/nostr-sdk-js/src/client/mod.rs @@ -2,8 +2,6 @@ // Copyright (c) 2023-2024 Rust Nostr Developers // Distributed under the MIT software license -#![allow(non_snake_case)] - use std::ops::Deref; use std::time::Duration; @@ -20,9 +18,11 @@ use wasm_bindgen::prelude::*; pub mod builder; pub mod options; pub mod signer; +pub mod zapper; use self::options::JsOptions; pub use self::signer::JsClientSigner; +use self::zapper::{JsZapDetails, JsZapEntity}; use crate::abortable::JsAbortHandle; use crate::database::JsNostrDatabase; use crate::relay::{JsRelay, JsRelayArray}; @@ -512,6 +512,19 @@ impl JsClient { .map(|id| id.into()) } + /// Send a Zap! + pub async fn zap( + &self, + to: &JsZapEntity, + satoshi: f64, + details: Option, + ) -> Result<()> { + self.inner + .zap(**to, satoshi as u64, details.map(|d| d.into())) + .await + .map_err(into_err) + } + /// Negentropy reconciliation /// /// diff --git a/bindings/nostr-sdk-js/src/client/zapper.rs b/bindings/nostr-sdk-js/src/client/zapper.rs new file mode 100644 index 000000000..be57c4958 --- /dev/null +++ b/bindings/nostr-sdk-js/src/client/zapper.rs @@ -0,0 +1,104 @@ +// Copyright (c) 2022-2023 Yuki Kishimoto +// Copyright (c) 2023-2024 Rust Nostr Developers +// Distributed under the MIT software license + +use core::ops::Deref; + +use nostr_js::event::JsEventId; +use nostr_js::key::JsPublicKey; +use nostr_js::nips::nip47::JsNostrWalletConnectURI; +use nostr_js::nips::nip57::JsZapType; +use nostr_sdk::client::{ClientZapper, ZapDetails, ZapEntity}; +use wasm_bindgen::prelude::*; +use webln_js::JsWebLN; + +/// Zap entity +#[wasm_bindgen(js_name = ZapEntity)] +pub struct JsZapEntity { + inner: ZapEntity, +} + +impl Deref for JsZapEntity { + type Target = ZapEntity; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +#[wasm_bindgen(js_class = ZapEntity)] +impl JsZapEntity { + pub fn event(event_id: &JsEventId) -> Self { + Self { + inner: ZapEntity::Event(**event_id), + } + } + + #[wasm_bindgen(js_name = publicKey)] + pub fn public_key(public_key: &JsPublicKey) -> Self { + Self { + inner: ZapEntity::PublicKey(**public_key), + } + } +} + +/// Client Zapper +#[wasm_bindgen(js_name = ClientZapper)] +pub struct JsClientZapper { + inner: ClientZapper, +} + +impl Deref for JsClientZapper { + type Target = ClientZapper; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +#[wasm_bindgen(js_class = ClientZapper)] +impl JsClientZapper { + pub fn webln(instance: &JsWebLN) -> Self { + Self { + inner: ClientZapper::WebLN(instance.deref().clone()), + } + } + + pub fn nwc(uri: &JsNostrWalletConnectURI) -> Self { + Self { + inner: ClientZapper::NWC(uri.deref().clone()), + } + } +} + +/// Zap Details +#[wasm_bindgen(js_name = ZapDetails)] +pub struct JsZapDetails { + inner: ZapDetails, +} + +impl From for ZapDetails { + fn from(value: JsZapDetails) -> Self { + value.inner + } +} + +#[wasm_bindgen(js_class = ZapDetails)] +impl JsZapDetails { + /// Create new Zap Details + /// + /// **Note: `private` zaps are not currently supported here!** + #[wasm_bindgen(constructor)] + pub fn new(zap_type: JsZapType) -> Self { + Self { + inner: ZapDetails::new(zap_type.into()), + } + } + + /// Add message + pub fn message(self, message: String) -> Self { + Self { + inner: self.inner.message(message), + } + } +} diff --git a/crates/nostr-sdk/src/client/zapper/mod.rs b/crates/nostr-sdk/src/client/zapper.rs similarity index 99% rename from crates/nostr-sdk/src/client/zapper/mod.rs rename to crates/nostr-sdk/src/client/zapper.rs index be77feba9..bd2942841 100644 --- a/crates/nostr-sdk/src/client/zapper/mod.rs +++ b/crates/nostr-sdk/src/client/zapper.rs @@ -30,6 +30,7 @@ use super::{Client, Error}; use crate::FilterOptions; /// Zap entity +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ZapEntity { /// Zap to event Event(EventId),