gloo_client.rs 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. //! gloo wasm http Client
  2. use async_trait::async_trait;
  3. use cashu::nuts::{
  4. BlindedMessage, Keys, MeltBolt11Request, MeltBolt11Response, MintBolt11Request,
  5. MintBolt11Response, MintInfo, PreMintSecrets, Proof, SwapRequest, SwapResponse, *,
  6. };
  7. #[cfg(feature = "nut07")]
  8. use cashu::nuts::{CheckSpendableRequest, CheckSpendableResponse};
  9. use gloo::net::http::Request;
  10. use serde_json::Value;
  11. use url::Url;
  12. use super::join_url;
  13. use crate::client::{Client, Error};
  14. #[derive(Debug, Clone)]
  15. pub struct HttpClient {}
  16. #[async_trait(?Send)]
  17. impl Client for HttpClient {
  18. /// Get Mint Keys [NUT-01]
  19. async fn get_mint_keys(&self, mint_url: Url) -> Result<Keys, Error> {
  20. let url = join_url(mint_url, "keys")?;
  21. let keys = Request::get(url.as_str())
  22. .send()
  23. .await
  24. .map_err(|err| Error::Gloo(err.to_string()))?
  25. .json::<Value>()
  26. .await
  27. .map_err(|err| Error::Gloo(err.to_string()))?;
  28. let keys: Keys = serde_json::from_str(&keys.to_string())?;
  29. Ok(keys)
  30. }
  31. /// Get Keysets [NUT-02]
  32. async fn get_mint_keysets(&self, mint_url: Url) -> Result<KeysetResponse, Error> {
  33. let url = join_url(mint_url, "keysets")?;
  34. let res = Request::get(url.as_str())
  35. .send()
  36. .await
  37. .map_err(|err| Error::Gloo(err.to_string()))?
  38. .json::<Value>()
  39. .await
  40. .map_err(|err| Error::Gloo(err.to_string()))?;
  41. let response: Result<KeysetResponse, serde_json::Error> =
  42. serde_json::from_value(res.clone());
  43. match response {
  44. Ok(res) => Ok(res),
  45. Err(_) => Err(Error::from_json(&res.to_string())?),
  46. }
  47. }
  48. /// Mint Tokens [NUT-04]
  49. async fn post_mint(
  50. &self,
  51. mint_url: Url,
  52. quote: &str,
  53. premint_secrets: PreMintSecrets,
  54. ) -> Result<MintBolt11Response, Error> {
  55. let url = join_url(mint_url, "mint")?;
  56. let request = MintBolt11Request {
  57. quote: quote.to_string(),
  58. outputs: premint_secrets.blinded_messages(),
  59. };
  60. let res = Request::post(url.as_str())
  61. .json(&request)
  62. .map_err(|err| Error::Gloo(err.to_string()))?
  63. .send()
  64. .await
  65. .map_err(|err| Error::Gloo(err.to_string()))?
  66. .json::<Value>()
  67. .await
  68. .map_err(|err| Error::Gloo(err.to_string()))?;
  69. let response: Result<MintBolt11Response, serde_json::Error> =
  70. serde_json::from_value(res.clone());
  71. match response {
  72. Ok(res) => Ok(res),
  73. Err(_) => Err(Error::from_json(&res.to_string())?),
  74. }
  75. }
  76. /// Melt [NUT-05]
  77. /// [Nut-08] Lightning fee return if outputs defined
  78. async fn post_melt(
  79. &self,
  80. mint_url: Url,
  81. quote: String,
  82. inputs: Vec<Proof>,
  83. outputs: Option<Vec<BlindedMessage>>,
  84. ) -> Result<MeltBolt11Response, Error> {
  85. let url = join_url(mint_url, "melt")?;
  86. let request = MeltBolt11Request {
  87. quote,
  88. inputs,
  89. outputs,
  90. };
  91. let value = Request::post(url.as_str())
  92. .json(&request)
  93. .map_err(|err| Error::Gloo(err.to_string()))?
  94. .send()
  95. .await
  96. .map_err(|err| Error::Gloo(err.to_string()))?
  97. .json::<Value>()
  98. .await
  99. .map_err(|err| Error::Gloo(err.to_string()))?;
  100. let response: Result<MeltBolt11Response, serde_json::Error> =
  101. serde_json::from_value(value.clone());
  102. match response {
  103. Ok(res) => Ok(res),
  104. Err(_) => Err(Error::from_json(&value.to_string())?),
  105. }
  106. }
  107. /// Split Token [NUT-06]
  108. async fn post_split(
  109. &self,
  110. mint_url: Url,
  111. split_request: SwapRequest,
  112. ) -> Result<SwapResponse, Error> {
  113. let url = join_url(mint_url, "split")?;
  114. let res = Request::post(url.as_str())
  115. .json(&split_request)
  116. .map_err(|err| Error::Gloo(err.to_string()))?
  117. .send()
  118. .await
  119. .map_err(|err| Error::Gloo(err.to_string()))?
  120. .json::<Value>()
  121. .await
  122. .map_err(|err| Error::Gloo(err.to_string()))?;
  123. let response: Result<SwapResponse, serde_json::Error> = serde_json::from_value(res.clone());
  124. match response {
  125. Ok(res) => Ok(res),
  126. Err(_) => Err(Error::from_json(&res.to_string())?),
  127. }
  128. }
  129. /// Spendable check [NUT-07]
  130. #[cfg(feature = "nut07")]
  131. async fn post_check_spendable(
  132. &self,
  133. mint_url: Url,
  134. proofs: Vec<nut00::mint::Proof>,
  135. ) -> Result<CheckSpendableResponse, Error> {
  136. let url = join_url(mint_url, "check")?;
  137. let request = CheckSpendableRequest {
  138. proofs: proofs.to_owned(),
  139. };
  140. let res = Request::post(url.as_str())
  141. .json(&request)
  142. .map_err(|err| Error::Gloo(err.to_string()))?
  143. .send()
  144. .await
  145. .map_err(|err| Error::Gloo(err.to_string()))?
  146. .json::<Value>()
  147. .await
  148. .map_err(|err| Error::Gloo(err.to_string()))?;
  149. let response: Result<CheckSpendableResponse, serde_json::Error> =
  150. serde_json::from_value(res.clone());
  151. match response {
  152. Ok(res) => Ok(res),
  153. Err(_) => Err(Error::from_json(&res.to_string())?),
  154. }
  155. }
  156. /// Get Mint Info [NUT-09]
  157. async fn get_mint_info(&self, mint_url: Url) -> Result<MintInfo, Error> {
  158. let url = join_url(mint_url, "info")?;
  159. let res = Request::get(url.as_str())
  160. .send()
  161. .await
  162. .map_err(|err| Error::Gloo(err.to_string()))?
  163. .json::<Value>()
  164. .await
  165. .map_err(|err| Error::Gloo(err.to_string()))?;
  166. let response: Result<MintInfo, serde_json::Error> = serde_json::from_value(res.clone());
  167. match response {
  168. Ok(res) => Ok(res),
  169. Err(_) => Err(Error::from_json(&res.to_string())?),
  170. }
  171. }
  172. }