cuprate_rpc_interface/
router_builder.rs

1//! Free functions.
2
3//---------------------------------------------------------------------------------------------------- Use
4use axum::Router;
5
6use crate::{
7    route::{bin, fallback, json_rpc, other},
8    rpc_handler::RpcHandler,
9};
10
11//---------------------------------------------------------------------------------------------------- RouterBuilder
12/// Generate the `RouterBuilder` struct.
13macro_rules! generate_router_builder {
14    ($(
15        // Syntax:
16        // $BUILDER_FUNCTION_NAME =>
17        // $ACTUAL_ENDPOINT_STRING =>
18        // $ENDPOINT_FUNCTION_MODULE::$ENDPOINT_FUNCTION =>
19        // ($HTTP_METHOD(s))
20        $endpoint_ident:ident =>
21        $endpoint_string:literal =>
22        $endpoint_module:ident::$endpoint_fn:ident =>
23        ($($http_method:ident),*)
24    ),* $(,)?) => {
25        /// Builder for creating the RPC router.
26        ///
27        /// This builder allows you to selectively enable endpoints for the router,
28        /// and a [`fallback`](RouterBuilder::fallback) route.
29        ///
30        /// The [`default`](RouterBuilder::default) is to enable [`all`](RouterBuilder::all) routes.
31        ///
32        /// # Routes
33        /// Functions that enable routes are separated into 3 groups:
34        /// - `json_rpc` (enables all of JSON RPC 2.0)
35        /// - `other_` (e.g. [`other_get_height`](RouterBuilder::other_get_height))
36        /// - `bin_` (e.g. [`bin_get_blocks`](RouterBuilder::bin_get_blocks))
37        ///
38        /// For a list of all `monerod` routes, see
39        /// [here](https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.h#L97-L189),
40        /// or the source file of this type.
41        ///
42        /// # Aliases
43        /// Some routes have aliases, such as [`/get_height`](RouterBuilder::other_get_height)
44        /// and [`/getheight`](RouterBuilder::other_getheight).
45        ///
46        /// These both route to the same handler function, but they do not enable each other.
47        ///
48        /// If desired, you can enable `/get_height` but not `/getheight`.
49        ///
50        /// # Example
51        /// ```rust
52        /// use cuprate_rpc_interface::{RouterBuilder, RpcHandlerDummy};
53        ///
54        /// // Create a router with _only_ `/json_rpc` enabled.
55        /// let only_json_rpc = RouterBuilder::<RpcHandlerDummy>::new()
56        ///     .json_rpc()
57        ///     .build();
58        ///
59        /// // Create a router with:
60        /// // - `/get_outs.bin` enabled
61        /// // - A fallback enabled
62        /// let get_outs_bin_and_fallback = RouterBuilder::<RpcHandlerDummy>::new()
63        ///     .bin_get_outs()
64        ///     .fallback()
65        ///     .build();
66        ///
67        /// // Create a router with all endpoints enabled.
68        /// let all = RouterBuilder::<RpcHandlerDummy>::new()
69        ///     .all()
70        ///     .build();
71        /// ```
72        #[derive(Clone)]
73        pub struct RouterBuilder<H: RpcHandler> {
74            router: Router<H>,
75        }
76
77        impl<H: RpcHandler> RouterBuilder<H> {
78            /// Create a new [`Self`].
79            #[must_use]
80            pub fn new() -> Self {
81                Self {
82                    router: Router::new(),
83                }
84            }
85
86            /// Build [`Self`] into a [`Router`].
87            ///
88            /// All endpoints enabled in [`RouterBuilder`]
89            /// will be enabled in this [`Router`].
90            pub fn build(self) -> Router<H> {
91                self.router
92            }
93
94            /// Enable all endpoints, including [`Self::fallback`].
95            #[must_use]
96            pub fn all(mut self) -> Self {
97                $(
98                    self = self.$endpoint_ident();
99                )*
100
101                self.fallback()
102            }
103
104            /// Enable the catch-all fallback route.
105            ///
106            /// Any unknown or disabled route will route here, e.g.:
107            /// - `get_info`
108            /// - `getinfo`
109            /// - `asdf`
110            #[must_use]
111            pub fn fallback(self) -> Self {
112                Self {
113                    router: self.router.fallback(fallback::fallback),
114                }
115            }
116
117            $(
118                #[doc = concat!(
119                    "Enable the `",
120                    $endpoint_string,
121                    "` endpoint.",
122                )]
123                #[must_use]
124                pub fn $endpoint_ident(self) -> Self {
125                    Self {
126                        router: self.router.route(
127                            $endpoint_string,
128                            ::axum::routing::method_routing::MethodRouter::new()
129                                $(.$http_method($endpoint_module::$endpoint_fn::<H>))*
130                        ),
131                    }
132                }
133            )*
134        }
135    };
136}
137
138generate_router_builder! {
139    // JSON-RPC 2.0 route.
140    json_rpc => "/json_rpc" => json_rpc::json_rpc => (get, post),
141
142    // Other JSON routes.
143    other_get_height                  => "/get_height"                  => other::get_height                  => (get, post),
144    other_getheight                   => "/getheight"                   => other::get_height                  => (get, post),
145    other_get_transactions            => "/get_transactions"            => other::get_transactions            => (get, post),
146    other_gettransactions             => "/gettransactions"             => other::get_transactions            => (get, post),
147    other_get_alt_blocks_hashes       => "/get_alt_blocks_hashes"       => other::get_alt_blocks_hashes       => (get, post),
148    other_is_key_image_spent          => "/is_key_image_spent"          => other::is_key_image_spent          => (get, post),
149    other_send_raw_transaction        => "/send_raw_transaction"        => other::send_raw_transaction        => (get, post),
150    other_sendrawtransaction          => "/sendrawtransaction"          => other::send_raw_transaction        => (get, post),
151    other_start_mining                => "/start_mining"                => other::start_mining                => (get, post),
152    other_stop_mining                 => "/stop_mining"                 => other::stop_mining                 => (get, post),
153    other_mining_status               => "/mining_status"               => other::mining_status               => (get, post),
154    other_save_bc                     => "/save_bc"                     => other::save_bc                     => (get, post),
155    other_get_peer_list               => "/get_peer_list"               => other::get_peer_list               => (get, post),
156    other_get_public_nodes            => "/get_public_nodes"            => other::get_public_nodes            => (get, post),
157    other_set_log_hash_rate           => "/set_log_hash_rate"           => other::set_log_hash_rate           => (get, post),
158    other_set_log_level               => "/set_log_level"               => other::set_log_level               => (get, post),
159    other_set_log_categories          => "/set_log_categories"          => other::set_log_categories          => (get, post),
160    other_get_transaction_pool        => "/get_transaction_pool"        => other::get_transaction_pool        => (get, post),
161    other_get_transaction_pool_hashes => "/get_transaction_pool_hashes" => other::get_transaction_pool_hashes => (get, post),
162    other_get_transaction_pool_stats  => "/get_transaction_pool_stats"  => other::get_transaction_pool_stats  => (get, post),
163    other_set_bootstrap_daemon        => "/set_bootstrap_daemon"        => other::set_bootstrap_daemon        => (get, post),
164    other_stop_daemon                 => "/stop_daemon"                 => other::stop_daemon                 => (get, post),
165    other_get_net_stats               => "/get_net_stats"               => other::get_net_stats               => (get, post),
166    other_get_limit                   => "/get_limit"                   => other::get_limit                   => (get, post),
167    other_set_limit                   => "/set_limit"                   => other::set_limit                   => (get, post),
168    other_out_peers                   => "/out_peers"                   => other::out_peers                   => (get, post),
169    other_in_peers                    => "/in_peers"                    => other::in_peers                    => (get, post),
170    other_get_outs                    => "/get_outs"                    => other::get_outs                    => (get, post),
171    other_update                      => "/update"                      => other::update                      => (get, post),
172    other_pop_blocks                  => "/pop_blocks"                  => other::pop_blocks                  => (get, post),
173
174    // Binary routes.
175    bin_get_blocks                  => "/get_blocks.bin"                  => bin::get_blocks                  => (get, post),
176    bin_getblocks                   => "/getblocks.bin"                   => bin::get_blocks                  => (get, post),
177    bin_get_blocks_by_height        => "/get_blocks_by_height.bin"        => bin::get_blocks_by_height        => (get, post),
178    bin_getblocks_by_height         => "/getblocks_by_height.bin"         => bin::get_blocks_by_height        => (get, post),
179    bin_get_hashes                  => "/get_hashes.bin"                  => bin::get_hashes                  => (get, post),
180    bin_gethashes                   => "/gethashes.bin"                   => bin::get_hashes                  => (get, post),
181    bin_get_o_indexes               => "/get_o_indexes.bin"               => bin::get_o_indexes               => (get, post),
182    bin_get_outs                    => "/get_outs.bin"                    => bin::get_outs                    => (get, post),
183    bin_get_transaction_pool_hashes => "/get_transaction_pool_hashes.bin" => bin::get_transaction_pool_hashes => (get, post),
184    bin_get_output_distribution     => "/get_output_distribution.bin"     => bin::get_output_distribution     => (get, post),
185}
186
187impl<H: RpcHandler> Default for RouterBuilder<H> {
188    /// Uses [`Self::all`].
189    fn default() -> Self {
190        Self::new().all()
191    }
192}