subrpcer/lib.rs
1//! Minimal implementation of Substrate RPC APIs.
2//!
3//! Formatting rule(s):
4//! - All the APIs must be sorted in alphabetic order.
5
6#![deny(missing_docs)]
7#![deny(unused_crate_dependencies)]
8
9// TODO: https://github.com/rust-lang/rust/issues/82715
10// This should be `no_run` eventually
11/// Define a group of APIs.
12///
13/// Require [serde](https://crates.io/crates/serde) and [serde_json](https://crates.io/crates/serde_json) as the dependencies.
14///
15/// # Example
16/// ```ignore
17/// impl_apis! {
18/// state {
19/// call { params: [name, bytes], opt_params: [hash] }
20/// get_keys { params: [prefix], opt_params: [hash] }
21/// get_metadata { params: [], opt_params: [hash] }
22/// get_pairs { params: [prefix], opt_params: [hash] }
23/// get_read_proof { params: [keys], opt_params: [hash] }
24/// get_runtime_version { params: [], opt_params: [hash] }
25/// get_storage { params: [key], opt_params: [hash] }
26/// get_storage_hash { params: [key], opt_params: [hash] }
27/// get_storage_size { params: [key], opt_params: [hash] }
28/// query_storage { params: [keys, block], opt_params: [hash] }
29/// query_storage_at { params: [keys], opt_params: [at] }
30/// subscribe_runtime_version { params: [], opt_params: [] }
31/// subscribe_storage { params: [], opt_params: [keys] }
32/// trace_block { params: [block], opt_params: [targets, storage_keys, methods] }
33/// unsubscribe_runtime_version { params: [subscription_id], opt_params: [] }
34/// unsubscribe_storage { params: [subscription_id], opt_params: [] }
35/// }
36/// }
37/// ```
38#[allow(clippy::tabs_in_doc_comments)]
39#[macro_export]
40macro_rules! impl_apis {
41 {
42 $prefix:ident {
43 $(
44 $method:ident {
45 params: [
46 $(
47 $param:ident
48 ),*
49 ],
50 opt_params: [
51 $(
52 $opt_param:ident
53 ),*
54 ]
55 }
56 )+
57 }
58 } => {
59 $(
60 affix::paste! {
61 /// Check module's Substrate reference(s) for the detail.
62 pub fn $method(
63 id: usize,
64 $($param: impl serde::Serialize,)*
65 $($opt_param: Option<impl serde::Serialize>,)*
66 ) -> serde_json::Value {
67 $crate::rpc(
68 id,
69 stringify!([<$prefix _ $method:camel>]),
70 serde_json::json!([
71 $($param,)*
72 $($opt_param,)*
73 ])
74 )
75 }
76
77 #[doc = concat!("Similar to [`", stringify!($method), "`], but return the method name and parameters directly.")]
78 pub fn [<$method _raw>](
79 $($param: impl serde::Serialize,)*
80 $($opt_param: Option<impl serde::Serialize>,)*
81 ) -> (&'static str, serde_json::Value) {
82 (
83 stringify!([<$prefix _ $method:camel>]),
84 serde_json::json!([
85 $($param,)*
86 $($opt_param,)*
87 ])
88 )
89 }
90 }
91 )+
92 };
93}
94
95pub mod author;
96pub mod babe;
97pub mod chain;
98pub mod grandpa;
99pub mod net;
100pub mod offchain;
101pub mod payment;
102pub mod rpc;
103pub mod state;
104pub mod system;
105
106#[cfg(any(feature = "reqwest-client", feature = "ureq-client"))] pub mod client;
107
108// TODO: optimize the option param
109
110// crates.io
111use serde_json::Value;
112
113/// Build a JSONRPC 2.0 call.
114pub fn rpc(id: usize, method: &str, params: Value) -> Value {
115 let rpc = serde_json::json!({
116 "jsonrpc": "2.0",
117 "id": id,
118 "method": method,
119 "params": params
120 });
121
122 // This must not fail.
123 //
124 // `unwrap_or_default` is useless actually.
125 #[cfg(feature = "trace")]
126 tracing::trace!("Rpc({:?})", serde_json::to_string(&rpc).unwrap_or_default());
127
128 rpc
129}