Compare commits
No commits in common. "330ab2393005db958ffb42b9d35382bfa4ab5811" and "3a0900fc15c4a6a5593260bbf3b3ef0d9636d555" have entirely different histories.
330ab23930
...
3a0900fc15
@ -47,8 +47,6 @@ tokio-postgres = "0.7.8" # Async PostgreSQL client
|
|||||||
tokio-test = "0.4.4"
|
tokio-test = "0.4.4"
|
||||||
uuid = { version = "1.16.0", features = ["v4"] }
|
uuid = { version = "1.16.0", features = ["v4"] }
|
||||||
zinit-client = { git = "https://github.com/threefoldtech/zinit", branch = "json_rpc", package = "zinit-client" }
|
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
|
# Optional features for specific OS functionality
|
||||||
[target.'cfg(unix)'.dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
|
@ -1,133 +0,0 @@
|
|||||||
// Basic example of using the Mycelium client in Rhai
|
|
||||||
|
|
||||||
// API URL for Mycelium
|
|
||||||
let api_url = "http://localhost:8989";
|
|
||||||
|
|
||||||
// Get node information
|
|
||||||
print("Getting node information:");
|
|
||||||
try {
|
|
||||||
let node_info = mycelium_get_node_info(api_url);
|
|
||||||
print(`Node subnet: ${node_info.nodeSubnet}`);
|
|
||||||
print(`Node public key: ${node_info.nodePubkey}`);
|
|
||||||
} catch(err) {
|
|
||||||
print(`Error getting node info: ${err}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// List all peers
|
|
||||||
print("\nListing all peers:");
|
|
||||||
try {
|
|
||||||
let peers = mycelium_list_peers(api_url);
|
|
||||||
|
|
||||||
if peers.is_empty() {
|
|
||||||
print("No peers connected.");
|
|
||||||
} else {
|
|
||||||
for peer in peers {
|
|
||||||
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}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch(err) {
|
|
||||||
print(`Error listing peers: ${err}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a new peer
|
|
||||||
print("\nAdding a new peer:");
|
|
||||||
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}`);
|
|
||||||
} catch(err) {
|
|
||||||
print(`Error adding peer: ${err}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// List selected routes
|
|
||||||
print("\nListing selected routes:");
|
|
||||||
try {
|
|
||||||
let routes = mycelium_list_selected_routes(api_url);
|
|
||||||
|
|
||||||
if routes.is_empty() {
|
|
||||||
print("No selected routes.");
|
|
||||||
} else {
|
|
||||||
for route in routes {
|
|
||||||
print(`Subnet: ${route.subnet}`);
|
|
||||||
print(` Next hop: ${route.nextHop}`);
|
|
||||||
print(` Metric: ${route.metric}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch(err) {
|
|
||||||
print(`Error listing routes: ${err}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// List fallback routes
|
|
||||||
print("\nListing fallback routes:");
|
|
||||||
try {
|
|
||||||
let routes = mycelium_list_fallback_routes(api_url);
|
|
||||||
|
|
||||||
if routes.is_empty() {
|
|
||||||
print("No fallback routes.");
|
|
||||||
} else {
|
|
||||||
for route in routes {
|
|
||||||
print(`Subnet: ${route.subnet}`);
|
|
||||||
print(` Next hop: ${route.nextHop}`);
|
|
||||||
print(` Metric: ${route.metric}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch(err) {
|
|
||||||
print(`Error listing fallback routes: ${err}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send a message
|
|
||||||
// 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}`);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Receive messages
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
// 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 = "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}`);
|
|
||||||
} catch(err) {
|
|
||||||
print(`Error removing peer: ${err}`);
|
|
||||||
}
|
|
@ -48,7 +48,6 @@ pub mod text;
|
|||||||
pub mod virt;
|
pub mod virt;
|
||||||
pub mod vault;
|
pub mod vault;
|
||||||
pub mod zinit_client;
|
pub mod zinit_client;
|
||||||
pub mod mycelium;
|
|
||||||
|
|
||||||
// Version information
|
// Version information
|
||||||
/// Returns the version of the SAL library
|
/// Returns the version of the SAL library
|
||||||
|
@ -1,300 +0,0 @@
|
|||||||
use base64::{
|
|
||||||
alphabet,
|
|
||||||
engine::{self, 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
|
|
||||||
/// * `deadline_secs` - The deadline in seconds
|
|
||||||
///
|
|
||||||
/// # 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,
|
|
||||||
deadline_secs: u64,
|
|
||||||
) -> Result<Value, String> {
|
|
||||||
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!({
|
|
||||||
"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
|
|
||||||
/// * `count` - The maximum number of messages to receive
|
|
||||||
///
|
|
||||||
/// # 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, count: u32) -> Result<Value, String> {
|
|
||||||
let client = Client::new();
|
|
||||||
let url = format!("{}/api/v1/messages", api_url);
|
|
||||||
|
|
||||||
let response = client
|
|
||||||
.get(&url)
|
|
||||||
.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)
|
|
||||||
}
|
|
@ -15,7 +15,6 @@ mod rfs;
|
|||||||
mod vault;
|
mod vault;
|
||||||
mod text;
|
mod text;
|
||||||
mod zinit;
|
mod zinit;
|
||||||
mod mycelium;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
@ -96,9 +95,6 @@ pub use git::register_git_module;
|
|||||||
// Re-export zinit module
|
// Re-export zinit module
|
||||||
pub use zinit::register_zinit_module;
|
pub use zinit::register_zinit_module;
|
||||||
|
|
||||||
// Re-export mycelium module
|
|
||||||
pub use mycelium::register_mycelium_module;
|
|
||||||
|
|
||||||
// Re-export text module
|
// Re-export text module
|
||||||
pub use text::register_text_module;
|
pub use text::register_text_module;
|
||||||
// Re-export text functions directly from text module
|
// Re-export text functions directly from text module
|
||||||
@ -159,9 +155,6 @@ pub fn register(engine: &mut Engine) -> Result<(), Box<rhai::EvalAltResult>> {
|
|||||||
// Register Zinit module functions
|
// Register Zinit module functions
|
||||||
zinit::register_zinit_module(engine)?;
|
zinit::register_zinit_module(engine)?;
|
||||||
|
|
||||||
// Register Mycelium module functions
|
|
||||||
mycelium::register_mycelium_module(engine)?;
|
|
||||||
|
|
||||||
// Register Text module functions
|
// Register Text module functions
|
||||||
text::register_text_module(engine)?;
|
text::register_text_module(engine)?;
|
||||||
|
|
||||||
|
@ -1,235 +0,0 @@
|
|||||||
//! Rhai wrappers for Mycelium client module functions
|
|
||||||
//!
|
|
||||||
//! This module provides Rhai wrappers for the functions in the Mycelium client module.
|
|
||||||
|
|
||||||
use rhai::{Engine, EvalAltResult, Array, Dynamic, Map};
|
|
||||||
use crate::mycelium as client;
|
|
||||||
use tokio::runtime::Runtime;
|
|
||||||
use serde_json::Value;
|
|
||||||
use crate::rhai::error::ToRhaiError;
|
|
||||||
|
|
||||||
/// Register Mycelium module functions with the Rhai engine
|
|
||||||
///
|
|
||||||
/// # Arguments
|
|
||||||
///
|
|
||||||
/// * `engine` - The Rhai engine to register the functions with
|
|
||||||
///
|
|
||||||
/// # Returns
|
|
||||||
///
|
|
||||||
/// * `Result<(), Box<EvalAltResult>>` - Ok if registration was successful, Err otherwise
|
|
||||||
pub fn register_mycelium_module(engine: &mut Engine) -> Result<(), Box<EvalAltResult>> {
|
|
||||||
// Register Mycelium client functions
|
|
||||||
engine.register_fn("mycelium_get_node_info", mycelium_get_node_info);
|
|
||||||
engine.register_fn("mycelium_list_peers", mycelium_list_peers);
|
|
||||||
engine.register_fn("mycelium_add_peer", mycelium_add_peer);
|
|
||||||
engine.register_fn("mycelium_remove_peer", mycelium_remove_peer);
|
|
||||||
engine.register_fn("mycelium_list_selected_routes", mycelium_list_selected_routes);
|
|
||||||
engine.register_fn("mycelium_list_fallback_routes", mycelium_list_fallback_routes);
|
|
||||||
engine.register_fn("mycelium_send_message", mycelium_send_message);
|
|
||||||
engine.register_fn("mycelium_receive_messages", mycelium_receive_messages);
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper function to get a runtime
|
|
||||||
fn get_runtime() -> Result<Runtime, Box<EvalAltResult>> {
|
|
||||||
tokio::runtime::Runtime::new().map_err(|e| {
|
|
||||||
Box::new(EvalAltResult::ErrorRuntime(
|
|
||||||
format!("Failed to create Tokio runtime: {}", e).into(),
|
|
||||||
rhai::Position::NONE
|
|
||||||
))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper function to convert serde_json::Value to rhai::Dynamic
|
|
||||||
fn value_to_dynamic(value: Value) -> Dynamic {
|
|
||||||
match value {
|
|
||||||
Value::Null => Dynamic::UNIT,
|
|
||||||
Value::Bool(b) => Dynamic::from(b),
|
|
||||||
Value::Number(n) => {
|
|
||||||
if let Some(i) = n.as_i64() {
|
|
||||||
Dynamic::from(i)
|
|
||||||
} else if let Some(f) = n.as_f64() {
|
|
||||||
Dynamic::from(f)
|
|
||||||
} else {
|
|
||||||
Dynamic::from(n.to_string())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Value::String(s) => Dynamic::from(s),
|
|
||||||
Value::Array(arr) => {
|
|
||||||
let mut rhai_arr = Array::new();
|
|
||||||
for item in arr {
|
|
||||||
rhai_arr.push(value_to_dynamic(item));
|
|
||||||
}
|
|
||||||
Dynamic::from(rhai_arr)
|
|
||||||
},
|
|
||||||
Value::Object(map) => {
|
|
||||||
let mut rhai_map = Map::new();
|
|
||||||
for (k, v) in map {
|
|
||||||
rhai_map.insert(k.into(), value_to_dynamic(v));
|
|
||||||
}
|
|
||||||
Dynamic::from_map(rhai_map)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Helper trait to convert String errors to Rhai errors
|
|
||||||
impl<T> ToRhaiError<T> for Result<T, String> {
|
|
||||||
fn to_rhai_error(self) -> Result<T, Box<EvalAltResult>> {
|
|
||||||
self.map_err(|e| {
|
|
||||||
Box::new(EvalAltResult::ErrorRuntime(
|
|
||||||
format!("Mycelium error: {}", e).into(),
|
|
||||||
rhai::Position::NONE
|
|
||||||
))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Mycelium Client Function Wrappers
|
|
||||||
//
|
|
||||||
|
|
||||||
/// Wrapper for mycelium::get_node_info
|
|
||||||
///
|
|
||||||
/// Gets information about the Mycelium node.
|
|
||||||
pub fn mycelium_get_node_info(api_url: &str) -> Result<Dynamic, Box<EvalAltResult>> {
|
|
||||||
let rt = get_runtime()?;
|
|
||||||
|
|
||||||
let result = rt.block_on(async {
|
|
||||||
client::get_node_info(api_url).await
|
|
||||||
});
|
|
||||||
|
|
||||||
let node_info = result.to_rhai_error()?;
|
|
||||||
|
|
||||||
Ok(value_to_dynamic(node_info))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wrapper for mycelium::list_peers
|
|
||||||
///
|
|
||||||
/// Lists all peers connected to the Mycelium node.
|
|
||||||
pub fn mycelium_list_peers(api_url: &str) -> Result<Dynamic, Box<EvalAltResult>> {
|
|
||||||
let rt = get_runtime()?;
|
|
||||||
|
|
||||||
let result = rt.block_on(async {
|
|
||||||
client::list_peers(api_url).await
|
|
||||||
});
|
|
||||||
|
|
||||||
let peers = result.to_rhai_error()?;
|
|
||||||
|
|
||||||
Ok(value_to_dynamic(peers))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wrapper for mycelium::add_peer
|
|
||||||
///
|
|
||||||
/// Adds a new peer to the Mycelium node.
|
|
||||||
pub fn mycelium_add_peer(api_url: &str, peer_address: &str) -> Result<Dynamic, Box<EvalAltResult>> {
|
|
||||||
let rt = get_runtime()?;
|
|
||||||
|
|
||||||
let result = rt.block_on(async {
|
|
||||||
client::add_peer(api_url, peer_address).await
|
|
||||||
});
|
|
||||||
|
|
||||||
let response = result.to_rhai_error()?;
|
|
||||||
|
|
||||||
Ok(value_to_dynamic(response))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wrapper for mycelium::remove_peer
|
|
||||||
///
|
|
||||||
/// Removes a peer from the Mycelium node.
|
|
||||||
pub fn mycelium_remove_peer(api_url: &str, peer_id: &str) -> Result<Dynamic, Box<EvalAltResult>> {
|
|
||||||
let rt = get_runtime()?;
|
|
||||||
|
|
||||||
let result = rt.block_on(async {
|
|
||||||
client::remove_peer(api_url, peer_id).await
|
|
||||||
});
|
|
||||||
|
|
||||||
let response = result.to_rhai_error()?;
|
|
||||||
|
|
||||||
Ok(value_to_dynamic(response))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wrapper for mycelium::list_selected_routes
|
|
||||||
///
|
|
||||||
/// Lists all selected routes in the Mycelium node.
|
|
||||||
pub fn mycelium_list_selected_routes(api_url: &str) -> Result<Dynamic, Box<EvalAltResult>> {
|
|
||||||
let rt = get_runtime()?;
|
|
||||||
|
|
||||||
let result = rt.block_on(async {
|
|
||||||
client::list_selected_routes(api_url).await
|
|
||||||
});
|
|
||||||
|
|
||||||
let routes = result.to_rhai_error()?;
|
|
||||||
|
|
||||||
Ok(value_to_dynamic(routes))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wrapper for mycelium::list_fallback_routes
|
|
||||||
///
|
|
||||||
/// Lists all fallback routes in the Mycelium node.
|
|
||||||
pub fn mycelium_list_fallback_routes(api_url: &str) -> Result<Dynamic, Box<EvalAltResult>> {
|
|
||||||
let rt = get_runtime()?;
|
|
||||||
|
|
||||||
let result = rt.block_on(async {
|
|
||||||
client::list_fallback_routes(api_url).await
|
|
||||||
});
|
|
||||||
|
|
||||||
let routes = result.to_rhai_error()?;
|
|
||||||
|
|
||||||
Ok(value_to_dynamic(routes))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wrapper for mycelium::send_message
|
|
||||||
///
|
|
||||||
/// Sends a message to a destination via the Mycelium node.
|
|
||||||
pub fn mycelium_send_message(api_url: &str, destination: &str, topic: &str, message: &str, deadline_secs: i64) -> Result<Dynamic, Box<EvalAltResult>> {
|
|
||||||
let rt = get_runtime()?;
|
|
||||||
|
|
||||||
// Convert deadline to u64
|
|
||||||
let deadline = if deadline_secs < 0 {
|
|
||||||
return Err(Box::new(EvalAltResult::ErrorRuntime(
|
|
||||||
"Deadline cannot be negative".into(),
|
|
||||||
rhai::Position::NONE
|
|
||||||
)));
|
|
||||||
} else {
|
|
||||||
deadline_secs as u64
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = rt.block_on(async {
|
|
||||||
client::send_message(api_url, destination, topic, message, deadline).await
|
|
||||||
});
|
|
||||||
|
|
||||||
let response = result.to_rhai_error()?;
|
|
||||||
|
|
||||||
Ok(value_to_dynamic(response))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wrapper for mycelium::receive_messages
|
|
||||||
///
|
|
||||||
/// Receives messages from a topic via the Mycelium node.
|
|
||||||
pub fn mycelium_receive_messages(api_url: &str, topic: &str, count: i64) -> Result<Dynamic, Box<EvalAltResult>> {
|
|
||||||
let rt = get_runtime()?;
|
|
||||||
|
|
||||||
// Convert count to u32
|
|
||||||
let count = if count < 0 {
|
|
||||||
return Err(Box::new(EvalAltResult::ErrorRuntime(
|
|
||||||
"Count cannot be negative".into(),
|
|
||||||
rhai::Position::NONE
|
|
||||||
)));
|
|
||||||
} else if count > u32::MAX as i64 {
|
|
||||||
return Err(Box::new(EvalAltResult::ErrorRuntime(
|
|
||||||
format!("Count too large, maximum is {}", u32::MAX).into(),
|
|
||||||
rhai::Position::NONE
|
|
||||||
)));
|
|
||||||
} else {
|
|
||||||
count as u32
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = rt.block_on(async {
|
|
||||||
client::receive_messages(api_url, topic, count).await
|
|
||||||
});
|
|
||||||
|
|
||||||
let messages = result.to_rhai_error()?;
|
|
||||||
|
|
||||||
Ok(value_to_dynamic(messages))
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user