refactor: add mint quote in sdk

This commit is contained in:
thesimplekid
2023-12-25 21:27:55 +00:00
parent 775117cf78
commit f835ca665d
5 changed files with 138 additions and 21 deletions

View File

@@ -7,6 +7,7 @@ use cashu::nuts::{
};
#[cfg(feature = "nut07")]
use cashu::nuts::{CheckSpendableRequest, CheckSpendableResponse};
use cashu::Amount;
use gloo::net::http::Request;
use serde_json::Value;
use url::Url;
@@ -54,6 +55,35 @@ impl Client for HttpClient {
}
}
/// Mint Quote [NUT-04]
async fn post_mint_quote(
&self,
mint_url: Url,
amount: Amount,
unit: CurrencyUnit,
) -> Result<MintQuoteBolt11Response, Error> {
let url = join_url(mint_url, &["v1", "quote", "bolt11"])?;
let request = MintQuoteBolt11Request { amount, unit };
let res = Request::post(url.as_str())
.json(&request)
.map_err(|err| Error::Gloo(err.to_string()))?
.send()
.await
.map_err(|err| Error::Gloo(err.to_string()))?
.json::<Value>()
.await
.map_err(|err| Error::Gloo(err.to_string()))?;
let response: Result<MintQuoteBolt11Response, serde_json::Error> =
serde_json::from_value(res.clone());
match response {
Ok(res) => Ok(res),
Err(_) => Err(Error::from_json(&res.to_string())?),
}
}
/// Mint Tokens [NUT-04]
async fn post_mint(
&self,
@@ -61,7 +91,7 @@ impl Client for HttpClient {
quote: &str,
premint_secrets: PreMintSecrets,
) -> Result<MintBolt11Response, Error> {
let url = join_url(mint_url, &["mint"])?;
let url = join_url(mint_url, &["v1", "mint"])?;
let request = MintBolt11Request {
quote: quote.to_string(),

View File

@@ -9,7 +9,9 @@ use cashu::nuts::{
};
#[cfg(feature = "nut07")]
use cashu::nuts::{CheckSpendableRequest, CheckSpendableResponse};
use cashu::Amount;
use serde_json::Value;
use tracing::warn;
use url::Url;
use super::join_url;
@@ -43,6 +45,34 @@ impl Client for HttpClient {
}
}
/// Mint Quote [NUT-04]
async fn post_mint_quote(
&self,
mint_url: Url,
amount: Amount,
unit: CurrencyUnit,
) -> Result<MintQuoteBolt11Response, Error> {
let url = join_url(mint_url, &["v1", "quote", "bolt11"])?;
let request = MintQuoteBolt11Request { amount, unit };
let res = minreq::post(url)
.with_json(&request)?
.send()?
.json::<Value>()?;
let response: Result<MintQuoteBolt11Response, serde_json::Error> =
serde_json::from_value(res.clone());
match response {
Ok(res) => Ok(res),
Err(_) => {
warn!("Bolt11 Mint Quote Unexpected response: {}", res);
Err(Error::from_json(&res.to_string())?)
}
}
}
/// Mint Tokens [NUT-04]
async fn post_mint(
&self,

View File

@@ -6,10 +6,10 @@ use cashu::nuts::nut00;
#[cfg(feature = "nut07")]
use cashu::nuts::CheckSpendableResponse;
use cashu::nuts::{
BlindedMessage, Keys, KeysetResponse, MeltBolt11Response, MintBolt11Response, MintInfo,
PreMintSecrets, Proof, SwapRequest, SwapResponse,
BlindedMessage, CurrencyUnit, Keys, KeysetResponse, MeltBolt11Response, MintBolt11Response,
MintInfo, MintQuoteBolt11Response, PreMintSecrets, Proof, SwapRequest, SwapResponse,
};
use cashu::utils;
use cashu::{utils, Amount};
use serde::{Deserialize, Serialize};
use thiserror::Error;
use url::Url;
@@ -87,7 +87,13 @@ pub trait Client {
async fn get_mint_keysets(&self, mint_url: Url) -> Result<KeysetResponse, Error>;
// TODO: Hash should have a type
async fn post_mint_quote(
&self,
mint_url: Url,
amount: Amount,
unit: CurrencyUnit,
) -> Result<MintQuoteBolt11Response, Error>;
async fn post_mint(
&self,
mint_url: Url,

View File

@@ -1,4 +1,5 @@
//! Cashu Wallet
use std::collections::HashMap;
use std::str::FromStr;
use cashu::dhke::{construct_proofs, unblind_message};
@@ -10,7 +11,7 @@ use cashu::nuts::{
};
#[cfg(feature = "nut07")]
use cashu::types::ProofsStatus;
use cashu::types::{Melted, SendProofs};
use cashu::types::{Melted, MintQuoteInfo, SendProofs};
use cashu::url::UncheckedUrl;
use cashu::Amount;
pub use cashu::Bolt11Invoice;
@@ -39,16 +40,23 @@ pub enum Error {
pub struct Wallet<C: Client> {
pub client: C,
pub mint_url: UncheckedUrl,
pub quotes: HashMap<String, MintQuoteInfo>,
pub mint_keys: Keys,
pub balance: Amount,
}
impl<C: Client> Wallet<C> {
pub fn new(client: C, mint_url: UncheckedUrl, mint_keys: Keys) -> Self {
pub fn new(
client: C,
mint_url: UncheckedUrl,
quotes: Vec<MintQuoteInfo>,
mint_keys: Keys,
) -> Self {
Self {
client,
mint_url,
mint_keys,
quotes: quotes.into_iter().map(|q| (q.id.clone(), q)).collect(),
balance: Amount::ZERO,
}
}
@@ -80,25 +88,56 @@ impl<C: Client> Wallet<C> {
spent: spent.into_iter().map(|(s, _)| s).cloned().collect(),
})
}
/*
// TODO: Need to use the unit, check keyset is of the same unit of attempting to
// mint
pub async fn mint_token(
&self,
amount: Amount,
quote: &str,
memo: Option<String>,
unit: Option<CurrencyUnit>,
) -> Result<Token, Error> {
let proofs = self.mint(amount, unit.clone().unwrap()).await?;
// TODO: Need to use the unit, check keyset is of the same unit of attempting to
// mint
pub async fn mint_token(
&self,
let token = Token::new(self.mint_url.clone(), proofs, memo, unit);
Ok(token?)
}
*/
pub async fn mint_quote(
&mut self,
amount: Amount,
quote: &str,
memo: Option<String>,
unit: Option<CurrencyUnit>,
) -> Result<Token, Error> {
let proofs = self.mint(amount, quote).await?;
unit: CurrencyUnit,
) -> Result<MintQuoteInfo, Error> {
let quote_res = self
.client
.post_mint_quote(self.mint_url.clone().try_into()?, amount, unit.clone())
.await?;
let token = Token::new(self.mint_url.clone(), proofs, memo, unit);
Ok(token?)
let quote = MintQuoteInfo {
id: quote_res.quote.clone(),
amount,
unit,
request: Some(Bolt11Invoice::from_str(&quote_res.request).unwrap()),
paid: quote_res.paid,
expiry: quote_res.expiry,
};
self.quotes.insert(quote_res.quote.clone(), quote.clone());
Ok(quote)
}
/// Mint Proofs
pub async fn mint(&self, amount: Amount, quote: &str) -> Result<Proofs, Error> {
let premint_secrets = PreMintSecrets::random((&self.mint_keys).into(), amount)?;
pub async fn mint(&self, quote: &str) -> Result<Proofs, Error> {
let quote_info = self
.quotes
.get(quote)
.ok_or(Error::Custom("Unknown quote".to_string()))?;
let premint_secrets = PreMintSecrets::random((&self.mint_keys).into(), quote_info.amount)?;
let mint_res = self
.client
@@ -271,6 +310,7 @@ impl<C: Client> Wallet<C> {
})
}
/// Melt
pub async fn melt(
&self,
quote: String,

View File

@@ -3,7 +3,7 @@
use serde::{Deserialize, Serialize};
use crate::nuts::{CurrencyUnit, Proofs};
use crate::Bolt11Invoice;
use crate::{Amount, Bolt11Invoice};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ProofsStatus {
@@ -34,6 +34,17 @@ pub enum InvoiceStatus {
InFlight,
}
/// Mint Quote Info
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct MintQuoteInfo {
pub id: String,
pub amount: Amount,
pub unit: CurrencyUnit,
pub request: Option<Bolt11Invoice>,
pub paid: bool,
pub expiry: u64,
}
/// Quote
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct Quote {