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

This commit is contained in:
thesimplekid
2023-11-12 14:32:03 +00:00
parent 659fc3aaf5
commit 0c9f6057bd
6 changed files with 60 additions and 173 deletions

View File

@@ -12,10 +12,18 @@ crate-type = ["cdylib", "staticlib"]
[dependencies] [dependencies]
cashu-ffi = { path = "../cashu-ffi" } 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 = { workspace = true }
tracing-subscriber = { workspace = true } tracing-subscriber = { workspace = true }
uniffi = { 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] [build-dependencies]
uniffi = { workspace = true, features = ["build"] } uniffi = { workspace = true, features = ["build"] }

View File

@@ -289,31 +289,7 @@ interface Melted {
sequence<Proof>? change(); 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 { interface Wallet {
constructor(Client client, Keys mint_keys);
// [Throws=CashuSdkError] // [Throws=CashuSdkError]
// ProofsStatus check_proofs_spent(sequence<MintProof> proofs); // ProofsStatus check_proofs_spent(sequence<MintProof> proofs);
[Throws=CashuSdkError] [Throws=CashuSdkError]

View File

@@ -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()))
}
}

View File

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

View File

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

View File

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