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