spark_rust/wallet/
mempool.rs1use reqwest::Response;
8use url::Url;
9
10use crate::{
11 error::{NetworkError, SparkSdkError},
12 SparkNetwork,
13};
14
15pub const MEMPOOL_ENDPOINT: &str = "https://mempool.space";
17
18pub const LIGHTSPARK_MEMPOOL_ENDPOINT: &str = "https://regtest-mempool.dev.dev.sparkinfra.net";
20pub const LIGHTSPARK_REGTEST_MEMPOOL_USERNAME: &str = "spark-sdk";
21pub const LIGHTSPARK_REGTEST_MEMPOOL_PASSWORD: &str = "mCMk1JqlBNtetUNy";
22
23pub(crate) struct MempoolClient {
25 regtest_base_url: Url,
26 regtest_username: String,
27 regtest_password: String,
28}
29
30impl MempoolClient {
31 pub(crate) fn new() -> Result<Self, SparkSdkError> {
38 let regtest_base_url = {
39 let url = std::env::var("LIGHTSPARK_MEMPOOL_ENDPOINT")
40 .unwrap_or(LIGHTSPARK_MEMPOOL_ENDPOINT.to_string());
41 Url::parse(&url).map_err(|_| {
42 SparkSdkError::from(NetworkError::InvalidUrl {
43 url: url.to_string(),
44 details: None,
45 })
46 })?
47 };
48
49 let regtest_username = std::env::var("LIGHTSPARK_REGTEST_MEMPOOL_USERNAME")
50 .unwrap_or(LIGHTSPARK_REGTEST_MEMPOOL_USERNAME.to_string());
51 let regtest_password = std::env::var("LIGHTSPARK_REGTEST_MEMPOOL_PASSWORD")
52 .unwrap_or(LIGHTSPARK_REGTEST_MEMPOOL_PASSWORD.to_string());
53
54 Ok(Self {
55 regtest_base_url,
56 regtest_username,
57 regtest_password,
58 })
59 }
60
61 pub(crate) async fn request(
67 &self,
68 network: SparkNetwork,
69 path: &str,
70 ) -> Result<Response, SparkSdkError> {
71 let client = reqwest::Client::new();
72 let url = match network {
73 SparkNetwork::Regtest => self.regtest_base_url.clone(),
74 SparkNetwork::Mainnet => Url::parse(MEMPOOL_ENDPOINT).unwrap(),
75 };
76
77 let url = url.join(&format!("api/{}", path)).map_err(|err| {
78 SparkSdkError::from(NetworkError::InvalidUrl {
79 url: url.to_string(),
80 details: Some(err.to_string()),
81 })
82 })?;
83
84 let mut request = client.get(url).header("Content-Type", "application/json");
85
86 if network == SparkNetwork::Regtest {
87 request = request.basic_auth(&self.regtest_username, Some(&self.regtest_password));
88 }
89
90 request
91 .send()
92 .await
93 .and_then(|res| res.error_for_status())
94 .map_err(|err| SparkSdkError::from(NetworkError::Http(err)))
95 }
96
97 pub(crate) async fn request_text(
103 &self,
104 network: SparkNetwork,
105 path: &str,
106 ) -> Result<String, SparkSdkError> {
107 self.request(network, path)
108 .await?
109 .text()
110 .await
111 .map_err(|err| SparkSdkError::from(NetworkError::Http(err)))
112 }
113
114 pub(crate) async fn request_json<T>(
123 &self,
124 network: SparkNetwork,
125 path: &str,
126 ) -> Result<T, SparkSdkError>
127 where
128 T: serde::de::DeserializeOwned,
129 {
130 self.request(network, path)
131 .await?
132 .json()
133 .await
134 .map_err(|err| SparkSdkError::from(NetworkError::Http(err)))
135 }
136}