use crate::serialization;
use crate::serialization::Encoding;
use crate::RPCRequest;
use crate::{config::LotusConfig, types::api::Rs};
use reqwest::{Client, RequestBuilder};
use serde_json::{json, Value};
use std::fmt::Debug;
#[derive(Debug, Clone)]
pub struct LotusClient {
config: LotusConfig,
client: Client,
}
impl<'de> LotusClient {
pub fn init(config: LotusConfig) -> LotusClient {
LotusClient {
config,
client: reqwest::Client::new(),
}
}
pub fn build(&self) -> RequestBuilder {
let request_builder = self
.client
.post(self.config.host_url.to_string())
.header("Content-Type", self.config.content_type.to_string());
if !&self.config.token.is_empty() {
request_builder.bearer_auth(self.config.token.to_string())
} else {
request_builder
}
}
pub fn format<T: serde::Serialize>(&self, method: String, val: T) -> RPCRequest {
RPCRequest {
jsonrpc: "2.0".to_string(),
method,
id: 1,
params: json!(val),
}
}
pub async fn send<Res: serde::de::DeserializeOwned>(
&self,
method: String,
data: Vec<Value>,
) -> anyhow::Result<Res> {
let response = self
.build()
.json(&self.format(format!("Filecoin.{}", method).to_string(), &data))
.send()
.await?;
let encoding = response.encoding();
let bytes = response.bytes().await?;
let trace_body = |error| {
let text_body = serialization::deserialize_text(&bytes, encoding);
tracing::error!(
"Invalid body: {}",
if text_body.is_empty() {
"<empty-body>".to_string()
} else {
text_body
}
);
error
};
let json_response =
serialization::deserialize_json::<Rs<Res>>(&bytes).map_err(trace_body)?;
Ok(json_response.result)
}
}