diff --git a/Cargo.toml b/Cargo.toml index 04cbbef..707145b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,6 +48,7 @@ tokio-test = "0.4.4" uuid = { version = "1.16.0", features = ["v4"] } zinit-client = { git = "https://github.com/threefoldtech/zinit", branch = "json_rpc", package = "zinit-client" } reqwest = { version = "0.12.15", features = ["json"] } +urlencoding = "2.1.3" # Optional features for specific OS functionality [target.'cfg(unix)'.dependencies] diff --git a/examples/mycelium/mycelium_basic.rhai b/examples/mycelium/mycelium_basic.rhai index 6460b24..1297fa4 100644 --- a/examples/mycelium/mycelium_basic.rhai +++ b/examples/mycelium/mycelium_basic.rhai @@ -22,9 +22,9 @@ try { print("No peers connected."); } else { for peer in peers { - print(`Peer ID: ${peer.id}`); - print(` Address: ${peer.address}`); - print(` Connected: ${peer.connected}`); + print(`Peer Endpoint: ${peer.endpoint.proto}://${peer.endpoint.socketAddr}`); + print(` Type: ${peer.type}`); + print(` Connection State: ${peer.connectionState}`); print(` Bytes sent: ${peer.txBytes}`); print(` Bytes received: ${peer.rxBytes}`); } @@ -35,7 +35,7 @@ try { // Add a new peer print("\nAdding a new peer:"); -let new_peer_address = "tcp://185.69.166.8:9651"; +let new_peer_address = "tcp://65.21.231.58:9651"; try { let result = mycelium_add_peer(api_url, new_peer_address); print(`Peer added: ${result.success}`); @@ -80,47 +80,51 @@ try { } // Send a message -print("\nSending a message:"); -let destination = "400:1234:5678:9abc:def0:1234:5678:9abc"; -let topic = "test"; -let message = "Hello from Rhai!"; -let deadline_secs = 60; +// TO SEND A MESSAGE FILL IN THE DESTINATION IP ADDRESS +// -----------------------------------------------------// +// print("\nSending a message:"); +// let destination = < FILL IN CORRECT DEST IP > +// let topic = "test"; +// let message = "Hello from Rhai!"; +// let deadline_secs = 60; -try { - let result = mycelium_send_message(api_url, destination, topic, message, deadline_secs); - print(`Message sent: ${result.success}`); - if result.id { - print(`Message ID: ${result.id}`); - } -} catch(err) { - print(`Error sending message: ${err}`); -} +// try { +// let result = mycelium_send_message(api_url, destination, topic, message, deadline_secs); +// print(`Message sent: ${result.success}`); +// if result.id { +// print(`Message ID: ${result.id}`); +// } +// } catch(err) { +// print(`Error sending message: ${err}`); +// } // Receive messages -print("\nReceiving messages:"); -let receive_topic = "test"; -let count = 5; +// RECEIVING MESSAGES SHOULD BE DONE ON THE DESTINATION NODE FROM THE CALL ABOVE +// -----------------------------------------------------------------------------// +// print("\nReceiving messages:"); +// let receive_topic = "test"; +// let count = 5; -try { - let messages = mycelium_receive_messages(api_url, receive_topic, count); +// try { +// let messages = mycelium_receive_messages(api_url, receive_topic, count); - if messages.is_empty() { - print("No messages received."); - } else { - for msg in messages { - print(`Message from: ${msg.source}`); - print(` Topic: ${msg.topic}`); - print(` Content: ${msg.content}`); - print(` Timestamp: ${msg.timestamp}`); - } - } -} catch(err) { - print(`Error receiving messages: ${err}`); -} +// if messages.is_empty() { +// print("No messages received."); +// } else { +// for msg in messages { +// print(`Message from: ${msg.source}`); +// print(` Topic: ${msg.topic}`); +// print(` Content: ${msg.content}`); +// print(` Timestamp: ${msg.timestamp}`); +// } +// } +// } catch(err) { +// print(`Error receiving messages: ${err}`); +// } // Remove a peer print("\nRemoving a peer:"); -let peer_id = "some-peer-id"; // Replace with an actual peer ID +let peer_id = "tcp://65.21.231.58:9651"; // This is the peer we added earlier try { let result = mycelium_remove_peer(api_url, peer_id); print(`Peer removed: ${result.success}`); diff --git a/src/mycelium/mod.rs b/src/mycelium/mod.rs index 10279ad..00847c2 100644 --- a/src/mycelium/mod.rs +++ b/src/mycelium/mod.rs @@ -1,7 +1,11 @@ -use std::time::Duration; -use serde_json::Value; +use base64::{ + alphabet, + engine::{self, general_purpose}, + Engine as _, +}; use reqwest::Client; -use base64::encode; +use serde_json::Value; +use std::time::Duration; /// Get information about the Mycelium node /// @@ -15,23 +19,23 @@ use base64::encode; pub async fn get_node_info(api_url: &str) -> Result { 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) } @@ -47,23 +51,23 @@ pub async fn get_node_info(api_url: &str) -> Result { pub async fn list_peers(api_url: &str) -> Result { 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) } @@ -80,26 +84,31 @@ pub async fn list_peers(api_url: &str) -> Result { pub async fn add_peer(api_url: &str, peer_address: &str) -> Result { let client = Client::new(); let url = format!("{}/api/v1/admin/peers", api_url); - + let response = client .post(&url) .json(&serde_json::json!({ - "address": peer_address + "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) } @@ -115,24 +124,29 @@ pub async fn add_peer(api_url: &str, peer_address: &str) -> Result` - 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 { let client = Client::new(); - let url = format!("{}/api/v1/admin/peers/{}", api_url, peer_id); - + 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) } @@ -148,23 +162,23 @@ pub async fn remove_peer(api_url: &str, peer_id: &str) -> Result pub async fn list_selected_routes(api_url: &str) -> Result { 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) } @@ -180,23 +194,23 @@ pub async fn list_selected_routes(api_url: &str) -> Result { pub async fn list_fallback_routes(api_url: &str) -> Result { 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) } @@ -213,35 +227,40 @@ pub async fn list_fallback_routes(api_url: &str) -> Result { /// # Returns /// /// * `Result` - 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, deadline_secs: u64) -> Result { +pub async fn send_message( + api_url: &str, + destination: &str, + topic: &str, + message: &str, + deadline_secs: u64, +) -> Result { let client = Client::new(); let url = format!("{}/api/v1/messages", api_url); - + // Convert deadline to seconds let deadline = Duration::from_secs(deadline_secs).as_secs(); - + let response = client .post(&url) .json(&serde_json::json!({ - "destination": destination, - "topic": topic, - "content": message, - "deadline": deadline + "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) } @@ -259,23 +278,23 @@ pub async fn send_message(api_url: &str, destination: &str, topic: &str, message pub async fn receive_messages(api_url: &str, topic: &str, count: u32) -> Result { let client = Client::new(); let url = format!("{}/api/v1/messages", api_url); - + let response = client .get(&url) - .query(&[("topic", encode(topic)), ("count", count.to_string())]) + .query(&[("topic", general_purpose::STANDARD.encode(topic))]) .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) -} \ No newline at end of file +}