avalanche_types/jsonrpc/
common.rs

1//! Common JSON-RPC types.
2// Copied from <https://github.com/gakonst/ethers-rs/blob/master/ethers-providers/src/transports/common.rs>.
3// Remove once is <https://github.com/gakonst/ethers-rs/issues/1997> resolved.
4use std::fmt;
5
6use ethers_core::types::U256;
7use serde::{Deserialize, Serialize};
8use serde_json::Value;
9use thiserror::Error;
10
11#[derive(Serialize, Deserialize, Debug, Clone, Error)]
12/// A JSON-RPC 2.0 error
13pub struct JsonRpcError {
14    /// The error code
15    pub code: i64,
16    /// The error message
17    pub message: String,
18    /// Additional data
19    pub data: Option<Value>,
20}
21
22impl fmt::Display for JsonRpcError {
23    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24        write!(
25            f,
26            "(code: {}, message: {}, data: {:?})",
27            self.code, self.message, self.data
28        )
29    }
30}
31
32fn is_zst<T>(_t: &T) -> bool {
33    std::mem::size_of::<T>() == 0
34}
35
36#[derive(Serialize, Deserialize, Debug)]
37/// A JSON-RPC request
38pub struct Request<'a, T> {
39    pub id: u64,
40    pub jsonrpc: &'a str,
41    pub method: &'a str,
42    #[serde(skip_serializing_if = "is_zst")]
43    pub params: T,
44}
45
46#[derive(Serialize, Deserialize, Debug)]
47/// A JSON-RPC Notifcation
48pub struct Notification<R> {
49    jsonrpc: String,
50    method: String,
51    pub params: Subscription<R>,
52}
53
54#[derive(Serialize, Deserialize, Debug)]
55pub struct Subscription<R> {
56    pub subscription: U256,
57    pub result: R,
58}
59
60impl<'a, T> Request<'a, T> {
61    /// Creates a new JSON RPC request
62    pub fn new(id: u64, method: &'a str, params: T) -> Self {
63        Self {
64            id,
65            jsonrpc: "2.0",
66            method,
67            params,
68        }
69    }
70}
71
72#[derive(Serialize, Deserialize, Debug, Clone)]
73pub struct Response<T> {
74    pub(crate) id: u64,
75    jsonrpc: String,
76    #[serde(flatten)]
77    pub data: ResponseData<T>,
78}
79
80#[derive(Serialize, Deserialize, Debug, Clone)]
81#[serde(untagged)]
82pub enum ResponseData<R> {
83    Error { error: JsonRpcError },
84    Success { result: R },
85}
86
87impl<R> ResponseData<R> {
88    /// Consume response and return value
89    pub fn into_result(self) -> Result<R, JsonRpcError> {
90        match self {
91            ResponseData::Success { result } => Ok(result),
92            ResponseData::Error { error } => Err(error),
93        }
94    }
95}
96
97#[cfg(test)]
98mod tests {
99    use super::*;
100
101    #[test]
102    fn deser_response() {
103        let response: Response<u64> =
104            serde_json::from_str(r#"{"jsonrpc": "2.0", "result": 19, "id": 1}"#).unwrap();
105        assert_eq!(response.id, 1);
106        assert_eq!(response.data.into_result().unwrap(), 19);
107    }
108
109    #[test]
110    fn ser_request() {
111        let request: Request<()> = Request::new(300, "method_name", ());
112        assert_eq!(
113            &serde_json::to_string(&request).unwrap(),
114            r#"{"id":300,"jsonrpc":"2.0","method":"method_name"}"#
115        );
116
117        let request: Request<u32> = Request::new(300, "method_name", 1);
118        assert_eq!(
119            &serde_json::to_string(&request).unwrap(),
120            r#"{"id":300,"jsonrpc":"2.0","method":"method_name","params":1}"#
121        );
122    }
123}