mirror of
https://github.com/aljazceru/cdk.git
synced 2025-12-21 22:54:49 +01:00
fix: cashu-sdk-ffi remove client, use async client with spawn blocking
This commit is contained in:
@@ -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"] }
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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};
|
||||||
|
|||||||
@@ -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> {
|
||||||
|
|||||||
@@ -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"]
|
||||||
|
|||||||
Reference in New Issue
Block a user