wallet.rs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. use std::ops::Deref;
  2. use std::str::FromStr;
  3. use std::sync::Arc;
  4. use cdk::nuts::SigningKey;
  5. use cdk::url::UncheckedUrl;
  6. use cdk::wallet::Wallet;
  7. use cdk::{Amount, HttpClient};
  8. use cdk_rexie::RexieWalletDatabase;
  9. use wasm_bindgen::prelude::*;
  10. use crate::error::{into_err, Result};
  11. use crate::nuts::nut11::JsP2PKSpendingConditions;
  12. use crate::nuts::nut14::JsHTLCSpendingConditions;
  13. use crate::nuts::{JsCurrencyUnit, JsMintInfo};
  14. use crate::types::melt_quote::JsMeltQuote;
  15. use crate::types::{JsAmount, JsMelted, JsMintQuote};
  16. #[wasm_bindgen(js_name = Wallet)]
  17. pub struct JsWallet {
  18. inner: Wallet,
  19. }
  20. impl Deref for JsWallet {
  21. type Target = Wallet;
  22. fn deref(&self) -> &Self::Target {
  23. &self.inner
  24. }
  25. }
  26. impl From<Wallet> for JsWallet {
  27. fn from(inner: Wallet) -> JsWallet {
  28. JsWallet { inner }
  29. }
  30. }
  31. #[wasm_bindgen(js_class = Wallet)]
  32. impl JsWallet {
  33. #[wasm_bindgen(constructor)]
  34. pub async fn new() -> Self {
  35. let client = HttpClient::new();
  36. let db = RexieWalletDatabase::new().await.unwrap();
  37. Wallet::new(client, Arc::new(db), None).await.into()
  38. }
  39. #[wasm_bindgen(js_name = mintBalances)]
  40. pub async fn mint_balances(&self) -> Result<JsValue> {
  41. let mint_balances = self.inner.mint_balances().await.map_err(into_err)?;
  42. Ok(serde_wasm_bindgen::to_value(&mint_balances)?)
  43. }
  44. #[wasm_bindgen(js_name = addMint)]
  45. pub async fn add_mint(&self, mint_url: String) -> Result<Option<JsMintInfo>> {
  46. let mint_url = UncheckedUrl::from_str(&mint_url).map_err(into_err)?;
  47. Ok(self
  48. .inner
  49. .add_mint(mint_url)
  50. .await
  51. .map_err(into_err)?
  52. .map(|i| i.into()))
  53. }
  54. #[wasm_bindgen(js_name = refreshMint)]
  55. pub async fn refresh_mint_keys(&self, mint_url: String) -> Result<()> {
  56. let mint_url = UncheckedUrl::from_str(&mint_url).map_err(into_err)?;
  57. self.inner
  58. .refresh_mint_keys(&mint_url)
  59. .await
  60. .map_err(into_err)?;
  61. Ok(())
  62. }
  63. #[wasm_bindgen(js_name = mintQuote)]
  64. pub async fn mint_quote(
  65. &mut self,
  66. mint_url: String,
  67. amount: u64,
  68. unit: JsCurrencyUnit,
  69. ) -> Result<JsMintQuote> {
  70. let mint_url = UncheckedUrl::from_str(&mint_url).map_err(into_err)?;
  71. let quote = self
  72. .inner
  73. .mint_quote(mint_url, amount.into(), unit.into())
  74. .await
  75. .map_err(into_err)?;
  76. Ok(quote.into())
  77. }
  78. #[wasm_bindgen(js_name = mint)]
  79. pub async fn mint(&mut self, mint_url: String, quote_id: String) -> Result<JsAmount> {
  80. let mint_url = UncheckedUrl::from_str(&mint_url).map_err(into_err)?;
  81. Ok(self
  82. .inner
  83. .mint(mint_url, &quote_id)
  84. .await
  85. .map_err(into_err)?
  86. .into())
  87. }
  88. #[wasm_bindgen(js_name = meltQuote)]
  89. pub async fn melt_quote(
  90. &mut self,
  91. mint_url: String,
  92. unit: JsCurrencyUnit,
  93. request: String,
  94. ) -> Result<JsMeltQuote> {
  95. let mint_url = UncheckedUrl::from_str(&mint_url).map_err(into_err)?;
  96. let melt_quote = self
  97. .inner
  98. .melt_quote(mint_url, unit.into(), request)
  99. .await
  100. .map_err(into_err)?;
  101. Ok(melt_quote.into())
  102. }
  103. #[wasm_bindgen(js_name = melt)]
  104. pub async fn melt(&mut self, mint_url: String, quote_id: String) -> Result<JsMelted> {
  105. let mint_url = UncheckedUrl::from_str(&mint_url).map_err(into_err)?;
  106. let melted = self
  107. .inner
  108. .melt(&mint_url, &quote_id)
  109. .await
  110. .map_err(into_err)?;
  111. Ok(melted.into())
  112. }
  113. #[wasm_bindgen(js_name = receive)]
  114. pub async fn receive(
  115. &mut self,
  116. encoded_token: String,
  117. signing_keys: JsValue,
  118. preimages: JsValue,
  119. ) -> Result<()> {
  120. let signing_keys: Option<Vec<SigningKey>> = serde_wasm_bindgen::from_value(signing_keys)?;
  121. let preimages: Option<Vec<String>> = serde_wasm_bindgen::from_value(preimages)?;
  122. self.inner
  123. .receive(&encoded_token, signing_keys, preimages)
  124. .await
  125. .map_err(into_err)?;
  126. Ok(())
  127. }
  128. #[wasm_bindgen(js_name = send)]
  129. pub async fn send(
  130. &mut self,
  131. mint_url: String,
  132. unit: JsCurrencyUnit,
  133. memo: Option<String>,
  134. amount: u64,
  135. p2pk_condition: Option<JsP2PKSpendingConditions>,
  136. htlc_condition: Option<JsHTLCSpendingConditions>,
  137. ) -> Result<String> {
  138. let conditions = match (p2pk_condition, htlc_condition) {
  139. (Some(_), Some(_)) => {
  140. return Err(JsValue::from_str(
  141. "Cannot define both p2pk and htlc conditions",
  142. ));
  143. }
  144. (None, Some(htlc_condition)) => Some(htlc_condition.deref().clone()),
  145. (Some(p2pk_condition), None) => Some(p2pk_condition.deref().clone()),
  146. (None, None) => None,
  147. };
  148. let mint_url = UncheckedUrl::from_str(&mint_url).map_err(into_err)?;
  149. self.inner
  150. .send(
  151. &mint_url,
  152. &unit.into(),
  153. memo,
  154. Amount::from(amount),
  155. conditions,
  156. )
  157. .await
  158. .map_err(into_err)
  159. }
  160. }