From a9f0116836afd591358466c34cd2c8183c55e29b Mon Sep 17 00:00:00 2001 From: thesimplekid Date: Mon, 13 May 2024 21:43:46 +0100 Subject: [PATCH] feat(wallet): mint and melt quote status --- bindings/cdk-js/src/wallet.rs | 36 +++++++++++++++++++++ crates/cdk/src/client.rs | 42 +++++++++++++++++++++++++ crates/cdk/src/wallet.rs | 59 +++++++++++++++++++++++++++++++++-- 3 files changed, 134 insertions(+), 3 deletions(-) diff --git a/bindings/cdk-js/src/wallet.rs b/bindings/cdk-js/src/wallet.rs index 711b582a0..e0d73f165 100644 --- a/bindings/cdk-js/src/wallet.rs +++ b/bindings/cdk-js/src/wallet.rs @@ -10,6 +10,8 @@ use cdk_rexie::RexieWalletDatabase; use wasm_bindgen::prelude::*; use crate::error::{into_err, Result}; +use crate::nuts::nut04::JsMintQuoteBolt11Response; +use crate::nuts::nut05::JsMeltQuoteBolt11Response; use crate::nuts::nut11::JsP2PKSpendingConditions; use crate::nuts::nut14::JsHTLCSpendingConditions; use crate::nuts::{JsCurrencyUnit, JsMintInfo, JsProof}; @@ -95,6 +97,23 @@ impl JsWallet { Ok(quote.into()) } + #[wasm_bindgen(js_name = mintQuoteStatus)] + pub async fn mint_quote_status( + &self, + mint_url: String, + quote_id: String, + ) -> Result { + let mint_url = UncheckedUrl::from_str(&mint_url).map_err(into_err)?; + + let quote = self + .inner + .mint_quote_status(mint_url, "e_id) + .await + .map_err(into_err)?; + + Ok(quote.into()) + } + #[wasm_bindgen(js_name = mint)] pub async fn mint(&mut self, mint_url: String, quote_id: String) -> Result { let mint_url = UncheckedUrl::from_str(&mint_url).map_err(into_err)?; @@ -124,6 +143,23 @@ impl JsWallet { Ok(melt_quote.into()) } + #[wasm_bindgen(js_name = meltQuoteStatus)] + pub async fn melt_quote_status( + &self, + mint_url: String, + quote_id: String, + ) -> Result { + let mint_url = UncheckedUrl::from_str(&mint_url).map_err(into_err)?; + + let quote = self + .inner + .melt_quote_status(mint_url, "e_id) + .await + .map_err(into_err)?; + + Ok(quote.into()) + } + #[wasm_bindgen(js_name = melt)] pub async fn melt(&mut self, mint_url: String, quote_id: String) -> Result { let mint_url = UncheckedUrl::from_str(&mint_url).map_err(into_err)?; diff --git a/crates/cdk/src/client.rs b/crates/cdk/src/client.rs index d793aa318..d970e2f15 100644 --- a/crates/cdk/src/client.rs +++ b/crates/cdk/src/client.rs @@ -136,6 +136,27 @@ impl HttpClient { } } + /// Mint Quote status + pub async fn get_mint_quote_status( + &self, + mint_url: Url, + quote_id: &str, + ) -> Result { + let url = join_url(mint_url, &["v1", "mint", "quote", "bolt11", quote_id])?; + + let res = self.inner.get(url).send().await?; + + let status = res.status(); + + let response: Result = + serde_json::from_value(res.json().await?); + + match response { + Ok(res) => Ok(res), + Err(_) => Err(ErrorResponse::from_json(&status.to_string())?.into()), + } + } + /// Mint Tokens [NUT-04] pub async fn post_mint( &self, @@ -192,6 +213,27 @@ impl HttpClient { } } + /// Melt Quote Status + pub async fn get_melt_quote_status( + &self, + mint_url: Url, + quote_id: &str, + ) -> Result { + let url = join_url(mint_url, &["v1", "melt", "quote", "bolt11", quote_id])?; + + let res = self.inner.get(url).send().await?; + + let status = res.status(); + + let response: Result = + serde_json::from_value(res.json().await?); + + match response { + Ok(res) => Ok(res), + Err(_) => Err(ErrorResponse::from_json(&status.to_string())?.into()), + } + } + /// Melt [NUT-05] /// [Nut-08] Lightning fee return if outputs defined pub async fn post_melt( diff --git a/crates/cdk/src/wallet.rs b/crates/cdk/src/wallet.rs index 4d8dce40d..329749e7a 100644 --- a/crates/cdk/src/wallet.rs +++ b/crates/cdk/src/wallet.rs @@ -15,9 +15,10 @@ use crate::cdk_database::{self, WalletDatabase}; use crate::client::HttpClient; use crate::dhke::{construct_proofs, hash_to_curve}; use crate::nuts::{ - nut10, nut12, Conditions, CurrencyUnit, Id, KeySet, KeySetInfo, Keys, Kind, MintInfo, - PreMintSecrets, PreSwap, Proof, ProofState, Proofs, PublicKey, RestoreRequest, SigFlag, - SigningKey, SpendingConditions, State, SwapRequest, Token, VerifyingKey, + nut10, nut12, Conditions, CurrencyUnit, Id, KeySet, KeySetInfo, Keys, Kind, + MeltQuoteBolt11Response, MintInfo, MintQuoteBolt11Response, PreMintSecrets, PreSwap, Proof, + ProofState, Proofs, PublicKey, RestoreRequest, SigFlag, SigningKey, SpendingConditions, State, + SwapRequest, Token, VerifyingKey, }; use crate::types::{MeltQuote, Melted, MintQuote}; use crate::url::UncheckedUrl; @@ -321,6 +322,32 @@ impl Wallet { Ok(quote) } + /// Mint quote status + pub async fn mint_quote_status( + &self, + mint_url: UncheckedUrl, + quote_id: &str, + ) -> Result { + let response = self + .client + .get_mint_quote_status(mint_url.try_into()?, quote_id) + .await?; + + match self.localstore.get_mint_quote(quote_id).await? { + Some(quote) => { + let mut quote = quote; + + quote.paid = response.paid; + self.localstore.add_mint_quote(quote).await?; + } + None => { + tracing::info!("Quote mint {} unknown", quote_id); + } + } + + Ok(response) + } + async fn active_mint_keyset( &mut self, mint_url: &UncheckedUrl, @@ -786,6 +813,32 @@ impl Wallet { Ok(quote) } + /// Melt quote status + pub async fn melt_quote_status( + &self, + mint_url: UncheckedUrl, + quote_id: &str, + ) -> Result { + let response = self + .client + .get_melt_quote_status(mint_url.try_into()?, quote_id) + .await?; + + match self.localstore.get_melt_quote(quote_id).await? { + Some(quote) => { + let mut quote = quote; + + quote.paid = response.paid; + self.localstore.add_melt_quote(quote).await?; + } + None => { + tracing::info!("Quote melt {} unknown", quote_id); + } + } + + Ok(response) + } + // Select proofs pub async fn select_proofs( &self,