mirror of
https://github.com/aljazceru/cdk.git
synced 2026-02-18 19:45:45 +01:00
chore: wallet doc tests
This commit is contained in:
@@ -190,7 +190,7 @@ pub enum SplitTarget {
|
||||
None,
|
||||
/// Target amount for wallet to have most proofs that add up to value
|
||||
Value(Amount),
|
||||
/// Specific amounts to split into **must** equal amount being split
|
||||
/// Specific amounts to split into **MUST** equal amount being split
|
||||
Values(Vec<Amount>),
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ impl MintUrl {
|
||||
Self(self.to_string().trim_end_matches('/').to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for MintUrl {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
@@ -57,6 +58,7 @@ impl<'de> Deserialize<'de> for MintUrl {
|
||||
MintUrl::from_str(&s).map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> From<S> for MintUrl
|
||||
where
|
||||
S: Into<String>,
|
||||
|
||||
22
crates/cdk/src/wallet/README.md
Normal file
22
crates/cdk/src/wallet/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# CDK Wallet
|
||||
|
||||
The CDK [`Wallet`] is a high level Cashu wallet. The [`Wallet`] is for a single mint and single unit. Multiple [`Wallet`]s can be created to support multi mints and multi units.
|
||||
|
||||
|
||||
## Example
|
||||
|
||||
### Create [`Wallet`]
|
||||
```rust
|
||||
use std::sync::Arc;
|
||||
use cdk::cdk_database::WalletMemoryDatabase;
|
||||
use cdk::nuts::CurrencyUnit;
|
||||
use cdk::wallet::Wallet;
|
||||
use rand::Rng;
|
||||
|
||||
let seed = rand::thread_rng().gen::<[u8; 32]>();
|
||||
let mint_url = "https://testnut.cashu.space";
|
||||
let unit = CurrencyUnit::Sat;
|
||||
|
||||
let localstore = WalletMemoryDatabase::default();
|
||||
let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None);
|
||||
```
|
||||
@@ -1,6 +1,4 @@
|
||||
//! Cashu Wallet
|
||||
//!
|
||||
//! Each wallet is single mint and single unit
|
||||
#![doc = include_str!("./README.md")]
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::str::FromStr;
|
||||
@@ -39,6 +37,10 @@ pub use multi_mint_wallet::MultiMintWallet;
|
||||
pub use types::{MeltQuote, MintQuote, SendKind};
|
||||
|
||||
/// CDK Wallet
|
||||
///
|
||||
/// The CDK [`Wallet`] is a high level cashu wallet.
|
||||
///
|
||||
/// A [`Wallet`] is for a single mint and single unit.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Wallet {
|
||||
/// Mint Url
|
||||
@@ -55,6 +57,22 @@ pub struct Wallet {
|
||||
|
||||
impl Wallet {
|
||||
/// Create new [`Wallet`]
|
||||
/// # Synopsis
|
||||
/// ```rust
|
||||
/// # use std::sync::Arc;
|
||||
///
|
||||
/// # use cdk::cdk_database::WalletMemoryDatabase;
|
||||
/// # use cdk::nuts::CurrencyUnit;
|
||||
/// # use cdk::wallet::Wallet;
|
||||
/// # use rand::Rng;
|
||||
///
|
||||
/// let seed = rand::thread_rng().gen::<[u8; 32]>();
|
||||
/// let mint_url = "https://testnut.cashu.space";
|
||||
/// let unit = CurrencyUnit::Sat;
|
||||
///
|
||||
/// let localstore = WalletMemoryDatabase::default();
|
||||
/// let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None);
|
||||
/// ```
|
||||
pub fn new(
|
||||
mint_url: &str,
|
||||
unit: CurrencyUnit,
|
||||
@@ -248,7 +266,7 @@ impl Wallet {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Add mint to wallet
|
||||
/// Qeury mint for current mint information
|
||||
#[instrument(skip(self))]
|
||||
pub async fn get_mint_info(&self) -> Result<Option<MintInfo>, Error> {
|
||||
let mint_info = match self
|
||||
@@ -267,12 +285,15 @@ impl Wallet {
|
||||
.add_mint(self.mint_url.clone(), mint_info.clone())
|
||||
.await?;
|
||||
|
||||
tracing::trace!("Mint info fetched for {}", self.mint_url);
|
||||
tracing::trace!("Mint info updated for {}", self.mint_url);
|
||||
|
||||
Ok(mint_info)
|
||||
}
|
||||
|
||||
/// Get keys for mint keyset
|
||||
///
|
||||
/// Selected keys from localstore if they are already known
|
||||
/// If they are not known queries mint for keyset id and stores the [`Keys`]
|
||||
#[instrument(skip(self))]
|
||||
pub async fn get_keyset_keys(&self, keyset_id: Id) -> Result<Keys, Error> {
|
||||
let keys = if let Some(keys) = self.localstore.get_keys(&keyset_id).await? {
|
||||
@@ -292,6 +313,8 @@ impl Wallet {
|
||||
}
|
||||
|
||||
/// Get keysets for mint
|
||||
///
|
||||
/// Queries mint for all keysets
|
||||
#[instrument(skip(self))]
|
||||
pub async fn get_mint_keysets(&self) -> Result<Vec<KeySetInfo>, Error> {
|
||||
let keysets = self
|
||||
@@ -307,7 +330,8 @@ impl Wallet {
|
||||
}
|
||||
|
||||
/// Get active keyset for mint
|
||||
/// Quieries mint for current keysets then gets Keys for any unknown keysets
|
||||
///
|
||||
/// Quieries mint for current keysets then gets [`Keys`] for any unknown keysets
|
||||
#[instrument(skip(self))]
|
||||
pub async fn get_active_mint_keyset(&self) -> Result<KeySetInfo, Error> {
|
||||
let keysets = self
|
||||
@@ -352,6 +376,8 @@ impl Wallet {
|
||||
}
|
||||
|
||||
/// Reclaim unspent proofs
|
||||
///
|
||||
/// Checks the stats of [`Proofs`] swapping for a new [`Proof`] if unspent
|
||||
#[instrument(skip(self, proofs))]
|
||||
pub async fn reclaim_unspent(&self, proofs: Proofs) -> Result<(), Error> {
|
||||
let proof_ys = proofs
|
||||
@@ -378,7 +404,7 @@ impl Wallet {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Check if a proof is spent
|
||||
/// NUT-07 Check the state of a [`Proof`] with the mint
|
||||
#[instrument(skip(self, proofs))]
|
||||
pub async fn check_proofs_spent(&self, proofs: Proofs) -> Result<Vec<ProofState>, Error> {
|
||||
let spendable = self
|
||||
@@ -444,6 +470,30 @@ impl Wallet {
|
||||
}
|
||||
|
||||
/// Mint Quote
|
||||
/// # Synopsis
|
||||
/// ```rust
|
||||
/// # use std::sync::Arc;
|
||||
///
|
||||
/// # use cdk::amount::Amount;
|
||||
/// # use cdk::cdk_database::WalletMemoryDatabase;
|
||||
/// # use cdk::nuts::CurrencyUnit;
|
||||
/// # use cdk::wallet::Wallet;
|
||||
/// # use rand::Rng;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> anyhow::Result<()> {
|
||||
/// # let seed = rand::thread_rng().gen::<[u8; 32]>();
|
||||
/// # let mint_url = "https://testnut.cashu.space";
|
||||
/// # let unit = CurrencyUnit::Sat;
|
||||
///
|
||||
/// # let localstore = WalletMemoryDatabase::default();
|
||||
/// let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None);
|
||||
/// let amount = Amount::from(100);
|
||||
///
|
||||
/// let quote = wallet.mint_quote(amount).await?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[instrument(skip(self))]
|
||||
pub async fn mint_quote(&self, amount: Amount) -> Result<MintQuote, Error> {
|
||||
let mint_url = self.mint_url.clone();
|
||||
@@ -468,7 +518,7 @@ impl Wallet {
|
||||
Ok(quote)
|
||||
}
|
||||
|
||||
/// Mint quote status
|
||||
/// Check mint quote status
|
||||
#[instrument(skip(self, quote_id))]
|
||||
pub async fn mint_quote_state(&self, quote_id: &str) -> Result<MintQuoteBolt11Response, Error> {
|
||||
let response = self
|
||||
@@ -513,6 +563,35 @@ impl Wallet {
|
||||
}
|
||||
|
||||
/// Mint
|
||||
/// # Synopsis
|
||||
/// ```rust
|
||||
/// # use std::sync::Arc;
|
||||
///
|
||||
/// # use anyhow::Result;
|
||||
/// # use cdk::amount::{Amount, SplitTarget};
|
||||
/// # use cdk::cdk_database::WalletMemoryDatabase;
|
||||
/// # use cdk::nuts::CurrencyUnit;
|
||||
/// # use cdk::wallet::Wallet;
|
||||
/// # use rand::Rng;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> Result<()> {
|
||||
/// # let seed = rand::thread_rng().gen::<[u8; 32]>();
|
||||
/// # let mint_url = "https://testnut.cashu.space";
|
||||
/// # let unit = CurrencyUnit::Sat;
|
||||
///
|
||||
/// # let localstore = WalletMemoryDatabase::default();
|
||||
/// let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None);
|
||||
/// let amount = Amount::from(100);
|
||||
///
|
||||
/// let quote = wallet.mint_quote(amount).await?;
|
||||
/// let quote_id = quote.id;
|
||||
/// // To be called after quote request is paid
|
||||
/// let amount_minted = wallet.mint("e_id, SplitTarget::default(), None).await?;
|
||||
///
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[instrument(skip(self))]
|
||||
pub async fn mint(
|
||||
&self,
|
||||
@@ -1173,6 +1252,29 @@ impl Wallet {
|
||||
}
|
||||
|
||||
/// Melt Quote
|
||||
/// # Synopsis
|
||||
/// ```rust
|
||||
/// # use std::sync::Arc;
|
||||
///
|
||||
/// # use cdk::cdk_database::WalletMemoryDatabase;
|
||||
/// # use cdk::nuts::CurrencyUnit;
|
||||
/// # use cdk::wallet::Wallet;
|
||||
/// # use rand::Rng;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> anyhow::Result<()> {
|
||||
/// # let seed = rand::thread_rng().gen::<[u8; 32]>();
|
||||
/// # let mint_url = "https://testnut.cashu.space";
|
||||
/// # let unit = CurrencyUnit::Sat;
|
||||
///
|
||||
/// # let localstore = WalletMemoryDatabase::default();
|
||||
/// let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None);
|
||||
/// let bolt11 = "lnbc100n1pnvpufspp5djn8hrq49r8cghwye9kqw752qjncwyfnrprhprpqk43mwcy4yfsqdq5g9kxy7fqd9h8vmmfvdjscqzzsxqyz5vqsp5uhpjt36rj75pl7jq2sshaukzfkt7uulj456s4mh7uy7l6vx7lvxs9qxpqysgqedwz08acmqwtk8g4vkwm2w78suwt2qyzz6jkkwcgrjm3r3hs6fskyhvud4fan3keru7emjm8ygqpcrwtlmhfjfmer3afs5hhwamgr4cqtactdq".to_string();
|
||||
/// let quote = wallet.melt_quote(bolt11, None).await?;
|
||||
///
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[instrument(skip(self))]
|
||||
pub async fn melt_quote(
|
||||
&self,
|
||||
@@ -1361,6 +1463,31 @@ impl Wallet {
|
||||
}
|
||||
|
||||
/// Melt
|
||||
/// # Synopsis
|
||||
/// ```rust, no_run
|
||||
/// # use std::sync::Arc;
|
||||
///
|
||||
/// # use cdk::cdk_database::WalletMemoryDatabase;
|
||||
/// # use cdk::nuts::CurrencyUnit;
|
||||
/// # use cdk::wallet::Wallet;
|
||||
/// # use rand::Rng;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> anyhow::Result<()> {
|
||||
/// # let seed = rand::thread_rng().gen::<[u8; 32]>();
|
||||
/// # let mint_url = "https://testnut.cashu.space";
|
||||
/// # let unit = CurrencyUnit::Sat;
|
||||
///
|
||||
/// # let localstore = WalletMemoryDatabase::default();
|
||||
/// # let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None);
|
||||
/// # let bolt11 = "lnbc100n1pnvpufspp5djn8hrq49r8cghwye9kqw752qjncwyfnrprhprpqk43mwcy4yfsqdq5g9kxy7fqd9h8vmmfvdjscqzzsxqyz5vqsp5uhpjt36rj75pl7jq2sshaukzfkt7uulj456s4mh7uy7l6vx7lvxs9qxpqysgqedwz08acmqwtk8g4vkwm2w78suwt2qyzz6jkkwcgrjm3r3hs6fskyhvud4fan3keru7emjm8ygqpcrwtlmhfjfmer3afs5hhwamgr4cqtactdq".to_string();
|
||||
/// let quote = wallet.melt_quote(bolt11, None).await?;
|
||||
/// let quote_id = quote.id;
|
||||
///
|
||||
/// let _ = wallet.melt("e_id).await?;
|
||||
///
|
||||
/// Ok(())
|
||||
/// }
|
||||
#[instrument(skip(self))]
|
||||
pub async fn melt(&self, quote_id: &str) -> Result<Melted, Error> {
|
||||
let quote_info = self.localstore.get_melt_quote(quote_id).await?;
|
||||
@@ -1635,6 +1762,29 @@ impl Wallet {
|
||||
}
|
||||
|
||||
/// Receive
|
||||
/// # Synopsis
|
||||
/// ```rust, no_run
|
||||
/// # use std::sync::Arc;
|
||||
///
|
||||
/// # use cdk::amount::SplitTarget;
|
||||
/// # use cdk::cdk_database::WalletMemoryDatabase;
|
||||
/// # use cdk::nuts::CurrencyUnit;
|
||||
/// # use cdk::wallet::Wallet;
|
||||
/// # use rand::Rng;
|
||||
///
|
||||
/// #[tokio::main]
|
||||
/// async fn main() -> anyhow::Result<()> {
|
||||
/// # let seed = rand::thread_rng().gen::<[u8; 32]>();
|
||||
/// # let mint_url = "https://testnut.cashu.space";
|
||||
/// # let unit = CurrencyUnit::Sat;
|
||||
///
|
||||
/// # let localstore = WalletMemoryDatabase::default();
|
||||
/// let wallet = Wallet::new(mint_url, unit, Arc::new(localstore), &seed, None);
|
||||
/// let token = "cashuAeyJ0b2tlbiI6W3sicHJvb2ZzIjpbeyJhbW91bnQiOjEsInNlY3JldCI6ImI0ZjVlNDAxMDJhMzhiYjg3NDNiOTkwMzU5MTU1MGYyZGEzZTQxNWEzMzU0OTUyN2M2MmM5ZDc5MGVmYjM3MDUiLCJDIjoiMDIzYmU1M2U4YzYwNTMwZWVhOWIzOTQzZmRhMWEyY2U3MWM3YjNmMGNmMGRjNmQ4NDZmYTc2NWFhZjc3OWZhODFkIiwiaWQiOiIwMDlhMWYyOTMyNTNlNDFlIn1dLCJtaW50IjoiaHR0cHM6Ly90ZXN0bnV0LmNhc2h1LnNwYWNlIn1dLCJ1bml0Ijoic2F0In0=";
|
||||
/// let amount_receive = wallet.receive(token, SplitTarget::default(), &[], &[]).await?;
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[instrument(skip_all)]
|
||||
pub async fn receive(
|
||||
&self,
|
||||
|
||||
Reference in New Issue
Block a user