mucelium client needs to be in wrapper #10

Open
opened 2026-04-05 18:19:00 +00:00 by despiegk · 4 comments
Owner

/Volumes/T7/code0/hero_lib/crates/clients/src/mycelium

do with factory

client = mycelium_client_factory()

default is to the local mycelium

image

when client cannot connect it gives error

put all features in nice format in a rhai wrapper

put in /Volumes/T7/code0/hero_lib_rhai/crates/clients_rhai/src

/Volumes/T7/code0/hero_lib/crates/clients/src/mycelium do with factory client = mycelium_client_factory() default is to the local mycelium ![image](/attachments/d76b4fd0-07f3-496c-a2dd-58895744c3f0) when client cannot connect it gives error put all features in nice format in a rhai wrapper put in /Volumes/T7/code0/hero_lib_rhai/crates/clients_rhai/src
152 KiB
Author
Owner

Implementation Spec for Issue #10 — Mycelium Client Rhai Wrapper (Factory Pattern)

Objective

Rewrite crates/clients_rhai/src/mycelium.rs to follow the factory pattern used by acp.rs and mqtt.rs: expose a mycelium_client_factory() function that returns a MyceliumClient struct. The client connects to the local Mycelium node by default (http://localhost:8990). Connection failure produces a clear Rhai runtime error. All API surface from the typed MyceliumJSONRPCAPIClient (the OpenRPC-generated client) is wrapped, including the REST-layer functions from client.rs that have no JSON-RPC equivalent (send_message, receive_messages).

Requirements

  • Replace the current global-URL + bare-function design with a MyceliumClient struct registered as a Rhai custom type.
  • Provide mycelium_client_factory() (no args — connects to http://localhost:8990) and mycelium_client_factory(url) (one-arg overload) as the entry points.
  • Connection failure inside the factory must propagate as a Rhai runtime error.
  • Wrap every typed JSON-RPC method: get_info, get_peers, add_peer, delete_peer, get_selected_routes, get_fallback_routes, get_public_key_from_ip, get_proxies, connect_proxy, disconnect_proxy.
  • Also wrap the HTTP-REST functions: send_message and receive_messages.
  • All methods return typed Rhai-friendly values: Map for structured objects, Array of Map for lists.
  • Every function and method must have a doc comment with a # Example block in Rhai syntax.
  • Use thread_local! + Arc<Runtime> for the Tokio runtime.
  • Remove all global mutable state (MYCELIUM_URL static). URL lives on the MyceliumClient struct.
  • No new crate dependencies are needed.

Files to Modify

File Action
crates/clients_rhai/src/mycelium.rs Rewrite with factory pattern
crates/clients_rhai/src/lib.rs No change
crates/clients_rhai/Cargo.toml No change

Implementation Plan

Step 1: Rewrite mycelium.rs — struct, factory, and thread-local runtime

  • Define MyceliumClient struct with Arc<TokioMutex<MyceliumJSONRPCAPIClient>> and rest_url: String
  • Add mycelium_client_factory() (no-args, defaults to http://localhost:8990)
  • Add mycelium_client_factory(url: String) (custom URL overload)
  • Add thread_local! runtime helper

Step 2: Implement node info and peer methods

  • get_info() → Map with node_pubkey, node_subnet
  • get_peers() → Array of Maps
  • add_peer(endpoint: String) → bool
  • delete_peer(endpoint: String) → bool

Step 3: Implement route and proxy methods

  • get_selected_routes() → Array
  • get_fallback_routes() → Array
  • get_public_key_from_ip(ip: String) → String
  • get_proxies() → Array
  • connect_proxy(remote: String) → String
  • disconnect_proxy() → bool

Step 4: Implement REST messaging methods

  • send_message(dst, topic, msg, deadline_secs) → Dynamic
  • receive_messages(topic, deadline_secs) → Dynamic

Step 5: Implement register_mycelium_module and register all methods

Acceptance Criteria

  • mycelium_client_factory() (no args) connects to http://localhost:8990
  • mycelium_client_factory(url) connects to custom URL
  • Both factory overloads return a clear Rhai error if unreachable
  • All 10 JSON-RPC methods wrapped and registered
  • send_message and receive_messages wrapped via REST client
  • Every public function has a doc comment with # Example block
  • Crate compiles with --features mycelium and --features full
  • lib.rs and Cargo.toml remain unchanged

Rhai Usage Example

let client = mycelium_client_factory();

let info = client.get_info();
print(`Node pubkey: ${info.node_pubkey}`);
print(`Node subnet: ${info.node_subnet}`);

let peers = client.get_peers();
for peer in peers { print(peer); }

client.add_peer("tcp://1.2.3.4:9651");

let routes = client.get_selected_routes();
let key = client.get_public_key_from_ip("5dd:f821::1");

client.send_message("5dd:f821::1", "my-topic", "hello", -1);
let msgs = client.receive_messages("my-topic", 5);
# Implementation Spec for Issue #10 — Mycelium Client Rhai Wrapper (Factory Pattern) ## Objective Rewrite `crates/clients_rhai/src/mycelium.rs` to follow the factory pattern used by `acp.rs` and `mqtt.rs`: expose a `mycelium_client_factory()` function that returns a `MyceliumClient` struct. The client connects to the local Mycelium node by default (`http://localhost:8990`). Connection failure produces a clear Rhai runtime error. All API surface from the typed `MyceliumJSONRPCAPIClient` (the OpenRPC-generated client) is wrapped, including the REST-layer functions from `client.rs` that have no JSON-RPC equivalent (`send_message`, `receive_messages`). ## Requirements - Replace the current global-URL + bare-function design with a `MyceliumClient` struct registered as a Rhai custom type. - Provide `mycelium_client_factory()` (no args — connects to `http://localhost:8990`) and `mycelium_client_factory(url)` (one-arg overload) as the entry points. - Connection failure inside the factory must propagate as a Rhai runtime error. - Wrap every typed JSON-RPC method: `get_info`, `get_peers`, `add_peer`, `delete_peer`, `get_selected_routes`, `get_fallback_routes`, `get_public_key_from_ip`, `get_proxies`, `connect_proxy`, `disconnect_proxy`. - Also wrap the HTTP-REST functions: `send_message` and `receive_messages`. - All methods return typed Rhai-friendly values: `Map` for structured objects, `Array` of `Map` for lists. - Every function and method must have a doc comment with a `# Example` block in Rhai syntax. - Use `thread_local!` + `Arc<Runtime>` for the Tokio runtime. - Remove all global mutable state (`MYCELIUM_URL` static). URL lives on the `MyceliumClient` struct. - No new crate dependencies are needed. ## Files to Modify | File | Action | |---|---| | `crates/clients_rhai/src/mycelium.rs` | **Rewrite** with factory pattern | | `crates/clients_rhai/src/lib.rs` | **No change** | | `crates/clients_rhai/Cargo.toml` | **No change** | ## Implementation Plan ### Step 1: Rewrite `mycelium.rs` — struct, factory, and thread-local runtime - Define `MyceliumClient` struct with `Arc<TokioMutex<MyceliumJSONRPCAPIClient>>` and `rest_url: String` - Add `mycelium_client_factory()` (no-args, defaults to `http://localhost:8990`) - Add `mycelium_client_factory(url: String)` (custom URL overload) - Add `thread_local!` runtime helper ### Step 2: Implement node info and peer methods - `get_info()` → Map with `node_pubkey`, `node_subnet` - `get_peers()` → Array of Maps - `add_peer(endpoint: String)` → bool - `delete_peer(endpoint: String)` → bool ### Step 3: Implement route and proxy methods - `get_selected_routes()` → Array - `get_fallback_routes()` → Array - `get_public_key_from_ip(ip: String)` → String - `get_proxies()` → Array - `connect_proxy(remote: String)` → String - `disconnect_proxy()` → bool ### Step 4: Implement REST messaging methods - `send_message(dst, topic, msg, deadline_secs)` → Dynamic - `receive_messages(topic, deadline_secs)` → Dynamic ### Step 5: Implement `register_mycelium_module` and register all methods ## Acceptance Criteria - [ ] `mycelium_client_factory()` (no args) connects to `http://localhost:8990` - [ ] `mycelium_client_factory(url)` connects to custom URL - [ ] Both factory overloads return a clear Rhai error if unreachable - [ ] All 10 JSON-RPC methods wrapped and registered - [ ] `send_message` and `receive_messages` wrapped via REST client - [ ] Every public function has a doc comment with `# Example` block - [ ] Crate compiles with `--features mycelium` and `--features full` - [ ] `lib.rs` and `Cargo.toml` remain unchanged ## Rhai Usage Example ```rhai let client = mycelium_client_factory(); let info = client.get_info(); print(`Node pubkey: ${info.node_pubkey}`); print(`Node subnet: ${info.node_subnet}`); let peers = client.get_peers(); for peer in peers { print(peer); } client.add_peer("tcp://1.2.3.4:9651"); let routes = client.get_selected_routes(); let key = client.get_public_key_from_ip("5dd:f821::1"); client.send_message("5dd:f821::1", "my-topic", "hello", -1); let msgs = client.receive_messages("my-topic", 5); ```
Author
Owner

Test Results

herolib_clients_rhai crate

  • Total: 0
  • Passed: 0
  • Failed: 0

Note: The crate currently has no unit tests or doc-tests defined. Both the lib test harness and the doc-test harness ran successfully with 0 tests each. Build compiled cleanly with only a minor warning about an unused engine parameter in register_clients_module.

Workspace (full cargo test)

  • Total: 113 (across all crates)
  • Passed: 108
  • Failed: 0
  • Ignored: 5 (4 doc-tests in herolib_crypt_rhai, 1 in herolib_vault_rhai)

All crates that have tests passed:

  • herolib_core — 10 passed
  • herolib_crypt — 2 passed
  • herolib_crypt_rhai — 11 passed
  • herolib_os — 3 passed
  • herolib_clients — 8 passed
  • herolib_vault — 7 passed
  • herolib_vault_rhai — 1 passed
  • herolib_do — 29 passed
  • herolib_tools_rhai — 8 passed
  • herolib_do (doc-test) — 29 passed + 1 passed

No failures or regressions detected in the workspace.

Build status: SUCCESS

## Test Results ### `herolib_clients_rhai` crate - Total: 0 - Passed: 0 - Failed: 0 > Note: The crate currently has no unit tests or doc-tests defined. Both the lib test harness and the doc-test harness ran successfully with 0 tests each. Build compiled cleanly with only a minor warning about an unused `engine` parameter in `register_clients_module`. ### Workspace (full `cargo test`) - Total: 113 (across all crates) - Passed: 108 - Failed: 0 - Ignored: 5 (4 doc-tests in `herolib_crypt_rhai`, 1 in `herolib_vault_rhai`) All crates that have tests passed: - `herolib_core` — 10 passed - `herolib_crypt` — 2 passed - `herolib_crypt_rhai` — 11 passed - `herolib_os` — 3 passed - `herolib_clients` — 8 passed - `herolib_vault` — 7 passed - `herolib_vault_rhai` — 1 passed - `herolib_do` — 29 passed - `herolib_tools_rhai` — 8 passed - `herolib_do` (doc-test) — 29 passed + 1 passed No failures or regressions detected in the workspace. Build status: ✅ SUCCESS
Author
Owner

Implementation Complete

Changes Made

File modified: crates/clients_rhai/src/mycelium.rs (complete rewrite)

The Mycelium client Rhai wrapper has been rewritten to follow the factory pattern.

Key changes:

  • Added MyceliumClient struct (holds Arc<TokioMutex<MyceliumJSONRPCAPIClient>> + rest_url)
  • Added factory functions registered as mycelium_client_factory() (no args, defaults to http://localhost:8990) and mycelium_client_factory(url) (custom URL overload)
  • Connection failure returns a clear Rhai runtime error
  • Removed all global mutable state (old MYCELIUM_URL static)
  • Used thread-local Tokio runtime helper for efficiency
  • Wrapped all 10 JSON-RPC methods as Rhai methods: get_info, get_peers, add_peer, delete_peer, get_selected_routes, get_fallback_routes, get_public_key_from_ip, get_proxies, connect_proxy, disconnect_proxy
  • Wrapped REST messaging methods: send_message, receive_messages
  • All functions have doc comments with Rhai # Example blocks
  • lib.rs and Cargo.toml unchanged — no new dependencies

Files unchanged: lib.rs, Cargo.toml

Test Results

  • Workspace: 108/108 tests passed (5 ignored by design)
  • herolib_clients_rhai crate: builds cleanly, 0 failures
  • No regressions detected

Rhai Usage

let client = mycelium_client_factory();

let info = client.get_info();
print(`Node pubkey: ${info.node_pubkey}`);
print(`Node subnet: ${info.node_subnet}`);

let peers = client.get_peers();
for peer in peers { print(peer); }

client.add_peer("tcp://1.2.3.4:9651");
client.delete_peer("tcp://1.2.3.4:9651");

let routes = client.get_selected_routes();
let key = client.get_public_key_from_ip("5dd:f821::1");

client.send_message("5dd:f821::1", "my-topic", "hello", -1);
let msgs = client.receive_messages("my-topic", 5);
## Implementation Complete ✅ ### Changes Made **File modified:** `crates/clients_rhai/src/mycelium.rs` (complete rewrite) The Mycelium client Rhai wrapper has been rewritten to follow the factory pattern. **Key changes:** - Added `MyceliumClient` struct (holds `Arc<TokioMutex<MyceliumJSONRPCAPIClient>>` + `rest_url`) - Added factory functions registered as `mycelium_client_factory()` (no args, defaults to `http://localhost:8990`) and `mycelium_client_factory(url)` (custom URL overload) - Connection failure returns a clear Rhai runtime error - Removed all global mutable state (old `MYCELIUM_URL` static) - Used thread-local Tokio runtime helper for efficiency - Wrapped all 10 JSON-RPC methods as Rhai methods: `get_info`, `get_peers`, `add_peer`, `delete_peer`, `get_selected_routes`, `get_fallback_routes`, `get_public_key_from_ip`, `get_proxies`, `connect_proxy`, `disconnect_proxy` - Wrapped REST messaging methods: `send_message`, `receive_messages` - All functions have doc comments with Rhai `# Example` blocks - `lib.rs` and `Cargo.toml` unchanged — no new dependencies **Files unchanged:** `lib.rs`, `Cargo.toml` ### Test Results - Workspace: 108/108 tests passed (5 ignored by design) - `herolib_clients_rhai` crate: builds cleanly, 0 failures - No regressions detected ### Rhai Usage ```rhai let client = mycelium_client_factory(); let info = client.get_info(); print(`Node pubkey: ${info.node_pubkey}`); print(`Node subnet: ${info.node_subnet}`); let peers = client.get_peers(); for peer in peers { print(peer); } client.add_peer("tcp://1.2.3.4:9651"); client.delete_peer("tcp://1.2.3.4:9651"); let routes = client.get_selected_routes(); let key = client.get_public_key_from_ip("5dd:f821::1"); client.send_message("5dd:f821::1", "my-topic", "hello", -1); let msgs = client.receive_messages("my-topic", 5); ```
Author
Owner

Implementation committed: b4790da

Browse: b4790da

Implementation committed: `b4790da` Browse: https://forge.ourworld.tf/lhumina_code/hero_lib_rhai/commit/b4790da
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lhumina_code/hero_lib_rhai#10
No description provided.