near_jsonrpc_client/methods/
mod.rs

1//! This module contains all the RPC methods.
2use std::io;
3
4use serde::{Deserialize, Serialize};
5use serde_json::json;
6use thiserror::Error;
7
8mod private {
9    pub trait Sealed {}
10}
11
12/// A trait identifying valid NEAR JSON-RPC methods.
13pub trait RpcMethod: private::Sealed
14where
15    Self::Response: RpcHandlerResponse,
16    Self::Error: RpcHandlerError,
17{
18    type Response;
19    type Error;
20
21    fn method_name(&self) -> &str;
22
23    fn params(&self) -> Result<serde_json::Value, io::Error>;
24
25    fn parse_handler_response(
26        response: serde_json::Value,
27    ) -> Result<Result<Self::Response, Self::Error>, serde_json::Error> {
28        Self::Response::parse(response).map(Ok)
29    }
30}
31
32impl<T> private::Sealed for &T where T: private::Sealed {}
33impl<T> RpcMethod for &T
34where
35    T: RpcMethod,
36{
37    type Response = T::Response;
38    type Error = T::Error;
39
40    fn method_name(&self) -> &str {
41        T::method_name(self)
42    }
43
44    fn params(&self) -> Result<serde_json::Value, io::Error> {
45        T::params(self)
46    }
47
48    fn parse_handler_response(
49        response: serde_json::Value,
50    ) -> Result<Result<Self::Response, Self::Error>, serde_json::Error> {
51        T::parse_handler_response(response)
52    }
53}
54
55/// A trait identifying valid NEAR JSON-RPC method responses.
56pub trait RpcHandlerResponse: serde::de::DeserializeOwned {
57    fn parse(value: serde_json::Value) -> Result<Self, serde_json::Error> {
58        serde_json::from_value(value)
59    }
60}
61
62/// A trait identifying valid NEAR JSON-RPC errors.
63pub trait RpcHandlerError: serde::de::DeserializeOwned {
64    /// Parser for the `.error_struct` field in RpcError.
65    fn parse(handler_error: serde_json::Value) -> Result<Self, serde_json::Error> {
66        serde_json::from_value(handler_error)
67    }
68
69    /// Parser for the `.data` field in RpcError, not `.error_struct`.
70    ///
71    /// This would only ever be used as a fallback if [`RpcHandlerError::parse`] fails.
72    ///
73    /// Defaults to `None` meaning there's no alternative deserialization available.
74    fn parse_legacy_error(_error: serde_json::Value) -> Option<Result<Self, serde_json::Error>> {
75        None
76    }
77}
78
79pub mod block;
80pub mod broadcast_tx_async;
81pub mod broadcast_tx_commit;
82pub mod chunk;
83pub mod gas_price;
84pub mod health;
85pub mod light_client_proof;
86pub mod network_info;
87pub mod next_light_client_block;
88pub mod query;
89pub mod send_tx;
90pub mod status;
91pub mod tx;
92pub mod validators;
93
94// ======== experimental ========
95mod experimental;
96pub use experimental::EXPERIMENTAL_changes;
97pub use experimental::EXPERIMENTAL_changes_in_block;
98pub use experimental::EXPERIMENTAL_genesis_config;
99pub use experimental::EXPERIMENTAL_protocol_config;
100pub use experimental::EXPERIMENTAL_receipt;
101pub use experimental::EXPERIMENTAL_tx_status;
102pub use experimental::EXPERIMENTAL_validators_ordered;
103// ======== experimental ========
104
105// ======== any ========
106#[cfg(feature = "any")]
107mod any;
108#[cfg(feature = "any")]
109pub use any::{request as any, RpcAnyRequest};
110// ======== any ========
111
112// ======== sandbox ========
113#[cfg(feature = "sandbox")]
114mod sandbox;
115
116#[cfg(feature = "sandbox")]
117pub use sandbox::sandbox_patch_state;
118
119#[cfg(feature = "sandbox")]
120pub use sandbox::sandbox_fast_forward;
121// ======== sandbox ========
122
123// ======== adversarial ========
124#[cfg(feature = "adversarial")]
125mod adversarial;
126
127#[cfg(feature = "adversarial")]
128pub use adversarial::adv_set_weight;
129
130#[cfg(feature = "adversarial")]
131pub use adversarial::adv_disable_header_sync;
132
133#[cfg(feature = "adversarial")]
134pub use adversarial::adv_disable_doomslug;
135
136#[cfg(feature = "adversarial")]
137pub use adversarial::adv_produce_blocks;
138
139#[cfg(feature = "adversarial")]
140pub use adversarial::adv_switch_to_height;
141
142#[cfg(feature = "adversarial")]
143pub use adversarial::adv_get_saved_blocks;
144
145#[cfg(feature = "adversarial")]
146pub use adversarial::adv_check_store;
147// ======== adversarial ========
148
149/// Converts an RPC Method into JSON.
150pub fn to_json<M: RpcMethod>(method: &M) -> Result<serde_json::Value, io::Error> {
151    let request_payload = near_jsonrpc_primitives::message::Message::request(
152        method.method_name().to_string(),
153        method.params()?,
154    );
155
156    Ok(json!(request_payload))
157}
158
159mod common {
160    use super::*;
161
162    // workaround for deserializing partially serialized
163    // error types missing the `error_message` field in
164    // their UnknownBlock variants.
165    macro_rules! _parse_unknown_block {
166        ($json:expr => $err_ty:ident) => {
167            match $json {
168                err => {
169                    if err["name"] == "UNKNOWN_BLOCK" {
170                        Ok($err_ty::UnknownBlock {
171                            error_message: "".to_string(),
172                        })
173                    } else {
174                        serde_json::from_value(err)
175                    }
176                }
177            }
178        };
179    }
180    pub(crate) use _parse_unknown_block as parse_unknown_block;
181
182    pub fn serialize_signed_transaction(
183        tx: &near_primitives::transaction::SignedTransaction,
184    ) -> Result<String, io::Error> {
185        Ok(near_primitives::serialize::to_base64(&borsh::to_vec(&tx)?))
186    }
187
188    // adv_*
189    #[cfg(feature = "adversarial")]
190    impl RpcHandlerError for () {}
191
192    // adv_*
193    #[cfg(feature = "adversarial")]
194    impl RpcHandlerResponse for () {
195        fn parse(_value: serde_json::Value) -> Result<Self, serde_json::Error> {
196            Ok(())
197        }
198    }
199
200    #[cfg(feature = "any")]
201    impl RpcHandlerResponse for serde_json::Value {
202        fn parse(value: serde_json::Value) -> Result<Self, serde_json::Error> {
203            Ok(value)
204        }
205    }
206
207    #[cfg(feature = "any")]
208    impl RpcHandlerError for serde_json::Value {
209        fn parse(handler_error: serde_json::Value) -> Result<Self, serde_json::Error> {
210            Ok(handler_error)
211        }
212    }
213
214    // broadcast_tx_commit, tx
215    impl RpcHandlerResponse for near_primitives::views::FinalExecutionOutcomeView {}
216
217    // broadcast_tx_commit, tx, EXPERIMENTAL_tx_status
218    impl RpcHandlerError for near_jsonrpc_primitives::types::transactions::RpcTransactionError {
219        fn parse_legacy_error(value: serde_json::Value) -> Option<Result<Self, serde_json::Error>> {
220            match serde_json::from_value::<near_jsonrpc_primitives::errors::ServerError>(value) {
221                Ok(near_jsonrpc_primitives::errors::ServerError::TxExecutionError(
222                    near_primitives::errors::TxExecutionError::InvalidTxError(context),
223                )) => Some(Ok(Self::InvalidTransaction { context })),
224                Err(err) => Some(Err(err)),
225                _ => None,
226            }
227        }
228    }
229
230    // health, status
231    impl RpcHandlerError for near_jsonrpc_primitives::types::status::RpcStatusError {}
232
233    // EXPERIMENTAL_changes, EXPERIMENTAL_changes_in_block
234    impl RpcHandlerError for near_jsonrpc_primitives::types::changes::RpcStateChangesError {
235        fn parse(value: serde_json::Value) -> Result<Self, serde_json::Error> {
236            parse_unknown_block!(value => Self)
237        }
238    }
239
240    // send_tx
241    impl RpcHandlerResponse for near_jsonrpc_primitives::types::transactions::RpcTransactionResponse {}
242
243    // validators, EXPERIMENTAL_validators_ordered
244    impl RpcHandlerError for near_jsonrpc_primitives::types::validator::RpcValidatorError {}
245}