diff --git a/bindings/cashu-ffi/src/nuts/nut02/key_set.rs b/bindings/cashu-ffi/src/nuts/nut02/key_set.rs index 2b0afe33..239a61e2 100644 --- a/bindings/cashu-ffi/src/nuts/nut02/key_set.rs +++ b/bindings/cashu-ffi/src/nuts/nut02/key_set.rs @@ -37,6 +37,12 @@ impl KeySet { } } +impl From for KeySet { + fn from(inner: cashu::nuts::nut02::KeySet) -> KeySet { + KeySet { inner } + } +} + pub struct KeySetResponse { inner: Response, } diff --git a/bindings/cashu-ffi/src/nuts/nut02/mint_keyset.rs b/bindings/cashu-ffi/src/nuts/nut02/mint_keyset.rs index 1b969ff3..ccd6e367 100644 --- a/bindings/cashu-ffi/src/nuts/nut02/mint_keyset.rs +++ b/bindings/cashu-ffi/src/nuts/nut02/mint_keyset.rs @@ -20,3 +20,9 @@ impl MintKeySet { } } } + +impl From for MintKeySet { + fn from(inner: cashu::nuts::nut02::mint::KeySet) -> MintKeySet { + MintKeySet { inner } + } +} diff --git a/bindings/cashu-ffi/src/nuts/nut04/mod.rs b/bindings/cashu-ffi/src/nuts/nut04/mod.rs index 0e0b3e96..82a7c508 100644 --- a/bindings/cashu-ffi/src/nuts/nut04/mod.rs +++ b/bindings/cashu-ffi/src/nuts/nut04/mod.rs @@ -8,6 +8,13 @@ pub struct MintRequest { inner: MintRequestSdk, } +impl Deref for MintRequest { + type Target = MintRequestSdk; + fn deref(&self) -> &Self::Target { + &self.inner + } +} + impl MintRequest { pub fn new(outputs: Vec>) -> Self { Self { @@ -34,10 +41,23 @@ impl MintRequest { } } +impl From for MintRequest { + fn from(inner: cashu::nuts::nut04::MintRequest) -> MintRequest { + MintRequest { inner } + } +} + pub struct PostMintResponse { inner: PostMintResponseSdk, } +impl Deref for PostMintResponse { + type Target = PostMintResponseSdk; + fn deref(&self) -> &Self::Target { + &self.inner + } +} + impl PostMintResponse { pub fn new(promises: Vec>) -> Self { Self { diff --git a/bindings/cashu-ffi/src/nuts/nut07/mod.rs b/bindings/cashu-ffi/src/nuts/nut07/mod.rs index 41db6678..34642ca6 100644 --- a/bindings/cashu-ffi/src/nuts/nut07/mod.rs +++ b/bindings/cashu-ffi/src/nuts/nut07/mod.rs @@ -1,4 +1,4 @@ -use std::sync::Arc; +use std::{ops::Deref, sync::Arc}; use cashu::nuts::nut07::{ CheckSpendableRequest as CheckSpendableRequestSdk, @@ -11,6 +11,13 @@ pub struct CheckSpendableRequest { inner: CheckSpendableRequestSdk, } +impl Deref for CheckSpendableRequest { + type Target = CheckSpendableRequestSdk; + fn deref(&self) -> &Self::Target { + &self.inner + } +} + impl CheckSpendableRequest { pub fn new(proofs: Vec>) -> Self { Self { diff --git a/bindings/cashu-ffi/src/nuts/nut08/mod.rs b/bindings/cashu-ffi/src/nuts/nut08/mod.rs index 7e2bb052..21d964d4 100644 --- a/bindings/cashu-ffi/src/nuts/nut08/mod.rs +++ b/bindings/cashu-ffi/src/nuts/nut08/mod.rs @@ -1,3 +1,4 @@ +use std::ops::Deref; use std::str::FromStr; use std::sync::Arc; @@ -11,6 +12,13 @@ pub struct MeltRequest { inner: MeltRequestSdk, } +impl Deref for MeltRequest { + type Target = MeltRequestSdk; + fn deref(&self) -> &Self::Target { + &self.inner + } +} + impl MeltRequest { pub fn new( proofs: Vec>, diff --git a/bindings/cashu-sdk-ffi/src/cashu_sdk.udl b/bindings/cashu-sdk-ffi/src/cashu_sdk.udl index 72b5d861..a5aba165 100644 --- a/bindings/cashu-sdk-ffi/src/cashu_sdk.udl +++ b/bindings/cashu-sdk-ffi/src/cashu_sdk.udl @@ -312,4 +312,25 @@ interface Wallet { Melted melt(Bolt11Invoice invoice, sequence proofs, Amount fee_reserve); [Throws=CashuSdkError] string proof_to_token(sequence proof, string? memo); +}; + + +interface Mint { + constructor(string secret, string derivation_path, record inactive_keysets, sequence spent_secrets, u8 max_order); + + KeySet active_keyset_pubkeys(); + KeySetResponse keysets(); + MintKeySet active_keyset(); + KeySet? keyset(string id); + [Throws=CashuSdkError] + PostMintResponse process_mint_request(MintRequest mint_request); + [Throws=CashuSdkError] + SplitResponse proccess_split_request(SplitRequest split_request); + [Throws=CashuSdkError] + string verify_proof(Proof proof); + [Throws=CashuSdkError] + void verify_melt_request(MeltRequest melt_request); + [Throws=CashuSdkError] + MeltResponse process_melt_request(MeltRequest melt_request, string preimage, Amount totoal_spent); + }; \ No newline at end of file diff --git a/bindings/cashu-sdk-ffi/src/error.rs b/bindings/cashu-sdk-ffi/src/error.rs index bed41221..d148c8ee 100644 --- a/bindings/cashu-sdk-ffi/src/error.rs +++ b/bindings/cashu-sdk-ffi/src/error.rs @@ -30,3 +30,11 @@ impl From for CashuSdkError { } } } + +impl From for CashuSdkError { + fn from(err: cashu_sdk::mint::Error) -> CashuSdkError { + Self::Generic { + err: err.to_string(), + } + } +} diff --git a/bindings/cashu-sdk-ffi/src/mint.rs b/bindings/cashu-sdk-ffi/src/mint.rs new file mode 100644 index 00000000..0e75b295 --- /dev/null +++ b/bindings/cashu-sdk-ffi/src/mint.rs @@ -0,0 +1,139 @@ +use std::{ + collections::HashMap, + ops::Deref, + sync::{Arc, RwLock}, +}; + +use cashu_sdk::mint::Mint as MintSdk; + +use crate::error::Result; +use cashu_ffi::{ + Amount, CheckSpendableRequest, CheckSpendableResponse, KeySet, KeySetResponse, MeltRequest, + MeltResponse, MintKeySet, MintRequest, PostMintResponse, Proof, SplitRequest, SplitResponse, +}; + +pub struct Mint { + inner: RwLock, +} + +impl Mint { + pub fn new( + secret: String, + derivation_path: String, + inactive_keysets: HashMap>, + spent_secrets: Vec, + max_order: u8, + ) -> Self { + let spent_secrets = spent_secrets.into_iter().collect(); + + let inactive_keysets = inactive_keysets + .into_iter() + .map(|(k, v)| (k, v.as_ref().deref().clone())) + .collect(); + + Self { + inner: MintSdk::new( + &secret, + &derivation_path, + inactive_keysets, + spent_secrets, + max_order, + ) + .into(), + } + } + + pub fn active_keyset_pubkeys(&self) -> Arc { + Arc::new(self.inner.read().unwrap().active_keyset_pubkeys().into()) + } + + pub fn keysets(&self) -> Arc { + Arc::new(self.inner.read().unwrap().keysets().into()) + } + + pub fn active_keyset(&self) -> Arc { + Arc::new(self.inner.read().unwrap().active_keyset.clone().into()) + } + + pub fn keyset(&self, id: String) -> Option> { + self.inner + .read() + .unwrap() + .keyset(&id) + .map(|k| Arc::new(k.into())) + } + + pub fn process_mint_request( + &self, + mint_request: Arc, + ) -> Result> { + Ok(Arc::new( + self.inner + .write() + .unwrap() + .process_mint_request(mint_request.as_ref().deref().clone())? + .into(), + )) + } + + pub fn proccess_split_request( + &self, + split_request: Arc, + ) -> Result> { + Ok(Arc::new( + self.inner + .write() + .unwrap() + .process_split_request(split_request.as_ref().deref().clone())? + .into(), + )) + } + + pub fn verify_proof(&self, proof: Arc) -> Result { + Ok(self + .inner + .read() + .unwrap() + .verify_proof(proof.as_ref().deref())?) + } + + pub fn check_spendable( + &self, + check_spendable: Arc, + ) -> Result> { + Ok(Arc::new( + self.inner + .read() + .unwrap() + .check_spendable(check_spendable.as_ref().deref())? + .into(), + )) + } + + pub fn verify_melt_request(&self, melt_request: Arc) -> Result<()> { + Ok(self + .inner + .write() + .unwrap() + .verify_melt_request(melt_request.as_ref().deref())?) + } + + pub fn process_melt_request( + &self, + melt_request: Arc, + preimage: String, + total_spent: Arc, + ) -> Result> { + Ok(Arc::new( + self.inner + .write() + .unwrap() + .process_melt_request( + melt_request.as_ref().deref(), + &preimage, + *total_spent.as_ref().deref(), + )? + .into(), + )) + } +} diff --git a/crates/cashu-sdk/src/mint.rs b/crates/cashu-sdk/src/mint.rs index 179528af..57417e83 100644 --- a/crates/cashu-sdk/src/mint.rs +++ b/crates/cashu-sdk/src/mint.rs @@ -2,7 +2,7 @@ use std::collections::{HashMap, HashSet}; use cashu::dhke::sign_message; use cashu::dhke::verify_message; -use cashu::error::mint::Error; +pub use cashu::error::mint::Error; use cashu::nuts::nut00::BlindedMessage; use cashu::nuts::nut00::BlindedSignature; use cashu::nuts::nut00::Proof;