Skip to content

Commit b321db6

Browse files
committed
chore: missing provider
1 parent 60c7aa6 commit b321db6

File tree

1 file changed

+79
-1
lines changed
  • packages/rs-sdk-trusted-context-provider/src

1 file changed

+79
-1
lines changed

packages/rs-sdk-trusted-context-provider/src/provider.rs

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use dpp::version::PlatformVersion;
2424

2525
use lru::LruCache;
2626
use reqwest::Client;
27+
use serde::Deserialize;
2728
use std::collections::HashMap;
2829
use std::error::Error as StdError;
2930
#[cfg(not(target_arch = "wasm32"))]
@@ -33,7 +34,6 @@ use std::sync::{Arc, Mutex};
3334
#[cfg(not(target_arch = "wasm32"))]
3435
use std::time::Duration;
3536
use tracing::{debug, info};
36-
#[cfg(not(target_arch = "wasm32"))]
3737
use url::Url;
3838

3939
/// A trusted HTTP-based context provider that fetches quorum information
@@ -65,6 +65,20 @@ pub struct TrustedHttpContextProvider {
6565
refetch_if_not_found: bool,
6666
}
6767

68+
#[derive(Debug, Deserialize)]
69+
struct MasternodeEntry {
70+
address: String,
71+
status: String,
72+
#[serde(rename = "versionCheck")]
73+
version_check: Option<String>,
74+
}
75+
76+
#[derive(Debug, Deserialize)]
77+
struct MasternodeDiscoveryResponse {
78+
success: bool,
79+
data: Vec<MasternodeEntry>,
80+
}
81+
6882
impl TrustedHttpContextProvider {
6983
/// Verify that a URL's domain resolves
7084
#[cfg(not(target_arch = "wasm32"))]
@@ -229,6 +243,70 @@ impl TrustedHttpContextProvider {
229243
current_count + previous_count
230244
}
231245

246+
/// Fetch DAPI HTTPS addresses from the masternode discovery endpoint
247+
pub async fn fetch_masternode_addresses(
248+
&self,
249+
) -> Result<Vec<Url>, TrustedContextProviderError> {
250+
let url = format!("{}/masternodes", self.base_url);
251+
debug!(
252+
"Fetching masternode addresses from trusted resource: {}",
253+
url
254+
);
255+
256+
let response = self.client.get(&url).send().await?;
257+
if !response.status().is_success() {
258+
return Err(TrustedContextProviderError::NetworkError(format!(
259+
"HTTP {} from {}",
260+
response.status(),
261+
url
262+
)));
263+
}
264+
265+
let body = response.text().await?;
266+
let parsed: MasternodeDiscoveryResponse = serde_json::from_str(&body)?;
267+
268+
if !parsed.success {
269+
return Err(TrustedContextProviderError::NetworkError(
270+
"Masternode discovery response indicated failure".to_string(),
271+
));
272+
}
273+
274+
let dapi_port = match self.network {
275+
Network::Dash => 443,
276+
Network::Testnet => 1443,
277+
_ => 443,
278+
};
279+
280+
let mut addresses = Vec::new();
281+
for entry in parsed
282+
.data
283+
.into_iter()
284+
.filter(|m| m.status == "ENABLED" && m.version_check.as_deref() == Some("success"))
285+
{
286+
let host_port = entry.address;
287+
let host = host_port
288+
.rsplit_once(':')
289+
.map(|(h, _)| h)
290+
.unwrap_or(host_port.as_str());
291+
let https_url = format!("https://{}:{}", host, dapi_port);
292+
let url = url::Url::parse(&https_url).map_err(|e| {
293+
TrustedContextProviderError::NetworkError(format!(
294+
"Invalid masternode URL '{}': {}",
295+
https_url, e
296+
))
297+
})?;
298+
addresses.push(url);
299+
}
300+
301+
if addresses.is_empty() {
302+
return Err(TrustedContextProviderError::NetworkError(
303+
"No eligible masternode addresses discovered".to_string(),
304+
));
305+
}
306+
307+
Ok(addresses)
308+
}
309+
232310
/// Fetch current quorums from the HTTP endpoint
233311
pub async fn fetch_current_quorums(
234312
&self,

0 commit comments

Comments
 (0)