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