diff --git a/Cargo.toml b/Cargo.toml index 2d8b4084..8f7e8331 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,8 @@ members = [ "bindings/uniffi-bindgen", "bindings/cashu-ffi", "bindings/cashu-sdk-ffi", - "bindings/cashu-js" + "bindings/cashu-js", + "bindings/cashu-sdk-js" ] resolver = "2" diff --git a/bindings/cashu-sdk-ffi/src/types/melted.rs b/bindings/cashu-sdk-ffi/src/types/melted.rs index 9bea4307..db27bf60 100644 --- a/bindings/cashu-sdk-ffi/src/types/melted.rs +++ b/bindings/cashu-sdk-ffi/src/types/melted.rs @@ -8,6 +8,14 @@ pub struct Melted { inner: MeltedSdk, } +// TODO: Deref + +impl From for Melted { + fn from(inner: cashu_sdk::types::Melted) -> Melted { + Melted { inner } + } +} + impl Melted { pub fn new(paid: bool, preimage: Option, change: Option>>) -> Self { Self { @@ -34,9 +42,3 @@ impl Melted { .map(|c| c.into_iter().map(|p| Arc::new(p.into())).collect()) } } - -impl From for Melted { - fn from(inner: cashu_sdk::types::Melted) -> Melted { - Melted { inner } - } -} diff --git a/bindings/cashu-sdk-ffi/src/types/proofs_status.rs b/bindings/cashu-sdk-ffi/src/types/proofs_status.rs index ec542d5c..1afcbcff 100644 --- a/bindings/cashu-sdk-ffi/src/types/proofs_status.rs +++ b/bindings/cashu-sdk-ffi/src/types/proofs_status.rs @@ -8,6 +8,9 @@ pub struct ProofsStatus { inner: ProofsStatusSdk, } +// TODO: Into +// TODO: Deref + impl ProofsStatus { pub fn new(spendable: Vec>, spent: Vec>) -> Self { Self { diff --git a/bindings/cashu-sdk-js/Cargo.toml b/bindings/cashu-sdk-js/Cargo.toml new file mode 100644 index 00000000..9b4bb669 --- /dev/null +++ b/bindings/cashu-sdk-js/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "cashu-sdk-js" +version = "0.1.0" +authors = ["thesimplekid "] +edition = "2021" +publish = false +repository.workspace = true +license.workspace = true + +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +default = ["console_error_panic_hook"] + +[dependencies] +cashu-sdk = { path = "../../crates/cashu-sdk" } +cashu-js = { path = "../cashu-js" } +wasm-bindgen = "0.2.84" +js-sys = "0.3.64" +serde-wasm-bindgen = "0.6.0" +serde_json.workspace = true +serde.workspace = true +wasm-bindgen-futures = "0.4.37" + +# The `console_error_panic_hook` crate provides better debugging of panics by +# logging them with `console.error`. This is great for development, but requires +# all the `std::fmt` and `std::panicking` infrastructure, so isn't great for +# code size when deploying. +console_error_panic_hook = { version = "0.1.7", optional = true } + +[dev-dependencies] +wasm-bindgen-test = "0.3.34" + +[package.metadata.wasm-pack.profile.release] +wasm-opt = true diff --git a/bindings/cashu-sdk-js/LICENSE b/bindings/cashu-sdk-js/LICENSE new file mode 100644 index 00000000..083823dd --- /dev/null +++ b/bindings/cashu-sdk-js/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2023, thesimplekid +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/bindings/cashu-sdk-js/LICENSES/NOSTR-MIT b/bindings/cashu-sdk-js/LICENSES/NOSTR-MIT new file mode 100644 index 00000000..2ff56442 --- /dev/null +++ b/bindings/cashu-sdk-js/LICENSES/NOSTR-MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022-2023 Yuki Kishimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/bindings/cashu-sdk-js/README.md b/bindings/cashu-sdk-js/README.md new file mode 100644 index 00000000..e69de29b diff --git a/bindings/cashu-sdk-js/src/error.rs b/bindings/cashu-sdk-js/src/error.rs new file mode 100644 index 00000000..019f9a3a --- /dev/null +++ b/bindings/cashu-sdk-js/src/error.rs @@ -0,0 +1,12 @@ +use wasm_bindgen::JsValue; + +pub type Result = std::result::Result; + +/// Helper to replace the `E` to `Error` to `napi::Error` conversion. +#[inline] +pub fn into_err(error: E) -> JsValue +where + E: std::error::Error, +{ + JsValue::from_str(&error.to_string()) +} diff --git a/bindings/cashu-sdk-js/src/lib.rs b/bindings/cashu-sdk-js/src/lib.rs new file mode 100644 index 00000000..8800f21b --- /dev/null +++ b/bindings/cashu-sdk-js/src/lib.rs @@ -0,0 +1,2 @@ +mod error; +mod types; diff --git a/bindings/cashu-sdk-js/src/types/melted.rs b/bindings/cashu-sdk-js/src/types/melted.rs new file mode 100644 index 00000000..e5db1a60 --- /dev/null +++ b/bindings/cashu-sdk-js/src/types/melted.rs @@ -0,0 +1,57 @@ +use std::ops::Deref; + +use cashu_sdk::types::Melted; +use wasm_bindgen::prelude::*; + +use crate::error::{into_err, Result}; + +#[wasm_bindgen(js_name = Melted)] +pub struct JsMelted { + inner: Melted, +} + +impl Deref for JsMelted { + type Target = Melted; + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl From for JsMelted { + fn from(inner: Melted) -> JsMelted { + JsMelted { inner } + } +} + +#[wasm_bindgen(js_class = Melted)] +impl JsMelted { + #[wasm_bindgen(constructor)] + pub fn new(paid: bool, preimage: Option, change: JsValue) -> Result { + let change = serde_wasm_bindgen::from_value(change).map_err(into_err)?; + Ok(JsMelted { + inner: Melted { + paid, + preimage, + change, + }, + }) + } + + /// Get Preimage + #[wasm_bindgen(getter)] + pub fn from_sat(&self) -> Option { + self.inner.preimage.clone() + } + + /// Get Paid + #[wasm_bindgen(getter)] + pub fn paid(&self) -> bool { + self.inner.paid.clone() + } + + /// Get Change + #[wasm_bindgen(getter)] + pub fn change(&self) -> Result { + serde_wasm_bindgen::to_value(&self.change).map_err(into_err) + } +} diff --git a/bindings/cashu-sdk-js/src/types/mod.rs b/bindings/cashu-sdk-js/src/types/mod.rs new file mode 100644 index 00000000..10186643 --- /dev/null +++ b/bindings/cashu-sdk-js/src/types/mod.rs @@ -0,0 +1,3 @@ +mod melted; +mod proof_status; +mod send_proofs; diff --git a/bindings/cashu-sdk-js/src/types/proof_status.rs b/bindings/cashu-sdk-js/src/types/proof_status.rs new file mode 100644 index 00000000..07e5a0d6 --- /dev/null +++ b/bindings/cashu-sdk-js/src/types/proof_status.rs @@ -0,0 +1,48 @@ +use std::ops::Deref; + +use cashu_sdk::types::ProofsStatus; +use wasm_bindgen::prelude::*; + +use crate::error::{into_err, Result}; + +#[wasm_bindgen(js_name = ProofStatus)] +pub struct JsProofsStatus { + inner: ProofsStatus, +} + +impl Deref for JsProofsStatus { + type Target = ProofsStatus; + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl From for JsProofsStatus { + fn from(inner: ProofsStatus) -> JsProofsStatus { + JsProofsStatus { inner } + } +} + +#[wasm_bindgen(js_class = ProofsStatus)] +impl JsProofsStatus { + #[wasm_bindgen(constructor)] + pub fn new(spendable: JsValue, spent: JsValue) -> Result { + let spendable = serde_wasm_bindgen::from_value(spendable).map_err(into_err)?; + let spent = serde_wasm_bindgen::from_value(spent).map_err(into_err)?; + Ok(JsProofsStatus { + inner: ProofsStatus { spendable, spent }, + }) + } + + /// Get Spendable + #[wasm_bindgen(getter)] + pub fn spendable(&self) -> Result { + serde_wasm_bindgen::to_value(&self.inner.spendable).map_err(into_err) + } + + /// Get Spent + #[wasm_bindgen(getter)] + pub fn spent(&self) -> Result { + serde_wasm_bindgen::to_value(&self.inner.spent).map_err(into_err) + } +} diff --git a/bindings/cashu-sdk-js/src/types/send_proofs.rs b/bindings/cashu-sdk-js/src/types/send_proofs.rs new file mode 100644 index 00000000..76a75acc --- /dev/null +++ b/bindings/cashu-sdk-js/src/types/send_proofs.rs @@ -0,0 +1,51 @@ +use std::ops::Deref; + +use cashu_sdk::types::SendProofs; +use wasm_bindgen::prelude::*; + +use crate::error::{into_err, Result}; + +#[wasm_bindgen(js_name = SendProofs)] +pub struct JsSendProofs { + inner: SendProofs, +} + +impl Deref for JsSendProofs { + type Target = SendProofs; + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl From for JsSendProofs { + fn from(inner: SendProofs) -> JsSendProofs { + JsSendProofs { inner } + } +} + +#[wasm_bindgen(js_class = SendProofs)] +impl JsSendProofs { + #[wasm_bindgen(constructor)] + pub fn new(change_proofs: JsValue, send_proofs: JsValue) -> Result { + let change_proofs = serde_wasm_bindgen::from_value(change_proofs).map_err(into_err)?; + let send_proofs = serde_wasm_bindgen::from_value(send_proofs).map_err(into_err)?; + Ok(JsSendProofs { + inner: SendProofs { + change_proofs, + send_proofs, + }, + }) + } + + /// Get Change Proofs + #[wasm_bindgen(getter)] + pub fn change_proofs(&self) -> Result { + serde_wasm_bindgen::to_value(&self.inner.change_proofs).map_err(into_err) + } + + /// Get Send Proofs + #[wasm_bindgen(getter)] + pub fn send_proofs(&self) -> Result { + serde_wasm_bindgen::to_value(&self.inner.send_proofs).map_err(into_err) + } +}