Jelajahi Sumber

fix: cashu-sdk-ffi remove client, use async client with spawn blocking

thesimplekid 1 tahun lalu
induk
melakukan
0c9f6057bd

+ 9 - 1
bindings/cashu-sdk-ffi/Cargo.toml

@@ -12,10 +12,18 @@ crate-type = ["cdylib", "staticlib"]
 
 [dependencies]
 cashu-ffi = { path = "../cashu-ffi" }
-cashu-sdk = { path = "../../crates/cashu-sdk", default-features = false, features = ["wallet", "mint"] }
+cashu-sdk = { path = "../../crates/cashu-sdk", default-features = false, features = ["wallet", "mint", "all-nuts"] }
 tracing = { workspace = true }
 tracing-subscriber = { workspace = true }
 uniffi = { workspace = true }
+futures = { version= "0.3.29", feature = "executor" }
+once_cell = { version = "1.17" }
+
+[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
+tokio = { workspace = true, features = ["rt-multi-thread", "time", "macros", "sync"] }
+
+[target.'cfg(target_arch = "wasm32")'.dependencies]
+tokio = { workspace = true, features = ["rt", "macros", "sync", "time"] }
 
 [build-dependencies]
 uniffi = { workspace = true, features = ["build"] }

+ 0 - 24
bindings/cashu-sdk-ffi/src/cashu_sdk.udl

@@ -289,31 +289,7 @@ interface Melted {
 	sequence<Proof>? change();
 };
 
-interface Client {
-    [Throws=CashuSdkError]
-	constructor(string mint_url);
-	[Throws=CashuSdkError]
-	Keys get_keys();
-    [Throws=CashuSdkError]
-	KeySetResponse get_keysets();
-    [Throws=CashuSdkError]
-    RequestMintResponse request_mint(Amount amount);
-    [Throws=CashuSdkError]
-	PostMintResponse mint(BlindedMessages blinded_messages, string hash);
-    [Throws=CashuSdkError]
-    CheckFeesResponse check_fees(Bolt11Invoice invoice);
-    [Throws=CashuSdkError]
-	MeltResponse melt(sequence<Proof> proofs, Bolt11Invoice invoice, sequence<BlindedMessage>? outputs);
-    [Throws=CashuSdkError]
-    SplitResponse split(SplitRequest split_request);
-    [Throws=CashuSdkError]
-	CheckSpendableResponse check_spendable(sequence<MintProof> proofs);
-    [Throws=CashuSdkError]
-    MintInfo get_info();
-};
-
 interface Wallet {
-	constructor(Client client, Keys mint_keys);
 	// [Throws=CashuSdkError]
 	// ProofsStatus check_proofs_spent(sequence<MintProof> proofs);
     [Throws=CashuSdkError]

+ 0 - 105
bindings/cashu-sdk-ffi/src/client.rs

@@ -1,105 +0,0 @@
-use std::ops::Deref;
-use std::sync::Arc;
-
-use cashu_ffi::{
-    BlindedMessage, BlindedMessages, Bolt11Invoice, CheckFeesResponse, CheckSpendableResponse,
-    KeySetResponse, MeltResponse, MintInfo, MintProof, PostMintResponse, Proof,
-    RequestMintResponse, SplitRequest, SplitResponse,
-};
-use cashu_sdk::client::blocking::Client as ClientSdk;
-
-use crate::error::Result;
-use crate::{Amount, Keys};
-
-pub struct Client {
-    inner: ClientSdk,
-}
-
-impl Deref for Client {
-    type Target = ClientSdk;
-    fn deref(&self) -> &Self::Target {
-        &self.inner
-    }
-}
-
-impl Client {
-    pub fn new(mint_url: String) -> Result<Self> {
-        Ok(Self {
-            inner: ClientSdk::new(&mint_url)?,
-        })
-    }
-
-    pub fn get_keys(&self) -> Result<Arc<Keys>> {
-        Ok(Arc::new(self.inner.get_keys()?.into()))
-    }
-
-    pub fn get_keysets(&self) -> Result<Arc<KeySetResponse>> {
-        Ok(Arc::new(self.inner.get_keysets()?.into()))
-    }
-
-    pub fn request_mint(&self, amount: Arc<Amount>) -> Result<Arc<RequestMintResponse>> {
-        Ok(Arc::new(
-            self.inner.request_mint(*amount.as_ref().deref())?.into(),
-        ))
-    }
-
-    pub fn mint(
-        &self,
-        blinded_messages: Arc<BlindedMessages>,
-        hash: String,
-    ) -> Result<Arc<PostMintResponse>> {
-        Ok(Arc::new(
-            self.inner
-                .mint(blinded_messages.as_ref().deref().clone(), &hash)?
-                .into(),
-        ))
-    }
-
-    pub fn check_fees(&self, invoice: Arc<Bolt11Invoice>) -> Result<Arc<CheckFeesResponse>> {
-        Ok(Arc::new(
-            self.inner
-                .check_fees(invoice.as_ref().deref().clone())?
-                .into(),
-        ))
-    }
-
-    pub fn melt(
-        &self,
-        proofs: Vec<Arc<Proof>>,
-        invoice: Arc<Bolt11Invoice>,
-        outputs: Option<Vec<Arc<BlindedMessage>>>,
-    ) -> Result<Arc<MeltResponse>> {
-        Ok(Arc::new(
-            self.inner
-                .melt(
-                    proofs.iter().map(|p| p.as_ref().deref().clone()).collect(),
-                    invoice.as_ref().deref().clone(),
-                    outputs.map(|bs| bs.iter().map(|b| b.as_ref().deref().clone()).collect()),
-                )?
-                .into(),
-        ))
-    }
-
-    pub fn split(&self, split_request: Arc<SplitRequest>) -> Result<Arc<SplitResponse>> {
-        Ok(Arc::new(
-            self.inner
-                .split(split_request.as_ref().deref().clone())?
-                .into(),
-        ))
-    }
-
-    pub fn check_spendable(
-        &self,
-        proofs: Vec<Arc<MintProof>>,
-    ) -> Result<Arc<CheckSpendableResponse>> {
-        Ok(Arc::new(
-            self.inner
-                .check_spendable(&proofs.iter().map(|p| p.as_ref().deref().clone()).collect())?
-                .into(),
-        ))
-    }
-
-    pub fn get_info(&self) -> Result<Arc<MintInfo>> {
-        Ok(Arc::new(self.inner.get_info()?.into()))
-    }
-}

+ 0 - 2
bindings/cashu-sdk-ffi/src/lib.rs

@@ -1,4 +1,3 @@
-mod client;
 mod error;
 mod mint;
 mod types;
@@ -14,7 +13,6 @@ mod ffi {
         RequestMintResponse, Secret, SecretKey, SplitRequest, SplitResponse, Token,
     };
 
-    pub use crate::client::Client;
     pub use crate::error::CashuSdkError;
     pub use crate::mint::Mint;
     pub use crate::types::{Melted, ProofsStatus, SendProofs};

+ 50 - 41
bindings/cashu-sdk-ffi/src/wallet.rs

@@ -4,72 +4,77 @@ use std::sync::Arc;
 use cashu_ffi::{
     BlindedMessages, BlindedSignature, Bolt11Invoice, Proof, RequestMintResponse, Token,
 };
+use cashu_sdk::client::minreq_client::HttpClient;
 use cashu_sdk::types::ProofsStatus;
+use cashu_sdk::url::UncheckedUrl;
 use cashu_sdk::wallet::Wallet as WalletSdk;
+use once_cell::sync::Lazy;
+use tokio::runtime::Runtime;
 
-use crate::client::Client;
 use crate::error::Result;
 use crate::types::{Melted, SendProofs};
 use crate::{Amount, Keys, MintProof};
 
+static RUNTIME: Lazy<Runtime> = Lazy::new(|| Runtime::new().expect("Can't start Tokio runtime"));
+
 pub struct Wallet {
-    inner: WalletSdk,
+    inner: WalletSdk<HttpClient>,
 }
 
 impl Wallet {
-    pub fn new(client: Arc<Client>, mint_keys: Arc<Keys>) -> Self {
+    pub fn new(mint_url: &str, mint_keys: Arc<Keys>) -> Self {
+        let client = HttpClient {};
         Self {
             inner: WalletSdk::new(
-                client.as_ref().deref().clone(),
+                client,
+                UncheckedUrl::new(mint_url),
                 mint_keys.as_ref().deref().clone(),
             ),
         }
     }
 
     pub fn check_proofs_spent(&self, proofs: Vec<Arc<MintProof>>) -> Result<Arc<ProofsStatus>> {
-        Ok(Arc::new(self.inner.check_proofs_spent(
-            &proofs.iter().map(|p| p.as_ref().deref().clone()).collect(),
-        )?))
+        let proofs = RUNTIME.block_on(async {
+            self.inner
+                .check_proofs_spent(proofs.iter().map(|p| p.as_ref().deref().clone()).collect())
+                .await
+        })?;
+
+        Ok(Arc::new(proofs))
     }
 
     pub fn request_mint(&self, amount: Arc<Amount>) -> Result<Arc<RequestMintResponse>> {
-        Ok(Arc::new(
-            self.inner.request_mint(*amount.as_ref().deref())?.into(),
-        ))
+        let mint_response = RUNTIME
+            .block_on(async { self.inner.request_mint(*amount.as_ref().deref()).await })?
+            .into();
+        Ok(Arc::new(mint_response))
     }
 
     pub fn mint_token(&self, amount: Arc<Amount>, hash: String) -> Result<Arc<Token>> {
-        Ok(Arc::new(
-            self.inner
-                .mint_token(*amount.as_ref().deref(), &hash)?
-                .into(),
-        ))
+        let token = RUNTIME
+            .block_on(async { self.inner.mint_token(*amount.as_ref().deref(), &hash).await })?;
+
+        Ok(Arc::new(token.into()))
     }
 
     pub fn mint(&self, amount: Arc<Amount>, hash: String) -> Result<Vec<Arc<Proof>>> {
-        Ok(self
-            .inner
-            .mint(*amount.as_ref().deref(), &hash)?
-            .into_iter()
-            .map(|p| Arc::new(p.into()))
-            .collect())
+        let proofs =
+            RUNTIME.block_on(async { self.inner.mint(*amount.as_ref().deref(), &hash).await })?;
+
+        Ok(proofs.into_iter().map(|p| Arc::new(p.into())).collect())
     }
 
     pub fn check_fee(&self, invoice: Arc<Bolt11Invoice>) -> Result<Arc<Amount>> {
-        Ok(Arc::new(
-            self.inner
-                .check_fee(invoice.as_ref().deref().clone())?
-                .into(),
-        ))
+        let amount = RUNTIME
+            .block_on(async { self.inner.check_fee(invoice.as_ref().deref().clone()).await })?;
+
+        Ok(Arc::new(amount.into()))
     }
 
     pub fn receive(&self, encoded_token: String) -> Result<Vec<Arc<Proof>>> {
-        Ok(self
-            .inner
-            .receive(&encoded_token)?
-            .into_iter()
-            .map(|p| Arc::new(p.into()))
-            .collect())
+        let proofs = RUNTIME.block_on(async { self.inner.receive(&encoded_token).await })?;
+
+        Ok(proofs.into_iter().map(|p| Arc::new(p.into())).collect())
     }
 
     pub fn process_split_response(
@@ -81,7 +86,7 @@ impl Wallet {
             .inner
             .process_split_response(
                 blinded_messages.as_ref().deref().clone(),
-                promises.iter().map(|p| p.as_ref().deref().into()).collect(),
+                promises.iter().map(|p| p.as_ref().into()).collect(),
             )?
             .into_iter()
             .map(|p| Arc::new(p.into()))
@@ -89,14 +94,16 @@ impl Wallet {
     }
 
     pub fn send(&self, amount: Arc<Amount>, proofs: Vec<Arc<Proof>>) -> Result<Arc<SendProofs>> {
-        Ok(Arc::new(
+        let send_proofs = RUNTIME.block_on(async {
             self.inner
                 .send(
                     *amount.as_ref().deref(),
                     proofs.iter().map(|p| p.as_ref().deref().clone()).collect(),
-                )?
-                .into(),
-        ))
+                )
+                .await
+        })?;
+
+        Ok(Arc::new(send_proofs.into()))
     }
 
     pub fn melt(
@@ -105,15 +112,17 @@ impl Wallet {
         proofs: Vec<Arc<Proof>>,
         fee_reserve: Arc<Amount>,
     ) -> Result<Arc<Melted>> {
-        Ok(Arc::new(
+        let melted = RUNTIME.block_on(async {
             self.inner
                 .melt(
                     invoice.as_ref().deref().clone(),
                     proofs.iter().map(|p| p.as_ref().deref().clone()).collect(),
                     *fee_reserve.as_ref().deref(),
-                )?
-                .into(),
-        ))
+                )
+                .await
+        })?;
+
+        Ok(Arc::new(melted.into()))
     }
 
     pub fn proof_to_token(&self, proofs: Vec<Arc<Proof>>, memo: Option<String>) -> Result<String> {

+ 1 - 0
crates/cashu-sdk/Cargo.toml

@@ -13,6 +13,7 @@ license.workspace = true
 default = ["mint", "wallet"]
 mint = ["cashu/mint"]
 wallet = ["cashu/wallet", "dep:minreq", "dep:once_cell"]
+all-nuts = ["nut07", "nut09"]
 nut07 = ["cashu/nut07"]
 # nut08 = ["cashu/nut08"]
 nut09 = ["cashu/nut09"]