use super::*;
use constants::*;
use serde_json::Value;
use std::collections::HashMap;
use std::num::Wrapping;
use bytes::buf::BufExt as _;
use crate::responses::ApiResponse;
use serde::{Serialize, de::DeserializeOwned};
use hyper::{Body, body, Request, client::ResponseFuture};
use http::{Uri, request::Builder, header::CONTENT_TYPE};
#[derive(Serialize, Debug, Clone)]
pub struct ApiRequest {
pub jsonrpc: &'static str,
pub id: Wrapping<usize>,
pub method: String,
pub params: HashMap<String, Value>
}
impl ApiRequest {
pub fn new(method: &str) -> ApiRequest {
ApiRequest {
jsonrpc: JSONRPC,
id: Wrapping(ID),
method: method.to_string(),
params: HashMap::new()
}
}
pub fn json(self) -> String {
serde_json::to_string(&self).expect("Serializing json")
}
pub fn builder(uri: &Uri) -> Builder {
let req = Request::builder()
.method("POST")
.header(CONTENT_TYPE, "application/json")
.uri(uri);
req
}
}
pub async fn factomd_call(api: &Factom, req: ApiRequest) -> ResponseFuture {
inner_call(api, &api.factomd_uri, req).await
}
pub async fn walletd_call(api: &Factom, req: ApiRequest) -> ResponseFuture {
inner_call(api, &api.walletd_uri, req).await
}
pub async fn debug_call(api: &Factom, req: ApiRequest) -> ResponseFuture {
inner_call(api, &api.debug_uri, req).await
}
async fn inner_call(
api: &Factom,
uri: &Rc<Uri>,
req: ApiRequest
) -> ResponseFuture
{
let json = Body::from(req.json());
let builder = ApiRequest::builder(&uri);
let payload = builder.body(json)
.expect("Constructing request body");
api.client.request(payload)
}
pub async fn parse<T>(fut: ResponseFuture) -> Result<ApiResponse<T>>
where T: DeserializeOwned + Default
{
let res = fut.await?;
let body = body::aggregate(res.into_body())
.await
.expect("Parsing response body");
let res: ApiResponse<T> =serde_json::from_reader(body.reader())
.expect("Deserialising JSON");
Ok(res)
}
#[cfg(feature="default")]
pub fn fetch<F: Future>(query: F) -> F::Output {
let mut rt = Runtime::new().expect("Initialising Runtime");
rt.block_on(query)
}