tendermint_rpc/
request.rs

1//! JSON-RPC requests
2
3use core::fmt::Debug;
4
5use serde::{de::DeserializeOwned, Deserialize, Serialize};
6
7use super::{Id, Method, Version};
8use crate::dialect::{Dialect, LatestDialect};
9use crate::{prelude::*, Error};
10
11/// Serialization for JSON-RPC requests
12pub trait RequestMessage: DeserializeOwned + Serialize + Sized {
13    /// Request method
14    fn method(&self) -> Method;
15
16    /// Serialize this request as JSON
17    fn into_json(self) -> String {
18        Wrapper::new(self).into_json()
19    }
20
21    /// Parse a JSON-RPC request from a JSON string.
22    fn from_string(s: impl AsRef<[u8]>) -> Result<Self, Error> {
23        let wrapper: Wrapper<Self> = serde_json::from_slice(s.as_ref()).map_err(Error::serde)?;
24        Ok(wrapper.params)
25    }
26}
27
28/// JSON-RPC requests
29pub trait Request<S: Dialect = LatestDialect>: RequestMessage + Send {
30    /// Response type for this command
31    type Response: super::response::Response;
32}
33
34/// Simple JSON-RPC requests which correlate with a single response from the
35/// remote endpoint.
36///
37/// An example of a request which is not simple would be the event subscription
38/// request, which, on success, returns a [`Subscription`] and not just a
39/// simple, singular response.
40///
41/// [`Subscription`]: struct.Subscription.html
42pub trait SimpleRequest<S: Dialect = LatestDialect>: Request<S> {
43    /// The output data, converted from Response.
44    type Output: From<Self::Response>;
45}
46
47/// JSON-RPC request wrapper (i.e. message envelope)
48#[derive(Debug, Deserialize, Serialize)]
49pub struct Wrapper<R> {
50    /// JSON-RPC version
51    jsonrpc: Version,
52
53    /// Identifier included in request
54    id: Id,
55
56    /// Request method
57    method: Method,
58
59    /// Request parameters (i.e. request object)
60    params: R,
61}
62
63impl<R> Wrapper<R>
64where
65    R: RequestMessage,
66{
67    /// Create a new request wrapper from the given request.
68    ///
69    /// The ID of the request is set to a random [UUIDv4] value.
70    ///
71    /// [UUIDv4]: https://en.wikipedia.org/wiki/Universally_unique_identifier#Version_4_(random)
72    pub fn new(request: R) -> Self {
73        Self::new_with_id(Id::uuid_v4(), request)
74    }
75
76    pub(crate) fn new_with_id(id: Id, request: R) -> Self {
77        Self {
78            jsonrpc: Version::current(),
79            id,
80            method: request.method(),
81            params: request,
82        }
83    }
84
85    pub fn id(&self) -> &Id {
86        &self.id
87    }
88
89    pub fn params(&self) -> &R {
90        &self.params
91    }
92
93    pub fn into_json(self) -> String {
94        serde_json::to_string_pretty(&self).unwrap()
95    }
96}