1use anyhow::anyhow;
10pub use bridge::{BridgeReadApiClient, BridgeReadApiOpenRpc, BridgeReadApiServer};
11pub use coin::{CoinReadApiClient, CoinReadApiOpenRpc, CoinReadApiServer};
12pub use extended::{ExtendedApiClient, ExtendedApiOpenRpc, ExtendedApiServer};
13pub use governance::{GovernanceReadApiClient, GovernanceReadApiOpenRpc, GovernanceReadApiServer};
14pub use indexer::{IndexerApiClient, IndexerApiOpenRpc, IndexerApiServer};
15use jsonrpsee::{
16 core::ClientError,
17 types::{
18 ErrorObjectOwned,
19 error::{INTERNAL_ERROR_CODE, UNKNOWN_ERROR_CODE},
20 },
21};
22pub use move_utils::{MoveUtilsClient, MoveUtilsOpenRpc, MoveUtilsServer};
23use once_cell::sync::Lazy;
24use prometheus::{
25 Histogram, IntCounter, register_histogram_with_registry, register_int_counter_with_registry,
26};
27pub use read::{ReadApiClient, ReadApiOpenRpc, ReadApiServer};
28use tap::TapFallible;
29use tracing::warn;
30pub use transaction_builder::{
31 TransactionBuilderClient, TransactionBuilderOpenRpc, TransactionBuilderServer,
32};
33pub use write::{WriteApiClient, WriteApiOpenRpc, WriteApiServer};
34
35mod bridge;
36mod coin;
37mod extended;
38mod governance;
39mod indexer;
40mod move_utils;
41mod read;
42mod transaction_builder;
43mod write;
44
45const RPC_QUERY_MAX_RESULT_LIMIT: &str = "RPC_QUERY_MAX_RESULT_LIMIT";
46const DEFAULT_RPC_QUERY_MAX_RESULT_LIMIT: usize = 50;
47
48pub static QUERY_MAX_RESULT_LIMIT: Lazy<usize> = Lazy::new(|| {
49 read_size_from_env(RPC_QUERY_MAX_RESULT_LIMIT).unwrap_or(DEFAULT_RPC_QUERY_MAX_RESULT_LIMIT)
50});
51
52pub const QUERY_MAX_RESULT_LIMIT_CHECKPOINTS: usize = 100;
54
55pub fn cap_page_limit(limit: Option<usize>) -> usize {
56 let limit = limit.unwrap_or_default();
57 if limit > *QUERY_MAX_RESULT_LIMIT || limit == 0 {
58 *QUERY_MAX_RESULT_LIMIT
59 } else {
60 limit
61 }
62}
63
64pub fn validate_limit(limit: Option<usize>, max: usize) -> Result<usize, anyhow::Error> {
65 match limit {
66 Some(l) if l > max => Err(anyhow!("Page size limit {l} exceeds max limit {max}")),
67 Some(0) => Err(anyhow!("Page size limit cannot be smaller than 1")),
68 Some(l) => Ok(l),
69 None => Ok(max),
70 }
71}
72
73#[derive(Clone)]
74pub struct JsonRpcMetrics {
75 pub get_objects_limit: Histogram,
76 pub get_objects_result_size: Histogram,
77 pub get_objects_result_size_total: IntCounter,
78 pub get_tx_blocks_limit: Histogram,
79 pub get_tx_blocks_result_size: Histogram,
80 pub get_tx_blocks_result_size_total: IntCounter,
81 pub get_checkpoints_limit: Histogram,
82 pub get_checkpoints_result_size: Histogram,
83 pub get_checkpoints_result_size_total: IntCounter,
84 pub get_owned_objects_limit: Histogram,
85 pub get_owned_objects_result_size: Histogram,
86 pub get_owned_objects_result_size_total: IntCounter,
87 pub get_coins_limit: Histogram,
88 pub get_coins_result_size: Histogram,
89 pub get_coins_result_size_total: IntCounter,
90 pub get_dynamic_fields_limit: Histogram,
91 pub get_dynamic_fields_result_size: Histogram,
92 pub get_dynamic_fields_result_size_total: IntCounter,
93 pub query_tx_blocks_limit: Histogram,
94 pub query_tx_blocks_result_size: Histogram,
95 pub query_tx_blocks_result_size_total: IntCounter,
96 pub query_events_limit: Histogram,
97 pub query_events_result_size: Histogram,
98 pub query_events_result_size_total: IntCounter,
99
100 pub get_stake_iota_result_size: Histogram,
101 pub get_stake_iota_result_size_total: IntCounter,
102
103 pub get_stake_iota_latency: Histogram,
104 pub get_delegated_iota_latency: Histogram,
105
106 pub orchestrator_latency_ms: Histogram,
107 pub post_orchestrator_latency_ms: Histogram,
108}
109
110impl JsonRpcMetrics {
111 pub fn new(registry: &prometheus::Registry) -> Self {
112 Self {
113 get_objects_limit: register_histogram_with_registry!(
114 "json_rpc_get_objects_limit",
115 "The input limit for multi_get_objects, after applying the cap",
116 iota_metrics::COUNT_BUCKETS.to_vec(),
117 registry,
118 )
119 .unwrap(),
120 get_objects_result_size: register_histogram_with_registry!(
121 "json_rpc_get_objects_result_size",
122 "The return size for multi_get_objects",
123 iota_metrics::COUNT_BUCKETS.to_vec(),
124 registry,
125 )
126 .unwrap(),
127 get_objects_result_size_total: register_int_counter_with_registry!(
128 "json_rpc_get_objects_result_size_total",
129 "The total return size for multi_get_objects",
130 registry
131 )
132 .unwrap(),
133 get_tx_blocks_limit: register_histogram_with_registry!(
134 "json_rpc_get_tx_blocks_limit",
135 "The input limit for get_tx_blocks, after applying the cap",
136 iota_metrics::COUNT_BUCKETS.to_vec(),
137 registry,
138 )
139 .unwrap(),
140 get_tx_blocks_result_size: register_histogram_with_registry!(
141 "json_rpc_get_tx_blocks_result_size",
142 "The return size for get_tx_blocks",
143 iota_metrics::COUNT_BUCKETS.to_vec(),
144 registry,
145 )
146 .unwrap(),
147 get_tx_blocks_result_size_total: register_int_counter_with_registry!(
148 "json_rpc_get_tx_blocks_result_size_total",
149 "The total return size for get_tx_blocks",
150 registry
151 )
152 .unwrap(),
153 get_checkpoints_limit: register_histogram_with_registry!(
154 "json_rpc_get_checkpoints_limit",
155 "The input limit for get_checkpoints, after applying the cap",
156 iota_metrics::COUNT_BUCKETS.to_vec(),
157 registry,
158 )
159 .unwrap(),
160 get_checkpoints_result_size: register_histogram_with_registry!(
161 "json_rpc_get_checkpoints_result_size",
162 "The return size for get_checkpoints",
163 iota_metrics::COUNT_BUCKETS.to_vec(),
164 registry,
165 )
166 .unwrap(),
167 get_checkpoints_result_size_total: register_int_counter_with_registry!(
168 "json_rpc_get_checkpoints_result_size_total",
169 "The total return size for get_checkpoints",
170 registry
171 )
172 .unwrap(),
173 get_owned_objects_limit: register_histogram_with_registry!(
174 "json_rpc_get_owned_objects_limit",
175 "The input limit for get_owned_objects, after applying the cap",
176 iota_metrics::COUNT_BUCKETS.to_vec(),
177 registry,
178 )
179 .unwrap(),
180 get_owned_objects_result_size: register_histogram_with_registry!(
181 "json_rpc_get_owned_objects_result_size",
182 "The return size for get_owned_objects",
183 iota_metrics::COUNT_BUCKETS.to_vec(),
184 registry,
185 )
186 .unwrap(),
187 get_owned_objects_result_size_total: register_int_counter_with_registry!(
188 "json_rpc_get_owned_objects_result_size_total",
189 "The total return size for get_owned_objects",
190 registry
191 )
192 .unwrap(),
193 get_coins_limit: register_histogram_with_registry!(
194 "json_rpc_get_coins_limit",
195 "The input limit for get_coins, after applying the cap",
196 iota_metrics::COUNT_BUCKETS.to_vec(),
197 registry,
198 )
199 .unwrap(),
200 get_coins_result_size: register_histogram_with_registry!(
201 "json_rpc_get_coins_result_size",
202 "The return size for get_coins",
203 iota_metrics::COUNT_BUCKETS.to_vec(),
204 registry,
205 )
206 .unwrap(),
207 get_coins_result_size_total: register_int_counter_with_registry!(
208 "json_rpc_get_coins_result_size_total",
209 "The total return size for get_coins",
210 registry
211 )
212 .unwrap(),
213 get_dynamic_fields_limit: register_histogram_with_registry!(
214 "json_rpc_get_dynamic_fields_limit",
215 "The input limit for get_dynamic_fields, after applying the cap",
216 iota_metrics::COUNT_BUCKETS.to_vec(),
217 registry,
218 )
219 .unwrap(),
220 get_dynamic_fields_result_size: register_histogram_with_registry!(
221 "json_rpc_get_dynamic_fields_result_size",
222 "The return size for get_dynamic_fields",
223 iota_metrics::COUNT_BUCKETS.to_vec(),
224 registry,
225 )
226 .unwrap(),
227 get_dynamic_fields_result_size_total: register_int_counter_with_registry!(
228 "json_rpc_get_dynamic_fields_result_size_total",
229 "The total return size for get_dynamic_fields",
230 registry
231 )
232 .unwrap(),
233 query_tx_blocks_limit: register_histogram_with_registry!(
234 "json_rpc_query_tx_blocks_limit",
235 "The input limit for query_tx_blocks, after applying the cap",
236 iota_metrics::COUNT_BUCKETS.to_vec(),
237 registry,
238 )
239 .unwrap(),
240 query_tx_blocks_result_size: register_histogram_with_registry!(
241 "json_rpc_query_tx_blocks_result_size",
242 "The return size for query_tx_blocks",
243 iota_metrics::COUNT_BUCKETS.to_vec(),
244 registry,
245 )
246 .unwrap(),
247 query_tx_blocks_result_size_total: register_int_counter_with_registry!(
248 "json_rpc_query_tx_blocks_result_size_total",
249 "The total return size for query_tx_blocks",
250 registry
251 )
252 .unwrap(),
253 query_events_limit: register_histogram_with_registry!(
254 "json_rpc_query_events_limit",
255 "The input limit for query_events, after applying the cap",
256 iota_metrics::COUNT_BUCKETS.to_vec(),
257 registry,
258 )
259 .unwrap(),
260 query_events_result_size: register_histogram_with_registry!(
261 "json_rpc_query_events_result_size",
262 "The return size for query_events",
263 iota_metrics::COUNT_BUCKETS.to_vec(),
264 registry,
265 )
266 .unwrap(),
267 query_events_result_size_total: register_int_counter_with_registry!(
268 "json_rpc_query_events_result_size_total",
269 "The total return size for query_events",
270 registry
271 )
272 .unwrap(),
273 get_stake_iota_result_size: register_histogram_with_registry!(
274 "json_rpc_get_stake_iota_result_size",
275 "The return size for get_stake_iota",
276 iota_metrics::COUNT_BUCKETS.to_vec(),
277 registry,
278 )
279 .unwrap(),
280 get_stake_iota_result_size_total: register_int_counter_with_registry!(
281 "json_rpc_get_stake_iota_result_size_total",
282 "The total return size for get_stake_iota",
283 registry
284 )
285 .unwrap(),
286 get_stake_iota_latency: register_histogram_with_registry!(
287 "get_stake_iota_latency",
288 "The latency of get stake iota, in ms",
289 iota_metrics::COARSE_LATENCY_SEC_BUCKETS.to_vec(),
290 registry,
291 )
292 .unwrap(),
293 get_delegated_iota_latency: register_histogram_with_registry!(
294 "get_delegated_iota_latency",
295 "The latency of get delegated iota, in ms",
296 iota_metrics::COARSE_LATENCY_SEC_BUCKETS.to_vec(),
297 registry,
298 )
299 .unwrap(),
300 orchestrator_latency_ms: register_histogram_with_registry!(
301 "json_rpc_orchestrator_latency",
302 "The latency of submitting transaction via transaction orchestrator, in ms",
303 iota_metrics::COARSE_LATENCY_SEC_BUCKETS.to_vec(),
304 registry,
305 )
306 .unwrap(),
307 post_orchestrator_latency_ms: register_histogram_with_registry!(
308 "json_rpc_post_orchestrator_latency",
309 "The latency of response processing after transaction orchestrator, in ms",
310 iota_metrics::COARSE_LATENCY_SEC_BUCKETS.to_vec(),
311 registry,
312 )
313 .unwrap(),
314 }
315 }
316
317 pub fn new_for_tests() -> Self {
318 let registry = prometheus::Registry::new();
319 Self::new(®istry)
320 }
321}
322
323pub fn read_size_from_env(var_name: &str) -> Option<usize> {
324 std::env::var(var_name)
325 .ok()?
326 .parse::<usize>()
327 .tap_err(|e| {
328 warn!(
329 "Env var {} does not contain valid usize integer: {}",
330 var_name, e
331 )
332 })
333 .ok()
334}
335
336pub const CLIENT_SDK_TYPE_HEADER: &str = "client-sdk-type";
337pub const CLIENT_SDK_VERSION_HEADER: &str = "client-sdk-version";
340pub const CLIENT_TARGET_API_VERSION_HEADER: &str = "client-target-api-version";
343
344pub const TRANSIENT_ERROR_CODE: i32 = -32050;
345pub const TRANSACTION_EXECUTION_CLIENT_ERROR_CODE: i32 = -32002;
346
347pub fn error_object_from_rpc(rpc_err: ClientError) -> ErrorObjectOwned {
349 match rpc_err {
350 ClientError::Call(e) => e,
351 _ => ErrorObjectOwned::owned::<()>(UNKNOWN_ERROR_CODE, rpc_err.to_string(), None),
352 }
353}
354
355pub fn internal_error(err: impl ToString) -> ErrorObjectOwned {
357 ErrorObjectOwned::owned::<()>(INTERNAL_ERROR_CODE, err.to_string(), None)
358}