314 lines
8.5 KiB
Rust
314 lines
8.5 KiB
Rust
use base64::{
|
|
engine::general_purpose,
|
|
Engine as _,
|
|
};
|
|
use reqwest::Client;
|
|
use serde_json::Value;
|
|
use std::time::Duration;
|
|
|
|
/// Get information about the Mycelium node
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `api_url` - The URL of the Mycelium API
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// * `Result<Value, String>` - The node information as a JSON value, or an error message
|
|
pub async fn get_node_info(api_url: &str) -> Result<Value, String> {
|
|
let client = Client::new();
|
|
let url = format!("{}/api/v1/admin", api_url);
|
|
|
|
let response = client
|
|
.get(&url)
|
|
.send()
|
|
.await
|
|
.map_err(|e| format!("Failed to send request: {}", e))?;
|
|
|
|
let status = response.status();
|
|
if !status.is_success() {
|
|
return Err(format!("Request failed with status: {}", status));
|
|
}
|
|
|
|
let result: Value = response
|
|
.json()
|
|
.await
|
|
.map_err(|e| format!("Failed to parse response: {}", e))?;
|
|
|
|
Ok(result)
|
|
}
|
|
|
|
/// List all peers connected to the Mycelium node
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `api_url` - The URL of the Mycelium API
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// * `Result<Value, String>` - The list of peers as a JSON value, or an error message
|
|
pub async fn list_peers(api_url: &str) -> Result<Value, String> {
|
|
let client = Client::new();
|
|
let url = format!("{}/api/v1/admin/peers", api_url);
|
|
|
|
let response = client
|
|
.get(&url)
|
|
.send()
|
|
.await
|
|
.map_err(|e| format!("Failed to send request: {}", e))?;
|
|
|
|
let status = response.status();
|
|
if !status.is_success() {
|
|
return Err(format!("Request failed with status: {}", status));
|
|
}
|
|
|
|
let result: Value = response
|
|
.json()
|
|
.await
|
|
.map_err(|e| format!("Failed to parse response: {}", e))?;
|
|
|
|
Ok(result)
|
|
}
|
|
|
|
/// Add a new peer to the Mycelium node
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `api_url` - The URL of the Mycelium API
|
|
/// * `peer_address` - The address of the peer to add
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// * `Result<Value, String>` - The result of the operation as a JSON value, or an error message
|
|
pub async fn add_peer(api_url: &str, peer_address: &str) -> Result<Value, String> {
|
|
let client = Client::new();
|
|
let url = format!("{}/api/v1/admin/peers", api_url);
|
|
|
|
let response = client
|
|
.post(&url)
|
|
.json(&serde_json::json!({
|
|
"endpoint": peer_address
|
|
}))
|
|
.send()
|
|
.await
|
|
.map_err(|e| format!("Failed to send request: {}", e))?;
|
|
|
|
let status = response.status();
|
|
if status == reqwest::StatusCode::NO_CONTENT {
|
|
// Successfully added, but no content to parse
|
|
return Ok(serde_json::json!({"success": true}));
|
|
}
|
|
if !status.is_success() {
|
|
return Err(format!("Request failed with status: {}", status));
|
|
}
|
|
|
|
// For other success statuses that might have a body
|
|
let result: Value = response
|
|
.json()
|
|
.await
|
|
.map_err(|e| format!("Failed to parse response: {}", e))?;
|
|
|
|
Ok(result)
|
|
}
|
|
|
|
/// Remove a peer from the Mycelium node
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `api_url` - The URL of the Mycelium API
|
|
/// * `peer_id` - The ID of the peer to remove
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// * `Result<Value, String>` - The result of the operation as a JSON value, or an error message
|
|
pub async fn remove_peer(api_url: &str, peer_id: &str) -> Result<Value, String> {
|
|
let client = Client::new();
|
|
let peer_id_url_encoded = urlencoding::encode(peer_id);
|
|
let url = format!("{}/api/v1/admin/peers/{}", api_url, peer_id_url_encoded);
|
|
|
|
let response = client
|
|
.delete(&url)
|
|
.send()
|
|
.await
|
|
.map_err(|e| format!("Failed to send request: {}", e))?;
|
|
|
|
let status = response.status();
|
|
if status == reqwest::StatusCode::NO_CONTENT {
|
|
// Successfully removed, but no content to parse
|
|
return Ok(serde_json::json!({"success": true}));
|
|
}
|
|
if !status.is_success() {
|
|
return Err(format!("Request failed with status: {}", status));
|
|
}
|
|
|
|
let result: Value = response
|
|
.json()
|
|
.await
|
|
.map_err(|e| format!("Failed to parse response: {}", e))?;
|
|
|
|
Ok(result)
|
|
}
|
|
|
|
/// List all selected routes in the Mycelium node
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `api_url` - The URL of the Mycelium API
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// * `Result<Value, String>` - The list of selected routes as a JSON value, or an error message
|
|
pub async fn list_selected_routes(api_url: &str) -> Result<Value, String> {
|
|
let client = Client::new();
|
|
let url = format!("{}/api/v1/admin/routes/selected", api_url);
|
|
|
|
let response = client
|
|
.get(&url)
|
|
.send()
|
|
.await
|
|
.map_err(|e| format!("Failed to send request: {}", e))?;
|
|
|
|
let status = response.status();
|
|
if !status.is_success() {
|
|
return Err(format!("Request failed with status: {}", status));
|
|
}
|
|
|
|
let result: Value = response
|
|
.json()
|
|
.await
|
|
.map_err(|e| format!("Failed to parse response: {}", e))?;
|
|
|
|
Ok(result)
|
|
}
|
|
|
|
/// List all fallback routes in the Mycelium node
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `api_url` - The URL of the Mycelium API
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// * `Result<Value, String>` - The list of fallback routes as a JSON value, or an error message
|
|
pub async fn list_fallback_routes(api_url: &str) -> Result<Value, String> {
|
|
let client = Client::new();
|
|
let url = format!("{}/api/v1/admin/routes/fallback", api_url);
|
|
|
|
let response = client
|
|
.get(&url)
|
|
.send()
|
|
.await
|
|
.map_err(|e| format!("Failed to send request: {}", e))?;
|
|
|
|
let status = response.status();
|
|
if !status.is_success() {
|
|
return Err(format!("Request failed with status: {}", status));
|
|
}
|
|
|
|
let result: Value = response
|
|
.json()
|
|
.await
|
|
.map_err(|e| format!("Failed to parse response: {}", e))?;
|
|
|
|
Ok(result)
|
|
}
|
|
|
|
/// Send a message to a destination via the Mycelium node
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `api_url` - The URL of the Mycelium API
|
|
/// * `destination` - The destination address
|
|
/// * `topic` - The message topic
|
|
/// * `message` - The message content
|
|
/// * `reply_deadline` - The deadline in seconds; pass `-1` to indicate we do not want to wait on a reply
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// * `Result<Value, String>` - The result of the operation as a JSON value, or an error message
|
|
pub async fn send_message(
|
|
api_url: &str,
|
|
destination: &str,
|
|
topic: &str,
|
|
message: &str,
|
|
reply_deadline: Option<Duration>, // This is passed in URL query
|
|
) -> Result<Value, String> {
|
|
let client = Client::new();
|
|
let url = format!("{}/api/v1/messages", api_url);
|
|
|
|
let mut request = client.post(&url);
|
|
if let Some(deadline) = reply_deadline {
|
|
request = request.query(&[("reply_timeout", deadline.as_secs())]);
|
|
}
|
|
|
|
let response = request
|
|
.json(&serde_json::json!({
|
|
"dst": { "ip": destination },
|
|
"topic": general_purpose::STANDARD.encode(topic),
|
|
"payload": general_purpose::STANDARD.encode(message)
|
|
}))
|
|
.send()
|
|
.await
|
|
.map_err(|e| format!("Failed to send request: {}", e))?;
|
|
|
|
let status = response.status();
|
|
if !status.is_success() {
|
|
return Err(format!("Request failed with status: {}", status));
|
|
}
|
|
|
|
let result: Value = response
|
|
.json()
|
|
.await
|
|
.map_err(|e| format!("Failed to parse response: {}", e))?;
|
|
|
|
Ok(result)
|
|
}
|
|
|
|
/// Receive messages from a topic via the Mycelium node
|
|
///
|
|
/// # Arguments
|
|
///
|
|
/// * `api_url` - The URL of the Mycelium API
|
|
/// * `topic` - The message topic
|
|
/// * `wait_deadline` - Time we wait for receiving a message
|
|
///
|
|
/// # Returns
|
|
///
|
|
/// * `Result<Value, String>` - The received messages as a JSON value, or an error message
|
|
pub async fn receive_messages(
|
|
api_url: &str,
|
|
topic: &str,
|
|
wait_deadline: Option<Duration>,
|
|
) -> Result<Value, String> {
|
|
let client = Client::new();
|
|
let url = format!("{}/api/v1/messages", api_url);
|
|
|
|
let mut request = client.get(&url);
|
|
|
|
if let Some(deadline) = wait_deadline {
|
|
request = request.query(&[
|
|
("topic", general_purpose::STANDARD.encode(topic)),
|
|
("timeout", deadline.as_secs().to_string()),
|
|
])
|
|
} else {
|
|
request = request.query(&[("topic", general_purpose::STANDARD.encode(topic))])
|
|
};
|
|
|
|
let response = request
|
|
.send()
|
|
.await
|
|
.map_err(|e| format!("Failed to send request: {}", e))?;
|
|
|
|
let status = response.status();
|
|
if !status.is_success() {
|
|
return Err(format!("Request failed with status: {}", status));
|
|
}
|
|
|
|
let result: Value = response
|
|
.json()
|
|
.await
|
|
.map_err(|e| format!("Failed to parse response: {}", e))?;
|
|
|
|
Ok(result)
|
|
}
|