mirror of
https://github.com/aljazceru/cdk.git
synced 2025-12-22 07:04:56 +01:00
sdk: add blocking client and wallet as feature
This commit is contained in:
4
.helix/languages.toml
Normal file
4
.helix/languages.toml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
[[language]]
|
||||||
|
name = "rust"
|
||||||
|
config = { cargo = { features = [ "blocking", "wallet" ] } }
|
||||||
|
|
||||||
@@ -23,5 +23,6 @@ keywords = ["bitcoin", "e-cash", "cashu"]
|
|||||||
serde = { version = "1.0.160", features = ["derive"]}
|
serde = { version = "1.0.160", features = ["derive"]}
|
||||||
serde_json = "1.0.96"
|
serde_json = "1.0.96"
|
||||||
url = "2.3.1"
|
url = "2.3.1"
|
||||||
|
tokio = { version = "1", default-features = false }
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-subscriber = "0.3"
|
tracing-subscriber = "0.3"
|
||||||
@@ -10,9 +10,17 @@ license.workspace = true
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["mint", "wallet"]
|
default = ["mint", "wallet"]
|
||||||
mint = []
|
mint = ["cashu/mint"]
|
||||||
|
blocking = ["once_cell"]
|
||||||
|
wallet = ["cashu/wallet", "minreq", "once_cell"]
|
||||||
|
|
||||||
|
|
||||||
# Fix: Should be minreq or gloo
|
# Fix: Should be minreq or gloo
|
||||||
wallet = ["minreq"]
|
# [target.'cfg(not(target_arch = "wasm32"))'.features]
|
||||||
|
# wallet = ["cashu/wallet", "minreq", "once_cell"]
|
||||||
|
|
||||||
|
# [target.'cfg(target_arch = "wasm32")'.features]
|
||||||
|
# wallet = ["cashu/wallet", "gloo", "once_cell"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cashu = { path = "../cashu" }
|
cashu = { path = "../cashu" }
|
||||||
@@ -20,9 +28,16 @@ serde = { workspace = true }
|
|||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
url = { workspace = true }
|
url = { workspace = true }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
|
futures-util = { version = "0.3", default-features = false, features = ["sink", "std"] }
|
||||||
|
once_cell = { version = "1.17", optional = true }
|
||||||
|
|
||||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
|
||||||
gloo = { version = "0.9.0", features = ["net"]}
|
|
||||||
|
|
||||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
|
tokio = { workspace = true, features = ["rt-multi-thread", "time", "macros", "sync"] }
|
||||||
minreq = { version = "2.7.0", optional = true, features = ["json-using-serde", "https"] }
|
minreq = { version = "2.7.0", optional = true, features = ["json-using-serde", "https"] }
|
||||||
|
|
||||||
|
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||||
|
tokio = { workspace = true, features = ["rt", "macros", "sync"] }
|
||||||
|
gloo = { version = "0.9.0", features = ["net"]}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
80
crates/cashu-sdk/src/client/blocking.rs
Normal file
80
crates/cashu-sdk/src/client/blocking.rs
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
use crate::RUNTIME;
|
||||||
|
|
||||||
|
use cashu::{
|
||||||
|
nuts::{
|
||||||
|
nut00::{self, wallet::BlindedMessages, BlindedMessage, Proof},
|
||||||
|
nut01::Keys,
|
||||||
|
nut02,
|
||||||
|
nut03::RequestMintResponse,
|
||||||
|
nut04::PostMintResponse,
|
||||||
|
nut05::CheckFeesResponse,
|
||||||
|
nut06::{SplitRequest, SplitResponse},
|
||||||
|
nut07::CheckSpendableResponse,
|
||||||
|
nut08::MeltResponse,
|
||||||
|
nut09::MintInfo,
|
||||||
|
},
|
||||||
|
Amount, Bolt11Invoice,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::Error;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Client {
|
||||||
|
pub(crate) client: super::Client,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Client {
|
||||||
|
pub fn new(mint_url: &str) -> Result<Self, Error> {
|
||||||
|
Ok(Self {
|
||||||
|
client: super::Client::new(mint_url)?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_keys(&self) -> Result<Keys, Error> {
|
||||||
|
RUNTIME.block_on(async { self.client.get_keys().await })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_keysets(&self) -> Result<nut02::Response, Error> {
|
||||||
|
RUNTIME.block_on(async { self.client.get_keysets().await })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn request_mint(&self, amount: Amount) -> Result<RequestMintResponse, Error> {
|
||||||
|
RUNTIME.block_on(async { self.client.request_mint(amount).await })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mint(
|
||||||
|
&self,
|
||||||
|
blinded_mssages: BlindedMessages,
|
||||||
|
hash: &str,
|
||||||
|
) -> Result<PostMintResponse, Error> {
|
||||||
|
RUNTIME.block_on(async { self.client.mint(blinded_mssages, hash).await })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_fees(&self, invoice: Bolt11Invoice) -> Result<CheckFeesResponse, Error> {
|
||||||
|
RUNTIME.block_on(async { self.client.check_fees(invoice).await })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn melt(
|
||||||
|
&self,
|
||||||
|
proofs: Vec<Proof>,
|
||||||
|
invoice: Bolt11Invoice,
|
||||||
|
outputs: Option<Vec<BlindedMessage>>,
|
||||||
|
) -> Result<MeltResponse, Error> {
|
||||||
|
RUNTIME.block_on(async { self.client.melt(proofs, invoice, outputs).await })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn split(&self, split_request: SplitRequest) -> Result<SplitResponse, Error> {
|
||||||
|
RUNTIME.block_on(async { self.client.split(split_request).await })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn check_spendable(
|
||||||
|
&self,
|
||||||
|
proofs: &Vec<nut00::mint::Proof>,
|
||||||
|
) -> Result<CheckSpendableResponse, Error> {
|
||||||
|
RUNTIME.block_on(async { self.client.check_spendable(proofs).await })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_info(&self) -> Result<MintInfo, Error> {
|
||||||
|
RUNTIME.block_on(async { self.client.get_info().await })
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,9 @@ use cashu::Amount;
|
|||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
use gloo::net::http::Request;
|
use gloo::net::http::Request;
|
||||||
|
|
||||||
|
#[cfg(feature = "blocking")]
|
||||||
|
pub mod blocking;
|
||||||
|
|
||||||
pub use cashu::Bolt11Invoice;
|
pub use cashu::Bolt11Invoice;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|||||||
@@ -1,7 +1,28 @@
|
|||||||
#[cfg(feature = "wallet")]
|
#[cfg(feature = "blocking")]
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
|
#[cfg(feature = "blocking")]
|
||||||
|
use tokio::runtime::Runtime;
|
||||||
|
|
||||||
|
#[cfg(feature = "blocking")]
|
||||||
|
use futures_util::Future;
|
||||||
|
|
||||||
|
// #[cfg(feature = "wallet")]
|
||||||
pub(crate) mod client;
|
pub(crate) mod client;
|
||||||
|
|
||||||
#[cfg(feature = "mint")]
|
#[cfg(feature = "mint")]
|
||||||
pub mod mint;
|
pub mod mint;
|
||||||
#[cfg(feature = "wallet")]
|
#[cfg(feature = "wallet")]
|
||||||
pub mod wallet;
|
pub mod wallet;
|
||||||
|
|
||||||
|
pub use cashu::{self, *};
|
||||||
|
|
||||||
|
#[cfg(all(feature = "blocking", feature = "wallet"))]
|
||||||
|
use self::client::blocking;
|
||||||
|
|
||||||
|
#[cfg(feature = "blocking")]
|
||||||
|
static RUNTIME: Lazy<Runtime> = Lazy::new(|| Runtime::new().expect("Can't start Tokio runtime"));
|
||||||
|
|
||||||
|
#[cfg(feature = "blocking")]
|
||||||
|
pub fn block_on<F: Future>(future: F) -> F::Output {
|
||||||
|
RUNTIME.block_on(future)
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ use cashu::Amount;
|
|||||||
pub use cashu::Bolt11Invoice;
|
pub use cashu::Bolt11Invoice;
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
|
||||||
|
#[cfg(feature = "blocking")]
|
||||||
|
use crate::client::blocking::Client;
|
||||||
|
|
||||||
|
#[cfg(not(feature = "blocking"))]
|
||||||
use crate::client::Client;
|
use crate::client::Client;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -71,6 +75,7 @@ impl Wallet {
|
|||||||
// TODO: getter method for keys that if it cant get them try again
|
// TODO: getter method for keys that if it cant get them try again
|
||||||
|
|
||||||
/// Check if a proof is spent
|
/// Check if a proof is spent
|
||||||
|
#[cfg(not(feature = "blocking"))]
|
||||||
pub async fn check_proofs_spent(&self, proofs: &mint::Proofs) -> Result<ProofsStatus, Error> {
|
pub async fn check_proofs_spent(&self, proofs: &mint::Proofs) -> Result<ProofsStatus, Error> {
|
||||||
let spendable = self.client.check_spendable(proofs).await?;
|
let spendable = self.client.check_spendable(proofs).await?;
|
||||||
|
|
||||||
@@ -86,12 +91,37 @@ impl Wallet {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check if a proof is spent
|
||||||
|
#[cfg(feature = "blocking")]
|
||||||
|
pub fn check_proofs_spent(&self, proofs: &mint::Proofs) -> Result<ProofsStatus, Error> {
|
||||||
|
let spendable = self.client.check_spendable(proofs)?;
|
||||||
|
|
||||||
|
// Separate proofs in spent and unspent based on mint response
|
||||||
|
let (spendable, spent): (Vec<_>, Vec<_>) = proofs
|
||||||
|
.iter()
|
||||||
|
.zip(spendable.spendable.iter())
|
||||||
|
.partition(|(_, &b)| b);
|
||||||
|
|
||||||
|
Ok(ProofsStatus {
|
||||||
|
spendable: spendable.into_iter().map(|(s, _)| s).cloned().collect(),
|
||||||
|
spent: spent.into_iter().map(|(s, _)| s).cloned().collect(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/// Request Token Mint
|
/// Request Token Mint
|
||||||
|
#[cfg(not(feature = "blocking"))]
|
||||||
pub async fn request_mint(&self, amount: Amount) -> Result<RequestMintResponse, Error> {
|
pub async fn request_mint(&self, amount: Amount) -> Result<RequestMintResponse, Error> {
|
||||||
Ok(self.client.request_mint(amount).await?)
|
Ok(self.client.request_mint(amount).await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Request Token Mint
|
||||||
|
#[cfg(feature = "blocking")]
|
||||||
|
pub fn request_mint(&self, amount: Amount) -> Result<RequestMintResponse, Error> {
|
||||||
|
Ok(self.client.request_mint(amount)?)
|
||||||
|
}
|
||||||
|
|
||||||
/// Mint Token
|
/// Mint Token
|
||||||
|
#[cfg(not(feature = "blocking"))]
|
||||||
pub async fn mint_token(&self, amount: Amount, hash: &str) -> Result<Token, Error> {
|
pub async fn mint_token(&self, amount: Amount, hash: &str) -> Result<Token, Error> {
|
||||||
let proofs = self.mint(amount, hash).await?;
|
let proofs = self.mint(amount, hash).await?;
|
||||||
|
|
||||||
@@ -99,7 +129,17 @@ impl Wallet {
|
|||||||
Ok(token)
|
Ok(token)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Blocking Mint Token
|
||||||
|
#[cfg(feature = "blocking")]
|
||||||
|
pub fn mint_token(&self, amount: Amount, hash: &str) -> Result<Token, Error> {
|
||||||
|
let proofs = self.mint(amount, hash)?;
|
||||||
|
|
||||||
|
let token = Token::new(self.client.client.mint_url.clone(), proofs, None);
|
||||||
|
Ok(token)
|
||||||
|
}
|
||||||
|
|
||||||
/// Mint Proofs
|
/// Mint Proofs
|
||||||
|
#[cfg(not(feature = "blocking"))]
|
||||||
pub async fn mint(&self, amount: Amount, hash: &str) -> Result<Proofs, Error> {
|
pub async fn mint(&self, amount: Amount, hash: &str) -> Result<Proofs, Error> {
|
||||||
let blinded_messages = BlindedMessages::random(amount)?;
|
let blinded_messages = BlindedMessages::random(amount)?;
|
||||||
|
|
||||||
@@ -115,12 +155,37 @@ impl Wallet {
|
|||||||
Ok(proofs)
|
Ok(proofs)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Blocking Mint Proofs
|
||||||
|
#[cfg(feature = "blocking")]
|
||||||
|
pub fn mint(&self, amount: Amount, hash: &str) -> Result<Proofs, Error> {
|
||||||
|
let blinded_messages = BlindedMessages::random(amount)?;
|
||||||
|
|
||||||
|
let mint_res = self.client.mint(blinded_messages.clone(), hash)?;
|
||||||
|
|
||||||
|
let proofs = construct_proofs(
|
||||||
|
mint_res.promises,
|
||||||
|
blinded_messages.rs,
|
||||||
|
blinded_messages.secrets,
|
||||||
|
&self.mint_keys,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(proofs)
|
||||||
|
}
|
||||||
|
|
||||||
/// Check fee
|
/// Check fee
|
||||||
|
#[cfg(not(feature = "blocking"))]
|
||||||
pub async fn check_fee(&self, invoice: Bolt11Invoice) -> Result<Amount, Error> {
|
pub async fn check_fee(&self, invoice: Bolt11Invoice) -> Result<Amount, Error> {
|
||||||
Ok(self.client.check_fees(invoice).await?.fee)
|
Ok(self.client.check_fees(invoice).await?.fee)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check fee
|
||||||
|
#[cfg(feature = "blocking")]
|
||||||
|
pub fn check_fee(&self, invoice: Bolt11Invoice) -> Result<Amount, Error> {
|
||||||
|
Ok(self.client.check_fees(invoice)?.fee)
|
||||||
|
}
|
||||||
|
|
||||||
/// Receive
|
/// Receive
|
||||||
|
#[cfg(not(feature = "blocking"))]
|
||||||
pub async fn receive(&self, encoded_token: &str) -> Result<Proofs, Error> {
|
pub async fn receive(&self, encoded_token: &str) -> Result<Proofs, Error> {
|
||||||
let token_data = Token::from_str(encoded_token)?;
|
let token_data = Token::from_str(encoded_token)?;
|
||||||
|
|
||||||
@@ -160,6 +225,51 @@ impl Wallet {
|
|||||||
Ok(proofs.iter().flatten().cloned().collect())
|
Ok(proofs.iter().flatten().cloned().collect())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Blocking Receive
|
||||||
|
#[cfg(feature = "blocking")]
|
||||||
|
pub fn receive(&self, encoded_token: &str) -> Result<Proofs, Error> {
|
||||||
|
let token_data = Token::from_str(encoded_token)?;
|
||||||
|
|
||||||
|
let mut proofs: Vec<Proofs> = vec![vec![]];
|
||||||
|
for token in token_data.token {
|
||||||
|
if token.proofs.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let keys = if token
|
||||||
|
.mint
|
||||||
|
.to_string()
|
||||||
|
.eq(&self.client.client.mint_url.to_string())
|
||||||
|
{
|
||||||
|
self.mint_keys.clone()
|
||||||
|
} else {
|
||||||
|
Client::new(token.mint.as_str())?.get_keys()?
|
||||||
|
};
|
||||||
|
|
||||||
|
// Sum amount of all proofs
|
||||||
|
let _amount: Amount = token.proofs.iter().map(|p| p.amount).sum();
|
||||||
|
|
||||||
|
let split_payload = self.create_split(token.proofs)?;
|
||||||
|
|
||||||
|
let split_response = self.client.split(split_payload.split_payload)?;
|
||||||
|
|
||||||
|
if let Some(promises) = &split_response.promises {
|
||||||
|
// Proof to keep
|
||||||
|
let p = construct_proofs(
|
||||||
|
promises.to_owned(),
|
||||||
|
split_payload.blinded_messages.rs,
|
||||||
|
split_payload.blinded_messages.secrets,
|
||||||
|
&keys,
|
||||||
|
)?;
|
||||||
|
proofs.push(p);
|
||||||
|
} else {
|
||||||
|
warn!("Response missing promises");
|
||||||
|
return Err(Error::Custom("Split response missing promises".to_string()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(proofs.iter().flatten().cloned().collect())
|
||||||
|
}
|
||||||
|
|
||||||
/// Create Split Payload
|
/// Create Split Payload
|
||||||
fn create_split(&self, proofs: Proofs) -> Result<SplitPayload, Error> {
|
fn create_split(&self, proofs: Proofs) -> Result<SplitPayload, Error> {
|
||||||
let value = proofs.iter().map(|p| p.amount).sum();
|
let value = proofs.iter().map(|p| p.amount).sum();
|
||||||
@@ -217,6 +327,7 @@ impl Wallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Send
|
/// Send
|
||||||
|
#[cfg(not(feature = "blocking"))]
|
||||||
pub async fn send(&self, amount: Amount, proofs: Proofs) -> Result<SendProofs, Error> {
|
pub async fn send(&self, amount: Amount, proofs: Proofs) -> Result<SendProofs, Error> {
|
||||||
let mut amount_available = Amount::ZERO;
|
let mut amount_available = Amount::ZERO;
|
||||||
let mut send_proofs = SendProofs::default();
|
let mut send_proofs = SendProofs::default();
|
||||||
@@ -277,6 +388,69 @@ impl Wallet {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Send
|
||||||
|
#[cfg(feature = "blocking")]
|
||||||
|
pub fn send(&self, amount: Amount, proofs: Proofs) -> Result<SendProofs, Error> {
|
||||||
|
let mut amount_available = Amount::ZERO;
|
||||||
|
let mut send_proofs = SendProofs::default();
|
||||||
|
|
||||||
|
for proof in proofs {
|
||||||
|
let proof_value = proof.amount;
|
||||||
|
if amount_available > amount {
|
||||||
|
send_proofs.change_proofs.push(proof);
|
||||||
|
} else {
|
||||||
|
send_proofs.send_proofs.push(proof);
|
||||||
|
}
|
||||||
|
amount_available += proof_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if amount_available.lt(&amount) {
|
||||||
|
println!("Not enough funds");
|
||||||
|
return Err(Error::InsufficantFunds);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If amount available is EQUAL to send amount no need to split
|
||||||
|
if amount_available.eq(&amount) {
|
||||||
|
return Ok(send_proofs);
|
||||||
|
}
|
||||||
|
|
||||||
|
let _amount_to_keep = amount_available - amount;
|
||||||
|
let amount_to_send = amount;
|
||||||
|
|
||||||
|
let split_payload = self.create_split(send_proofs.send_proofs)?;
|
||||||
|
|
||||||
|
let split_response = self.client.split(split_payload.split_payload)?;
|
||||||
|
|
||||||
|
// If only promises assemble proofs needed for amount
|
||||||
|
let keep_proofs;
|
||||||
|
let send_proofs;
|
||||||
|
|
||||||
|
if let Some(promises) = split_response.promises {
|
||||||
|
let proofs = construct_proofs(
|
||||||
|
promises,
|
||||||
|
split_payload.blinded_messages.rs,
|
||||||
|
split_payload.blinded_messages.secrets,
|
||||||
|
&self.mint_keys,
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let split = amount_to_send.split();
|
||||||
|
|
||||||
|
keep_proofs = proofs[0..split.len()].to_vec();
|
||||||
|
send_proofs = proofs[split.len()..].to_vec();
|
||||||
|
} else {
|
||||||
|
return Err(Error::Custom("Invalid split response".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// println!("Send Proofs: {:#?}", send_proofs);
|
||||||
|
// println!("Keep Proofs: {:#?}", keep_proofs);
|
||||||
|
|
||||||
|
Ok(SendProofs {
|
||||||
|
change_proofs: keep_proofs,
|
||||||
|
send_proofs,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "blocking"))]
|
||||||
pub async fn melt(
|
pub async fn melt(
|
||||||
&self,
|
&self,
|
||||||
invoice: Bolt11Invoice,
|
invoice: Bolt11Invoice,
|
||||||
@@ -308,11 +482,49 @@ impl Wallet {
|
|||||||
Ok(melted)
|
Ok(melted)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "blocking")]
|
||||||
|
pub fn melt(
|
||||||
|
&self,
|
||||||
|
invoice: Bolt11Invoice,
|
||||||
|
proofs: Proofs,
|
||||||
|
fee_reserve: Amount,
|
||||||
|
) -> Result<Melted, Error> {
|
||||||
|
let blinded = BlindedMessages::blank(fee_reserve)?;
|
||||||
|
let melt_response = self
|
||||||
|
.client
|
||||||
|
.melt(proofs, invoice, Some(blinded.blinded_messages))?;
|
||||||
|
|
||||||
|
let change_proofs = match melt_response.change {
|
||||||
|
Some(change) => Some(construct_proofs(
|
||||||
|
change,
|
||||||
|
blinded.rs,
|
||||||
|
blinded.secrets,
|
||||||
|
&self.mint_keys,
|
||||||
|
)?),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let melted = Melted {
|
||||||
|
paid: true,
|
||||||
|
preimage: melt_response.preimage,
|
||||||
|
change: change_proofs,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(melted)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "blocking"))]
|
||||||
pub fn proofs_to_token(&self, proofs: Proofs, memo: Option<String>) -> Result<String, Error> {
|
pub fn proofs_to_token(&self, proofs: Proofs, memo: Option<String>) -> Result<String, Error> {
|
||||||
Ok(Token::new(self.client.mint_url.clone(), proofs, memo).convert_to_string()?)
|
Ok(Token::new(self.client.mint_url.clone(), proofs, memo).convert_to_string()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "blocking")]
|
||||||
|
pub fn proofs_to_token(&self, proofs: Proofs, memo: Option<String>) -> Result<String, Error> {
|
||||||
|
Ok(Token::new(self.client.client.mint_url.clone(), proofs, memo).convert_to_string()?)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
@@ -379,3 +591,4 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|||||||
@@ -30,4 +30,4 @@ url = { workspace = true }
|
|||||||
regex = "1.8.4"
|
regex = "1.8.4"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tokio = {version = "1.27.0", features = ["rt", "macros"] }
|
# tokio = {version = "1.27.0", features = ["rt", "macros"] }
|
||||||
|
|||||||
Reference in New Issue
Block a user