client.rs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. //! Client to connet to mint
  2. use bitcoin::Amount;
  3. use serde_json::Value;
  4. use url::Url;
  5. pub use crate::Invoice;
  6. use crate::{
  7. error::Error,
  8. keyset::{Keys, MintKeySets},
  9. types::{
  10. BlindedMessage, BlindedMessages, CheckFeesRequest, CheckFeesResponse,
  11. CheckSpendableRequest, CheckSpendableResponse, MeltRequest, MeltResponse, MintInfo,
  12. MintRequest, PostMintResponse, Proof, RequestMintResponse, SplitRequest, SplitResponse,
  13. },
  14. };
  15. #[derive(Debug, Clone)]
  16. pub struct Client {
  17. pub mint_url: Url,
  18. }
  19. impl Client {
  20. pub fn new(mint_url: &str) -> Result<Self, Error> {
  21. // HACK
  22. let mut mint_url = String::from(mint_url);
  23. if !mint_url.ends_with('/') {
  24. mint_url.push('/');
  25. }
  26. let mint_url = Url::parse(&mint_url)?;
  27. Ok(Self { mint_url })
  28. }
  29. /// Get Mint Keys [NUT-01]
  30. pub async fn get_keys(&self) -> Result<Keys, Error> {
  31. let url = self.mint_url.join("keys")?;
  32. let keys = minreq::get(url).send()?.json::<Value>()?;
  33. let keys: Keys = serde_json::from_str(&keys.to_string())?;
  34. /*
  35. let keys: BTreeMap<u64, String> = match serde_json::from_value(keys.clone()) {
  36. Ok(keys) => keys,
  37. Err(_err) => {
  38. return Err(Error::CustomError(format!(
  39. "url: {}, {}",
  40. url,
  41. serde_json::to_string(&keys)?
  42. )))
  43. }
  44. };
  45. let mint_keys: BTreeMap<u64, PublicKey> = keys
  46. .into_iter()
  47. .filter_map(|(k, v)| {
  48. let key = hex::decode(v).ok()?;
  49. let public_key = PublicKey::from_sec1_bytes(&key).ok()?;
  50. Some((k, public_key))
  51. })
  52. .collect();
  53. */
  54. Ok(keys)
  55. }
  56. /// Get Keysets [NUT-02]
  57. pub async fn get_keysets(&self) -> Result<MintKeySets, Error> {
  58. let url = self.mint_url.join("keysets")?;
  59. let res = minreq::get(url).send()?.json::<Value>()?;
  60. let response: Result<MintKeySets, serde_json::Error> = serde_json::from_value(res.clone());
  61. match response {
  62. Ok(res) => Ok(res),
  63. Err(_) => Err(Error::CustomError(res.to_string())),
  64. }
  65. }
  66. /// Request Mint [NUT-03]
  67. pub async fn request_mint(&self, amount: Amount) -> Result<RequestMintResponse, Error> {
  68. let mut url = self.mint_url.join("mint")?;
  69. url.query_pairs_mut()
  70. .append_pair("amount", &amount.to_sat().to_string());
  71. let res = minreq::get(url).send()?.json::<Value>()?;
  72. let response: Result<RequestMintResponse, serde_json::Error> =
  73. serde_json::from_value(res.clone());
  74. match response {
  75. Ok(res) => Ok(res),
  76. Err(_) => Err(Error::CustomError(res.to_string())),
  77. }
  78. }
  79. /// Mint Tokens [NUT-04]
  80. pub async fn mint(
  81. &self,
  82. blinded_messages: BlindedMessages,
  83. hash: &str,
  84. ) -> Result<PostMintResponse, Error> {
  85. let mut url = self.mint_url.join("mint")?;
  86. url.query_pairs_mut().append_pair("hash", hash);
  87. let request = MintRequest {
  88. outputs: blinded_messages.blinded_messages,
  89. };
  90. let res = minreq::post(url)
  91. .with_json(&request)?
  92. .send()?
  93. .json::<Value>()?;
  94. let response: Result<PostMintResponse, serde_json::Error> =
  95. serde_json::from_value(res.clone());
  96. match response {
  97. Ok(res) => Ok(res),
  98. Err(_) => Err(Error::CustomError(res.to_string())),
  99. }
  100. }
  101. /// Check Max expected fee [NUT-05]
  102. pub async fn check_fees(&self, invoice: Invoice) -> Result<CheckFeesResponse, Error> {
  103. let url = self.mint_url.join("checkfees")?;
  104. let request = CheckFeesRequest { pr: invoice };
  105. let res = minreq::post(url)
  106. .with_json(&request)?
  107. .send()?
  108. .json::<Value>()?;
  109. let response: Result<CheckFeesResponse, serde_json::Error> =
  110. serde_json::from_value(res.clone());
  111. match response {
  112. Ok(res) => Ok(res),
  113. Err(_) => Err(Error::CustomError(res.to_string())),
  114. }
  115. }
  116. /// Melt [NUT-05]
  117. /// [Nut-08] Lightning fee return if outputs defined
  118. pub async fn melt(
  119. &self,
  120. proofs: Vec<Proof>,
  121. invoice: Invoice,
  122. outputs: Option<Vec<BlindedMessage>>,
  123. ) -> Result<MeltResponse, Error> {
  124. let url = self.mint_url.join("melt")?;
  125. let request = MeltRequest {
  126. proofs,
  127. pr: invoice,
  128. outputs,
  129. };
  130. let value = minreq::post(url)
  131. .with_json(&request)?
  132. .send()?
  133. .json::<Value>()?;
  134. let response: Result<MeltResponse, serde_json::Error> =
  135. serde_json::from_value(value.clone());
  136. match response {
  137. Ok(res) => Ok(res),
  138. Err(_) => Err(Error::CustomError(value.to_string())),
  139. }
  140. }
  141. /// Split Token [NUT-06]
  142. pub async fn split(&self, split_request: SplitRequest) -> Result<SplitResponse, Error> {
  143. let url = self.mint_url.join("split")?;
  144. let res = minreq::post(url)
  145. .with_json(&split_request)?
  146. .send()?
  147. .json::<Value>()?;
  148. let response: Result<SplitResponse, serde_json::Error> =
  149. serde_json::from_value(res.clone());
  150. match response {
  151. Ok(res) => Ok(res),
  152. Err(_) => Err(Error::CustomError(res.to_string())),
  153. }
  154. }
  155. /// Spendable check [NUT-07]
  156. pub async fn check_spendable(
  157. &self,
  158. proofs: &Vec<Proof>,
  159. ) -> Result<CheckSpendableResponse, Error> {
  160. let url = self.mint_url.join("check")?;
  161. let request = CheckSpendableRequest {
  162. proofs: proofs.to_owned(),
  163. };
  164. let res = minreq::post(url)
  165. .with_json(&request)?
  166. .send()?
  167. .json::<Value>()?;
  168. let response: Result<CheckSpendableResponse, serde_json::Error> =
  169. serde_json::from_value(res.clone());
  170. match response {
  171. Ok(res) => Ok(res),
  172. Err(_) => Err(Error::CustomError(res.to_string())),
  173. }
  174. }
  175. /// Get Mint Info [NUT-09]
  176. pub async fn get_info(&self) -> Result<MintInfo, Error> {
  177. let url = self.mint_url.join("info")?;
  178. let res = minreq::get(url).send()?.json::<Value>()?;
  179. let response: Result<MintInfo, serde_json::Error> = serde_json::from_value(res.clone());
  180. match response {
  181. Ok(res) => Ok(res),
  182. Err(_) => Err(Error::CustomError(res.to_string())),
  183. }
  184. }
  185. }