use ethers::core::types::U256;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::fmt;
use thiserror::Error;
#[derive(Serialize, Deserialize, Debug, Clone, Error)]
pub struct JsonRpcError {
pub code: i64,
pub message: String,
pub data: Option<Value>,
}
impl fmt::Display for JsonRpcError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"(code: {}, message: {}, data: {:?})",
self.code, self.message, self.data
)
}
}
fn is_zst<T>(_t: &T) -> bool {
std::mem::size_of::<T>() == 0
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Request<'a, T> {
id: u64,
jsonrpc: &'a str,
method: &'a str,
#[serde(skip_serializing_if = "is_zst")]
params: T,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Notification<R> {
jsonrpc: String,
method: String,
pub params: Subscription<R>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct Subscription<R> {
pub subscription: U256,
pub result: R,
}
impl<'a, T> Request<'a, T> {
pub fn new(id: u64, method: &'a str, params: T) -> Self {
Self {
id,
jsonrpc: "2.0",
method,
params,
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Response<T> {
pub(crate) id: u64,
jsonrpc: String,
#[serde(flatten)]
pub data: ResponseData<T>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(untagged)]
pub enum ResponseData<R> {
Error { error: JsonRpcError },
Success { result: Option<R> },
}
impl<R> ResponseData<R> {
pub fn into_result(self) -> Result<Option<R>, JsonRpcError> {
match self {
ResponseData::Success { result } => Ok(result),
ResponseData::Error { error } => Err(error),
}
}
}