125 lines
4.4 KiB
Rust
125 lines
4.4 KiB
Rust
use std::path::PathBuf;
|
|
|
|
use anyhow::Result;
|
|
use clap::Parser;
|
|
use jsonrpsee::core::client::ClientT;
|
|
use jsonrpsee::rpc_params;
|
|
use reth_ipc::client::IpcClientBuilder;
|
|
use serde_json::Value;
|
|
use tracing_subscriber::EnvFilter;
|
|
|
|
/// Simple IPC (Unix socket) JSON-RPC client for manual testing.
|
|
///
|
|
/// Examples:
|
|
/// - Call method without params:
|
|
/// hero-client-unix --socket /tmp/baobab.ipc --method whoami
|
|
///
|
|
/// - Call method with positional params (as JSON array):
|
|
/// hero-client-unix --socket /tmp/baobab.ipc --method authenticate --params '["pubkey","signature","nonce"]'
|
|
///
|
|
/// - Call method with single object param:
|
|
/// hero-client-unix --socket /tmp/baobab.ipc --method create_job --params '{"job_id":"abc"}'
|
|
#[derive(Parser, Debug)]
|
|
#[command(name = "hero-client-unix", version, about = "IPC JSON-RPC client")]
|
|
struct Args {
|
|
/// Filesystem path to the Unix domain socket
|
|
#[arg(long, default_value = "/tmp/baobab.ipc", env = "HERO_IPC_SOCKET")]
|
|
socket: PathBuf,
|
|
|
|
/// JSON-RPC method name to call
|
|
#[arg(long)]
|
|
method: String,
|
|
|
|
/// JSON string for params. Either an array for positional params or an object for named params.
|
|
/// Defaults to [] (no params).
|
|
#[arg(long, default_value = "[]")]
|
|
params: String,
|
|
|
|
/// Log filter (e.g., info, debug, trace)
|
|
#[arg(long, default_value = "info", env = "RUST_LOG")]
|
|
log: String,
|
|
}
|
|
|
|
#[tokio::main]
|
|
async fn main() -> Result<()> {
|
|
let args = Args::parse();
|
|
|
|
tracing_subscriber::FmtSubscriber::builder()
|
|
.with_env_filter(EnvFilter::new(args.log.clone()))
|
|
.try_init()
|
|
.expect("setting default subscriber failed");
|
|
|
|
let socket_str = args.socket.to_string_lossy().to_string();
|
|
let client = IpcClientBuilder::default().build(&socket_str).await?;
|
|
|
|
let params_value: Value = serde_json::from_str(&args.params)?;
|
|
|
|
// We deserialize responses to serde_json::Value for generality.
|
|
// You can set a concrete type instead if needed.
|
|
let result: Value = match params_value {
|
|
Value::Array(arr) => match arr.len() {
|
|
0 => client.request(&args.method, rpc_params![]).await?,
|
|
1 => client.request(&args.method, rpc_params![arr[0].clone()]).await?,
|
|
2 => client.request(&args.method, rpc_params![arr[0].clone(), arr[1].clone()]).await?,
|
|
3 => client
|
|
.request(&args.method, rpc_params![arr[0].clone(), arr[1].clone(), arr[2].clone()])
|
|
.await?,
|
|
4 => client
|
|
.request(
|
|
&args.method,
|
|
rpc_params![arr[0].clone(), arr[1].clone(), arr[2].clone(), arr[3].clone()],
|
|
)
|
|
.await?,
|
|
5 => client
|
|
.request(
|
|
&args.method,
|
|
rpc_params![
|
|
arr[0].clone(),
|
|
arr[1].clone(),
|
|
arr[2].clone(),
|
|
arr[3].clone(),
|
|
arr[4].clone()
|
|
],
|
|
)
|
|
.await?,
|
|
6 => client
|
|
.request(
|
|
&args.method,
|
|
rpc_params![
|
|
arr[0].clone(),
|
|
arr[1].clone(),
|
|
arr[2].clone(),
|
|
arr[3].clone(),
|
|
arr[4].clone(),
|
|
arr[5].clone()
|
|
],
|
|
)
|
|
.await?,
|
|
7 => client
|
|
.request(
|
|
&args.method,
|
|
rpc_params![
|
|
arr[0].clone(),
|
|
arr[1].clone(),
|
|
arr[2].clone(),
|
|
arr[3].clone(),
|
|
arr[4].clone(),
|
|
arr[5].clone(),
|
|
arr[6].clone()
|
|
],
|
|
)
|
|
.await?,
|
|
_ => {
|
|
// Fallback: send entire array as a single param to avoid combinatorial explosion.
|
|
// Adjust if your server expects strictly positional expansion beyond 7 items.
|
|
client.request(&args.method, rpc_params![Value::Array(arr)]).await?
|
|
}
|
|
},
|
|
// Single non-array param (object, string, number, etc.)
|
|
other => client.request(&args.method, rpc_params![other]).await?,
|
|
};
|
|
|
|
println!("{}", serde_json::to_string_pretty(&result)?);
|
|
Ok(())
|
|
}
|