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