So looks like there's no RPC client ATM which supports no_std
.
the following is the implementation of an RPC method using sp_runtime::offchain::http::Request
and serde
:
use serde::{Deserialize, Serialize};
use scale_info::prelude::string::String;
use sp_runtime::{
offchain::{
http::Request,
Duration,
},
};
#[derive(Serialize, Deserialize, Clone)]
struct RpcObject {
jsonrpc: String,
method: String,
params: String, // could be a nested object
id: String
}
#[derive(Serialize, Deserialize, Clone)]
struct RpcResponse {
result: String,
id: String
}
fn call_rpc_method(url: &str, method: String, params: String) -> Result<Vec<u8>, Error<T>> {
let request_body = RpcObject {
jsonrpc: String::from("2.0"),
method: method.into(),
params: params.into(),
id: String::from("1")
};
let request_body_str = serde_json::to_string(&request_body).map_err(|_| <Error<T>>::Error)?;
let request = Request::post(url, vec![request_body_str.clone()])
.add_header("content-type", "application/json");
let timeout = sp_io::offchain::timestamp()
.add(Duration::from_millis(FETCH_TIMEOUT_PERIOD));
let pending = request
.deadline(timeout)
.body(vec![request_body_str.clone()])
.send() // Sending the request out by the host
.map_err(|e| {
log::error!("rpc request err: {:?}", e);
<Error<T>>::Error
})?;
let response = pending
.try_wait(timeout)
.map_err(|e| {
log::error!("rpc error: {:?}", e);
<Error<T>>::HttpFetchingError
})?
.map_err(|e| {
log::error!("rpc error: {:?}", e);
<Error<T>>::HttpFetchingError
})?;
if response.code != 200 {
log::error!("Unexpected http request status code: {}", response.code);
return Err(<Error<T>>::HttpFetchingError);
}
// Next we fully read the response body and collect it to a vector of bytes.
let resp_bytes = response.body().collect::<Vec<u8>>();
Ok(resp_bytes)
}
next you can use the response like:
let resut: RpcResponse = serde_json::from_slice(&res)
.map_err(|e| {
log::info!("deserialize error: {:?}", e);
<Error<T>>::DeserializeToObjError
})?;