crate::ix!();
pub fn parse_non_rfcjson_value(str_val: &str) -> Result<UniValue,StdException> {
let mut j_val = UniValue::default();
let msg = format!("[{}]", str_val);
if !j_val.read(msg.as_ptr() as *const u8, msg.len())
|| !j_val.is_array()
|| j_val.size() != 1 {
let msg = format!("Error parsing JSON: {}", str_val);
return Err(runtime_error(&msg));
}
Ok(j_val[0].clone())
}
pub fn rpc_convert_values(
str_method: &str,
str_params: &Vec<String>) -> UniValue {
let mut params: UniValue = UniValue::from(uni_value::VType::VARR);
for idx in 0..str_params.len() {
let str_val: &str = &str_params[idx];
if !RPC_CVT_TABLE
.lock()
.convert_with_method_and_idx(
str_method,
idx.try_into().unwrap()
)
{
params.push_back(str_val);
} else {
params.push_back(&parse_non_rfcjson_value(str_val));
}
}
params
}
pub fn rpc_convert_named_values(
str_method: &str,
str_params: &Vec<String>) -> Result<UniValue,StdException> {
let mut params: UniValue
= UniValue::from(uni_value::VType::VOBJ);
for s in str_params.iter() {
if let Some(pos) = s.find('=') {
let name: String = s[0..pos].to_string();
let value: String = s[pos + 1..].to_string();
if !RPC_CVT_TABLE
.lock()
.convert_with_method_and_name(str_method, &name)
{
params.pushkv(name, value);
} else {
params.pushkv(name, parse_non_rfcjson_value(&value));
}
} else {
let msg = format!{
"No '=' in named argument '{}', this needs to be present for every argument (even if it is empty)",
s
};
return Err(runtime_error(&msg));
}
}
Ok(params)
}
pub trait BaseRequestHandler {
fn prepare_request(&mut self,
method: &str,
args: &Vec<String>) -> Result<UniValue,StdException>;
fn process_reply(&mut self, batch_in: &UniValue) -> Result<UniValue,StdException>;
}
#[derive(Default)]
pub struct AddrinfoRequestHandler {
}
impl BaseRequestHandler for AddrinfoRequestHandler {
fn prepare_request(&mut self,
method: &str,
args: &Vec<String>) -> Result<UniValue,StdException> {
if !args.is_empty() {
return Err(runtime_error("-addrinfo takes no arguments"));
}
let params: UniValue = {
let params = vec!["0".to_string()];
rpc_convert_values("getnodeaddresses",¶ms)
};
let result = jsonrpc_request_obj(
"getnodeaddresses",
¶ms,
&UniValue::from(1_i32)
);
Ok(result)
}
fn process_reply(&mut self, reply: &UniValue) -> Result<UniValue,StdException> {
if !reply["error"].is_null() {
return Ok(reply.clone());
}
let nodes: &Vec::<UniValue>
= reply["result"]
.get_values()
.unwrap();
if !nodes.is_empty() && nodes[0]["network"].is_null() {
return Err(runtime_error("-addrinfo requires bitcoind server to be running v22.0 and up"));
}
todo!();
let mut counts: Vec<u64> = Vec::with_capacity(NETINFO_REQUEST_HANDLER_NETWORKS.len());
for node in nodes.iter() {
let network_name: String = String::from(node["network"].get_str());
let network_id: i8 = self.network_string_to_id(&network_name);
if network_id == UNKNOWN_NETWORK {
continue;
}
let idx: usize = network_id.try_into().unwrap();
counts[idx] += 1;
}
let result: UniValue = UniValue::from(uni_value::VType::VOBJ);;
let addresses: UniValue = UniValue::from(uni_value::VType::VOBJ);;
let total: u64 = 0;
for i in 0..NETINFO_REQUEST_HANDLER_NETWORKS.len() {
addresses.pushkv(
NETINFO_REQUEST_HANDLER_NETWORKS[i],
counts[i]
);
total += counts[i];
}
addresses.pushkv("total", total);
result.pushkv("addresses_known", ADDRESSES);
Ok(
jsonrpc_reply_obj(
&result,
&NULL_UNI_VALUE,
&UniValue::from(1_i32)
)
)
}
}