Procházet zdrojové kódy

`bindings/cashu-sdk:` add ffi bindings for `mint` and `wallet`

thesimplekid před 1 rokem
rodič
revize
0beca645b8

+ 1 - 1
.helix/languages.toml

@@ -1,4 +1,4 @@
 [[language]]
 name = "rust"
-config = { cargo = { features = [ "blocking", "wallet" ] } }
+config = { cargo = { features = [ "blocking", "wallet", "mint" ] } }
 

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

@@ -11,7 +11,7 @@ crate-type = ["lib", "cdylib", "staticlib"]
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
 [dependencies]
-cashu  = { path = "../../crates/cashu", featues = ["wallet", "mint"] }
+cashu  = { path = "../../crates/cashu", features = ["wallet", "mint"] }
 url = { workspace = true }
 uniffi = { workspace = true }
 

+ 0 - 50
bindings/cashu-ffi/justfile

@@ -6,56 +6,6 @@ init:
 	cargo install cbindgen
 	cargo install cargo-ndk
 
-
-kotlin:
-	$(JUST) ffi-kotlin-clean
-	$(JUST) ffi-kotlin-generate
-
-ffi-kotlin-clean:
-	find ./ffi/kotlin/jniLibs -name libcashu_sdk_ffi.so -type f -delete
-
-ffi-kotlin-generate:
-	cargo run -p uniffi-bindgen generate src/cashu.udl --language kotlin --no-format -o ffi/kotlin
-
-android: aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android
-
-aarch64-linux-android:
-	cargo ndk -t aarch64-linux-android -o ffi/kotlin/jniLibs build --release
-
-armv7-linux-androideabi:
-	$(JUST) ffi-ndk-build TARGET=armv7-linux-androideabi
-
-i686-linux-android:
-	$(JUST) ffi-ndk-build TARGET=i686-linux-android
-
-x86_64-linux-android:
-	$(JUST) ffi-ndk-build TARGET=x86_64-linux-android
-
-ffi-ndk-build:
-	cargo ndk -t $(TARGET) -o ffi/kotlin/jniLibs build --release
-
-bindings-android:
-	$(JUST) bindings-android-clean
-	$(JUST) bindings-android-copy
-	cd bindings-android && ./gradlew assemble
-	$(JUST) bindings-android-package
-
-bindings-android-clean:
-	rm -rf bindings-android/lib/src/main/jniLibs
-	rm -rf bindings-android/lib/src/main/kotlin
-
-bindings-android-copy:
-	cp -r ffi/kotlin/jniLibs bindings-android/lib/src/main
-	cp -r ffi/kotlin/cashu bindings-android/lib/src/main/kotlin/
-
-bindings-android-package:
-	mkdir -p ffi/android
-	cp bindings-android/lib/build/outputs/aar/lib-release.aar ffi/android
-
-publish-android:
-	cd bindings-android && ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository
-
-
 python:
 	rm -rf dist
 	pip install -r bindings-python/requirements.txt

+ 12 - 0
bindings/cashu-ffi/src/nuts/nut00/blinded_messages.rs

@@ -59,3 +59,15 @@ impl BlindedMessages {
             .collect()
     }
 }
+
+impl From<cashu::nuts::nut00::wallet::BlindedMessages> for BlindedMessages {
+    fn from(inner: cashu::nuts::nut00::wallet::BlindedMessages) -> BlindedMessages {
+        BlindedMessages { inner }
+    }
+}
+
+impl From<BlindedMessages> for cashu::nuts::nut00::wallet::BlindedMessages {
+    fn from(blinded_messages: BlindedMessages) -> cashu::nuts::nut00::wallet::BlindedMessages {
+        blinded_messages.inner
+    }
+}

+ 2 - 4
bindings/cashu-ffi/src/nuts/nut00/mint_proofs.rs

@@ -32,14 +32,12 @@ impl MintProofs {
     }
 
     pub fn proofs(&self) -> Vec<Arc<Proof>> {
-        let proofs = self
-            .inner
+        self.inner
             .proofs
             .clone()
             .into_iter()
             .map(|p| Arc::new(p.into()))
-            .collect();
-        proofs
+            .collect()
     }
 }
 

+ 12 - 6
bindings/cashu-ffi/src/nuts/nut00/token.rs

@@ -8,7 +8,7 @@ use crate::MintProofs;
 use crate::Proof;
 
 pub struct Token {
-    token: TokenSdk,
+    inner: TokenSdk,
 }
 
 impl Token {
@@ -16,12 +16,12 @@ impl Token {
         let mint = url::Url::from_str(&mint)?;
         let proofs = proofs.into_iter().map(|p| p.as_ref().into()).collect();
         Ok(Self {
-            token: TokenSdk::new(mint, proofs, memo)?,
+            inner: TokenSdk::new(mint, proofs, memo)?,
         })
     }
 
     pub fn token(&self) -> Vec<Arc<MintProofs>> {
-        self.token
+        self.inner
             .token
             .clone()
             .into_iter()
@@ -30,16 +30,22 @@ impl Token {
     }
 
     pub fn memo(&self) -> Option<String> {
-        self.token.memo.clone()
+        self.inner.memo.clone()
     }
 
     pub fn from_string(token: String) -> Result<Self> {
         Ok(Self {
-            token: TokenSdk::from_str(&token)?,
+            inner: TokenSdk::from_str(&token)?,
         })
     }
 
     pub fn as_string(&self) -> Result<String> {
-        Ok(self.token.convert_to_string()?)
+        Ok(self.inner.convert_to_string()?)
+    }
+}
+
+impl From<cashu::nuts::nut00::wallet::Token> for Token {
+    fn from(inner: cashu::nuts::nut00::wallet::Token) -> Token {
+        Token { inner }
     }
 }

+ 6 - 0
bindings/cashu-ffi/src/nuts/nut02/key_set.rs

@@ -53,3 +53,9 @@ impl KeySetResponse {
         self.inner.clone().keysets.into_iter().collect()
     }
 }
+
+impl From<cashu::nuts::nut02::Response> for KeySetResponse {
+    fn from(inner: Response) -> KeySetResponse {
+        KeySetResponse { inner }
+    }
+}

+ 8 - 0
bindings/cashu-ffi/src/nuts/nut03/mod.rs

@@ -25,3 +25,11 @@ impl RequestMintResponse {
         self.inner.hash.to_string()
     }
 }
+
+impl From<cashu::nuts::nut03::RequestMintResponse> for RequestMintResponse {
+    fn from(mint_response: cashu::nuts::nut03::RequestMintResponse) -> RequestMintResponse {
+        RequestMintResponse {
+            inner: mint_response,
+        }
+    }
+}

+ 6 - 0
bindings/cashu-ffi/src/nuts/nut04/mod.rs

@@ -56,3 +56,9 @@ impl PostMintResponse {
             .collect()
     }
 }
+
+impl From<cashu::nuts::nut04::PostMintResponse> for PostMintResponse {
+    fn from(inner: cashu::nuts::nut04::PostMintResponse) -> PostMintResponse {
+        PostMintResponse { inner }
+    }
+}

+ 12 - 0
bindings/cashu-ffi/src/nuts/nut05/mod.rs

@@ -46,6 +46,18 @@ impl CheckFeesResponse {
     }
 }
 
+impl From<cashu::nuts::nut05::CheckFeesResponse> for CheckFeesResponse {
+    fn from(inner: cashu::nuts::nut05::CheckFeesResponse) -> CheckFeesResponse {
+        Self { inner }
+    }
+}
+
+impl From<CheckFeesResponse> for cashu::nuts::nut05::CheckFeesResponse {
+    fn from(res: CheckFeesResponse) -> cashu::nuts::nut05::CheckFeesResponse {
+        res.inner
+    }
+}
+
 pub struct MeltRequest {
     inner: MeltRequestSdk,
 }

+ 14 - 1
bindings/cashu-ffi/src/nuts/nut06/mod.rs

@@ -1,4 +1,4 @@
-use std::sync::Arc;
+use std::{ops::Deref, sync::Arc};
 
 use cashu::nuts::nut06::{SplitRequest as SplitRequestSdk, SplitResponse as SplitResponseSdk};
 
@@ -8,6 +8,13 @@ pub struct SplitRequest {
     inner: SplitRequestSdk,
 }
 
+impl Deref for SplitRequest {
+    type Target = SplitRequestSdk;
+    fn deref(&self) -> &Self::Target {
+        &self.inner
+    }
+}
+
 impl SplitRequest {
     pub fn new(proofs: Vec<Arc<Proof>>, outputs: Vec<Arc<BlindedMessage>>) -> Self {
         let proofs = proofs.into_iter().map(|p| p.as_ref().into()).collect();
@@ -79,3 +86,9 @@ impl SplitResponse {
         self.inner.promises_amount().map(|a| Arc::new(a.into()))
     }
 }
+
+impl From<cashu::nuts::nut06::SplitResponse> for SplitResponse {
+    fn from(inner: cashu::nuts::nut06::SplitResponse) -> SplitResponse {
+        SplitResponse { inner }
+    }
+}

+ 6 - 0
bindings/cashu-ffi/src/nuts/nut07/mod.rs

@@ -49,3 +49,9 @@ impl CheckSpendableResponse {
         self.inner.pending.clone()
     }
 }
+
+impl From<cashu::nuts::nut07::CheckSpendableResponse> for CheckSpendableResponse {
+    fn from(inner: cashu::nuts::nut07::CheckSpendableResponse) -> CheckSpendableResponse {
+        CheckSpendableResponse { inner }
+    }
+}

+ 12 - 0
bindings/cashu-ffi/src/nuts/nut08/mod.rs

@@ -85,3 +85,15 @@ impl MeltResponse {
             .map(|change| change.into_iter().map(|bs| Arc::new(bs.into())).collect())
     }
 }
+
+impl From<cashu::nuts::nut08::MeltResponse> for MeltResponse {
+    fn from(inner: cashu::nuts::nut08::MeltResponse) -> MeltResponse {
+        MeltResponse { inner }
+    }
+}
+
+impl From<MeltResponse> for cashu::nuts::nut08::MeltResponse {
+    fn from(res: MeltResponse) -> cashu::nuts::nut08::MeltResponse {
+        res.inner
+    }
+}

+ 6 - 0
bindings/cashu-ffi/src/nuts/nut09/mod.rs

@@ -74,3 +74,9 @@ impl MintInfo {
         }
     }
 }
+
+impl From<cashu::nuts::nut09::MintInfo> for MintInfo {
+    fn from(inner: cashu::nuts::nut09::MintInfo) -> MintInfo {
+        MintInfo { inner }
+    }
+}

+ 0 - 1
bindings/cashu-sdk-ffi/bindings-python/.gitignore

@@ -13,5 +13,4 @@ src/cashu-sdk/*.so
 *.whl
 build/
 
-testing-setup-py-simple-example.py
 

+ 3 - 0
bindings/cashu-sdk-ffi/bindings-python/examples/test.py

@@ -0,0 +1,3 @@
+import cashu_sdk;
+
+help(cashu_sdk)

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

@@ -7,6 +7,14 @@ interface CashuError {
     Generic(string err);
 };
 
+
+interface Bolt11Invoice {
+    [Throws=CashuError]
+    constructor(string bolt11);
+	string as_string();
+	Amount? amount();
+};
+
 interface Amount {
 	u64 to_sat();	
 	u64 to_msat();
@@ -216,4 +224,73 @@ enum InvoiceStatus {
 	"Paid",
 	"Expired",
 	"InFlight"
+};
+
+// Cashu Sdk
+
+
+[Error]
+interface CashuSdkError {
+    Generic(string err);
+};
+
+interface SendProofs {
+	constructor(sequence<Proof> change_proofs, sequence<Proof> send_proofs);
+	sequence<Proof> send_proofs();
+	sequence<Proof> change_proofs();
+};
+
+interface Melted {
+	constructor(boolean paid, string? preimage, sequence<Proof>? change);
+	string? preimage();
+	boolean paid();
+	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);
+    // TODO: ProofStatus type
+	// [Throws=CashuSdkError]
+	// ProofsStatus check_proofs_spent(sequence<MintProof> proofs);
+    [Throws=CashuSdkError]
+	RequestMintResponse request_mint(Amount amount);
+    [Throws=CashuSdkError]
+	Token mint_token(Amount amount, string hash);
+    [Throws=CashuSdkError]
+	sequence<Proof> mint(Amount amount, string hash);
+    [Throws=CashuSdkError]
+	Amount check_fee(Bolt11Invoice invoice);
+    [Throws=CashuSdkError]
+	sequence<Proof> receive(string encoded_token);
+    [Throws=CashuSdkError]
+	sequence<Proof> process_split_response(BlindedMessages blinded_messages, sequence<BlindedSignature> promises);
+    [Throws=CashuSdkError]
+	SendProofs send(Amount amount, sequence<Proof> proofs);
+    [Throws=CashuSdkError]
+	Melted melt(Bolt11Invoice invoice, sequence<Proof> proofs, Amount fee_reserve);
+    [Throws=CashuSdkError]
+	string proof_to_token(sequence<Proof> proof, string? memo);
 };

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

@@ -0,0 +1,105 @@
+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()))
+    }
+}

+ 32 - 0
bindings/cashu-sdk-ffi/src/error.rs

@@ -0,0 +1,32 @@
+use std::fmt;
+
+pub type Result<T, E = CashuSdkError> = std::result::Result<T, E>;
+
+#[derive(Debug)]
+pub enum CashuSdkError {
+    Generic { err: String },
+}
+
+impl fmt::Display for CashuSdkError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::Generic { err } => write!(f, "{err}"),
+        }
+    }
+}
+
+impl From<cashu_sdk::client::Error> for CashuSdkError {
+    fn from(err: cashu_sdk::client::Error) -> CashuSdkError {
+        Self::Generic {
+            err: err.to_string(),
+        }
+    }
+}
+
+impl From<cashu_sdk::wallet::Error> for CashuSdkError {
+    fn from(err: cashu_sdk::wallet::Error) -> CashuSdkError {
+        Self::Generic {
+            err: err.to_string(),
+        }
+    }
+}

+ 16 - 5
bindings/cashu-sdk-ffi/src/lib.rs

@@ -1,12 +1,23 @@
+mod client;
+mod error;
+mod types;
+mod wallet;
+
 mod ffi {
     pub use cashu_ffi::{
-        Amount, BlindedMessage, BlindedMessages, BlindedSignature, CashuError, CheckFeesRequest,
-        CheckFeesResponse, CheckSpendableRequest, CheckSpendableResponse, InvoiceStatus, KeyPair,
-        KeySet, KeySetResponse, Keys, MeltRequest, MeltResponse, MintInfo, MintProof, MintProofs,
-        MintRequest, MintVersion, Nut05MeltRequest, Nut05MeltResponse, PostMintResponse, Proof,
-        PublicKey, RequestMintResponse, SecretKey, SplitRequest, SplitResponse, Token,
+        Amount, BlindedMessage, BlindedMessages, BlindedSignature, Bolt11Invoice, CashuError,
+        CheckFeesRequest, CheckFeesResponse, CheckSpendableRequest, CheckSpendableResponse,
+        InvoiceStatus, KeyPair, KeySet, KeySetResponse, Keys, MeltRequest, MeltResponse, MintInfo,
+        MintProof, MintProofs, MintRequest, MintVersion, Nut05MeltRequest, Nut05MeltResponse,
+        PostMintResponse, Proof, PublicKey, RequestMintResponse, SecretKey, SplitRequest,
+        SplitResponse, Token,
     };
 
+    pub use crate::client::Client;
+    pub use crate::error::CashuSdkError;
+    pub use crate::types::{Melted, SendProofs};
+    pub use crate::wallet::Wallet;
+
     // UDL
     uniffi::include_scaffolding!("cashu_sdk");
 }

+ 42 - 0
bindings/cashu-sdk-ffi/src/types/melted.rs

@@ -0,0 +1,42 @@
+use std::{ops::Deref, sync::Arc};
+
+use cashu_sdk::types::Melted as MeltedSdk;
+
+use cashu_ffi::Proof;
+
+pub struct Melted {
+    inner: MeltedSdk,
+}
+
+impl Melted {
+    pub fn new(paid: bool, preimage: Option<String>, change: Option<Vec<Arc<Proof>>>) -> Self {
+        Self {
+            inner: MeltedSdk {
+                paid,
+                preimage,
+                change: change.map(|c| c.iter().map(|p| p.as_ref().deref().clone()).collect()),
+            },
+        }
+    }
+
+    pub fn preimage(&self) -> Option<String> {
+        self.inner.preimage.clone()
+    }
+
+    pub fn paid(&self) -> bool {
+        self.inner.paid
+    }
+
+    pub fn change(&self) -> Option<Vec<Arc<Proof>>> {
+        self.inner
+            .change
+            .clone()
+            .map(|c| c.into_iter().map(|p| Arc::new(p.into())).collect())
+    }
+}
+
+impl From<cashu_sdk::types::Melted> for Melted {
+    fn from(inner: cashu_sdk::types::Melted) -> Melted {
+        Melted { inner }
+    }
+}

+ 5 - 0
bindings/cashu-sdk-ffi/src/types/mod.rs

@@ -0,0 +1,5 @@
+pub mod melted;
+pub mod send_proofs;
+
+pub use melted::Melted;
+pub use send_proofs::SendProofs;

+ 50 - 0
bindings/cashu-sdk-ffi/src/types/send_proofs.rs

@@ -0,0 +1,50 @@
+use std::{ops::Deref, sync::Arc};
+
+use cashu_sdk::types::SendProofs as SendProofSdk;
+
+use cashu_ffi::Proof;
+
+pub struct SendProofs {
+    inner: SendProofSdk,
+}
+
+impl SendProofs {
+    pub fn new(change_proofs: Vec<Arc<Proof>>, send_proofs: Vec<Arc<Proof>>) -> Self {
+        Self {
+            inner: SendProofSdk {
+                change_proofs: change_proofs
+                    .iter()
+                    .map(|p| p.as_ref().deref().clone())
+                    .collect(),
+                send_proofs: send_proofs
+                    .iter()
+                    .map(|p| p.as_ref().deref().clone())
+                    .collect(),
+            },
+        }
+    }
+
+    pub fn send_proofs(&self) -> Vec<Arc<Proof>> {
+        self.inner
+            .send_proofs
+            .clone()
+            .into_iter()
+            .map(|p| Arc::new(p.into()))
+            .collect()
+    }
+
+    pub fn change_proofs(&self) -> Vec<Arc<Proof>> {
+        self.inner
+            .change_proofs
+            .clone()
+            .into_iter()
+            .map(|p| Arc::new(p.into()))
+            .collect()
+    }
+}
+
+impl From<cashu_sdk::types::SendProofs> for SendProofs {
+    fn from(inner: cashu_sdk::types::SendProofs) -> SendProofs {
+        SendProofs { inner }
+    }
+}

+ 127 - 0
bindings/cashu-sdk-ffi/src/wallet.rs

@@ -0,0 +1,127 @@
+use std::ops::Deref;
+use std::sync::Arc;
+
+use cashu_ffi::{
+    BlindedMessages, BlindedSignature, Bolt11Invoice, Proof, RequestMintResponse, Token,
+};
+use cashu_sdk::types::ProofsStatus;
+use cashu_sdk::wallet::Wallet as WalletSdk;
+
+use crate::{
+    client::Client,
+    error::Result,
+    types::{Melted, SendProofs},
+    Amount, Keys, MintProof,
+};
+
+pub struct Wallet {
+    inner: WalletSdk,
+}
+
+impl Wallet {
+    pub fn new(client: Arc<Client>, mint_keys: Arc<Keys>) -> Self {
+        Self {
+            inner: WalletSdk::new(
+                client.as_ref().deref().clone(),
+                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(),
+        )?))
+    }
+
+    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_token(&self, amount: Arc<Amount>, hash: String) -> Result<Arc<Token>> {
+        Ok(Arc::new(
+            self.inner
+                .mint_token(*amount.as_ref().deref(), &hash)?
+                .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())
+    }
+
+    pub fn check_fee(&self, invoice: Arc<Bolt11Invoice>) -> Result<Arc<Amount>> {
+        Ok(Arc::new(
+            self.inner
+                .check_fee(invoice.as_ref().deref().clone())?
+                .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())
+    }
+
+    pub fn process_split_response(
+        &self,
+        blinded_messages: Arc<BlindedMessages>,
+        promises: Vec<Arc<BlindedSignature>>,
+    ) -> Result<Vec<Arc<Proof>>> {
+        Ok(self
+            .inner
+            .process_split_response(
+                blinded_messages.as_ref().deref().clone(),
+                promises.iter().map(|p| p.as_ref().deref().into()).collect(),
+            )?
+            .into_iter()
+            .map(|p| Arc::new(p.into()))
+            .collect())
+    }
+
+    pub fn send(&self, amount: Arc<Amount>, proofs: Vec<Arc<Proof>>) -> Result<Arc<SendProofs>> {
+        Ok(Arc::new(
+            self.inner
+                .send(
+                    *amount.as_ref().deref(),
+                    proofs.iter().map(|p| p.as_ref().deref().clone()).collect(),
+                )?
+                .into(),
+        ))
+    }
+
+    pub fn melt(
+        &self,
+        invoice: Arc<Bolt11Invoice>,
+        proofs: Vec<Arc<Proof>>,
+        fee_reserve: Arc<Amount>,
+    ) -> Result<Arc<Melted>> {
+        Ok(Arc::new(
+            self.inner
+                .melt(
+                    invoice.as_ref().deref().clone(),
+                    proofs.iter().map(|p| p.as_ref().deref().clone()).collect(),
+                    *fee_reserve.as_ref().deref(),
+                )?
+                .into(),
+        ))
+    }
+
+    pub fn proof_to_token(&self, proofs: Vec<Arc<Proof>>, memo: Option<String>) -> Result<String> {
+        Ok(self.inner.proofs_to_token(
+            proofs.iter().map(|p| p.as_ref().deref().clone()).collect(),
+            memo,
+        )?)
+    }
+}

+ 2 - 2
crates/cashu-sdk/src/client/blocking.rs

@@ -44,10 +44,10 @@ impl Client {
 
     pub fn mint(
         &self,
-        blinded_mssages: BlindedMessages,
+        blinded_messages: BlindedMessages,
         hash: &str,
     ) -> Result<PostMintResponse, Error> {
-        RUNTIME.block_on(async { self.client.mint(blinded_mssages, hash).await })
+        RUNTIME.block_on(async { self.client.mint(blinded_messages, hash).await })
     }
 
     pub fn check_fees(&self, invoice: Bolt11Invoice) -> Result<CheckFeesResponse, Error> {

+ 1 - 1
crates/cashu/src/nuts/nut01.rs

@@ -88,7 +88,7 @@ impl Keys {
         self.0.get(&amount.to_sat()).cloned()
     }
 
-    /// As seralized hashmap
+    /// As serialized hashmap
     pub fn as_hashmap(&self) -> HashMap<u64, String> {
         self.0
             .iter()