1use borsh::BorshDeserialize;
2use near_api_types::{
3 json::U64, AccessKey, Account, AccountView, ContractCodeView, Data, PublicKey,
4 RpcBlockResponse, RpcValidatorResponse, ViewStateResult,
5};
6use near_openapi_client::types::RpcQueryResponse;
7use serde::de::DeserializeOwned;
8use std::marker::PhantomData;
9use tracing::{info, trace, warn};
10
11use crate::{
12 advanced::{
13 block_rpc::SimpleBlockRpc, query_rpc::SimpleQueryRpc, validator_rpc::SimpleValidatorRpc,
14 RpcType,
15 },
16 common::query::{ResultWithMethod, QUERY_EXECUTOR_TARGET},
17 errors::QueryError,
18};
19pub mod transformers;
20pub use transformers::*;
21
22const fn query_to_kind(response: &RpcQueryResponse) -> &'static str {
23 match response {
24 RpcQueryResponse::Variant0 { .. } => "ViewAccount",
25 RpcQueryResponse::Variant1 { .. } => "ViewCode",
26 RpcQueryResponse::Variant2 { .. } => "ViewState",
27 RpcQueryResponse::Variant3 { .. } => "CallResult",
28 RpcQueryResponse::Variant4 { .. } => "AccessKey",
29 RpcQueryResponse::Variant5 { .. } => "AccessKeyList",
30 RpcQueryResponse::Variant6 { .. } => "ViewGasKey",
31 RpcQueryResponse::Variant7 { .. } => "ViewGasKeyList",
32
33 #[allow(unreachable_patterns)]
34 _ => "UnknownQueryResponse",
35 }
36}
37
38pub trait ResponseHandler {
39 type Response;
40 type Query: RpcType;
41
42 fn process_response(
44 &self,
45 responses: Vec<<Self::Query as RpcType>::Response>,
46 ) -> ResultWithMethod<Self::Response, <Self::Query as RpcType>::Error>;
47 fn request_amount(&self) -> usize {
48 1
49 }
50}
51
52#[derive(Default, Debug, Clone)]
53pub struct CallResultHandler<Response: Send + Sync>(PhantomData<Response>);
54
55impl<Response: Send + Sync> CallResultHandler<Response> {
56 pub const fn new() -> Self {
57 Self(PhantomData::<Response>)
58 }
59}
60
61impl<Response> ResponseHandler for CallResultHandler<Response>
62where
63 Response: DeserializeOwned + Send + Sync,
64{
65 type Response = Data<Response>;
66 type Query = SimpleQueryRpc;
67
68 fn process_response(
69 &self,
70 response: Vec<RpcQueryResponse>,
71 ) -> ResultWithMethod<Self::Response, <Self::Query as RpcType>::Error> {
72 let response = response
73 .into_iter()
74 .next()
75 .ok_or(QueryError::InternalErrorNoResponse)?;
76
77 if let RpcQueryResponse::Variant3 {
78 result,
79 logs: _logs,
80 block_height,
81 block_hash,
82 } = response
83 {
84 trace!(target: QUERY_EXECUTOR_TARGET, "Deserializing CallResult, result size: {} bytes", result.len());
85 let data: Response = serde_json::from_slice(&result)?;
86 Ok(Data {
87 data,
88 block_height,
89 block_hash: block_hash.into(),
90 })
91 } else {
92 warn!(target: QUERY_EXECUTOR_TARGET, "Unexpected response kind: {:?}", response);
93 Err(QueryError::UnexpectedResponse {
94 expected: "CallResult",
95 got: query_to_kind(&response),
96 })
97 }
98 }
99}
100
101#[derive(Default, Debug, Clone)]
102pub struct CallResultRawHandler;
103
104impl CallResultRawHandler {
105 pub const fn new() -> Self {
106 Self
107 }
108}
109
110impl ResponseHandler for CallResultRawHandler {
111 type Response = Data<Vec<u8>>;
112 type Query = SimpleQueryRpc;
113
114 fn process_response(
115 &self,
116 response: Vec<RpcQueryResponse>,
117 ) -> ResultWithMethod<Self::Response, <Self::Query as RpcType>::Error> {
118 let response = response
119 .into_iter()
120 .next()
121 .ok_or(QueryError::InternalErrorNoResponse)?;
122
123 if let RpcQueryResponse::Variant3 {
124 result,
125 logs: _logs,
126 block_height,
127 block_hash,
128 } = response
129 {
130 trace!(target: QUERY_EXECUTOR_TARGET, "Returning CallResult raw bytes, result size: {} bytes", result.len());
131 Ok(Data {
132 data: result,
133 block_height,
134 block_hash: block_hash.into(),
135 })
136 } else {
137 warn!(target: QUERY_EXECUTOR_TARGET, "Unexpected response kind: {:?}", response);
138 Err(QueryError::UnexpectedResponse {
139 expected: "CallResult",
140 got: query_to_kind(&response),
141 })
142 }
143 }
144}
145
146#[derive(Default, Debug, Clone)]
147pub struct CallResultBorshHandler<Response: Send + Sync>(PhantomData<Response>);
148
149impl<Response: Send + Sync> CallResultBorshHandler<Response> {
150 pub const fn new() -> Self {
151 Self(PhantomData::<Response>)
152 }
153}
154
155impl<Response> ResponseHandler for CallResultBorshHandler<Response>
156where
157 Response: BorshDeserialize + Send + Sync,
158{
159 type Response = Data<Response>;
160 type Query = SimpleQueryRpc;
161
162 fn process_response(
163 &self,
164 response: Vec<RpcQueryResponse>,
165 ) -> ResultWithMethod<Self::Response, <Self::Query as RpcType>::Error> {
166 let response = response
167 .into_iter()
168 .next()
169 .ok_or(QueryError::InternalErrorNoResponse)?;
170
171 if let RpcQueryResponse::Variant3 {
172 result,
173 logs: _logs,
174 block_height,
175 block_hash,
176 } = response
177 {
178 trace!(target: QUERY_EXECUTOR_TARGET, "Deserializing CallResult using Borsh, result size: {} bytes", result.len());
179 let data: Response = Response::try_from_slice(&result)
180 .map_err(|e| QueryError::ConversionError(Box::new(e)))?;
181 Ok(Data {
182 data,
183 block_height,
184 block_hash: block_hash.into(),
185 })
186 } else {
187 warn!(target: QUERY_EXECUTOR_TARGET, "Unexpected response kind: {:?}", response);
188 Err(QueryError::UnexpectedResponse {
189 expected: "CallResult",
190 got: query_to_kind(&response),
191 })
192 }
193 }
194}
195
196#[derive(Default, Debug, Clone)]
197pub struct AccountViewHandler;
198
199impl ResponseHandler for AccountViewHandler {
200 type Query = SimpleQueryRpc;
201 type Response = Data<Account>;
202
203 fn process_response(
204 &self,
205 response: Vec<RpcQueryResponse>,
206 ) -> ResultWithMethod<Self::Response, <Self::Query as RpcType>::Error> {
207 let response = response
208 .into_iter()
209 .next()
210 .ok_or(QueryError::InternalErrorNoResponse)?;
211
212 if let RpcQueryResponse::Variant0 {
213 amount,
214 locked,
215 code_hash,
216 storage_usage,
217 storage_paid_at,
218 block_hash,
219 block_height,
220 global_contract_account_id,
221 global_contract_hash,
222 } = response
223 {
224 info!(
225 target: QUERY_EXECUTOR_TARGET,
226 "Processed ViewAccount response: balance: {}, locked: {}",
227 amount, locked
228 );
229 Ok(Data {
230 data: AccountView {
231 amount,
232 locked,
233 code_hash,
234 storage_usage,
235 storage_paid_at,
236 global_contract_account_id,
237 global_contract_hash,
238 }
239 .try_into()
240 .map_err(|e| QueryError::ConversionError(Box::new(e)))?,
241 block_height,
242 block_hash: block_hash.into(),
243 })
244 } else {
245 warn!(target: QUERY_EXECUTOR_TARGET, "Unexpected response kind: {:?}", response);
246 Err(QueryError::UnexpectedResponse {
247 expected: "ViewAccount",
248 got: query_to_kind(&response),
249 })
250 }
251 }
252
253 fn request_amount(&self) -> usize {
254 1
255 }
256}
257
258#[derive(Default, Debug, Clone)]
259pub struct AccessKeyListHandler;
260
261impl ResponseHandler for AccessKeyListHandler {
262 type Response = Data<Vec<(PublicKey, AccessKey)>>;
263 type Query = SimpleQueryRpc;
264
265 fn process_response(
266 &self,
267 response: Vec<RpcQueryResponse>,
268 ) -> ResultWithMethod<Self::Response, <Self::Query as RpcType>::Error> {
269 let response = response
270 .into_iter()
271 .next()
272 .ok_or(QueryError::InternalErrorNoResponse)?;
273 if let RpcQueryResponse::Variant5 {
274 keys,
275 block_height,
276 block_hash,
277 } = response
278 {
279 info!(
280 target: QUERY_EXECUTOR_TARGET,
281 "Processed AccessKeyList response, keys count: {}",
282 keys.len()
283 );
284 Ok(Data {
285 data: keys
286 .into_iter()
287 .filter_map(|key| {
288 let public_key = key.public_key.try_into().ok()?;
289 let access_key = key.access_key.try_into().ok()?;
290 Some((public_key, access_key))
291 })
292 .collect(),
293 block_height,
294 block_hash: block_hash.into(),
295 })
296 } else {
297 warn!(target: QUERY_EXECUTOR_TARGET, "Unexpected response kind: {:?}", response);
298 Err(QueryError::UnexpectedResponse {
299 expected: "AccessKeyList",
300 got: query_to_kind(&response),
301 })
302 }
303 }
304
305 fn request_amount(&self) -> usize {
306 1
307 }
308}
309
310#[derive(Default, Debug, Clone)]
311pub struct AccessKeyHandler;
312
313impl ResponseHandler for AccessKeyHandler {
314 type Response = Data<AccessKey>;
315 type Query = SimpleQueryRpc;
316
317 fn process_response(
318 &self,
319 response: Vec<RpcQueryResponse>,
320 ) -> ResultWithMethod<Self::Response, <Self::Query as RpcType>::Error> {
321 let response = response
322 .into_iter()
323 .next()
324 .ok_or(QueryError::InternalErrorNoResponse)?;
325 if let RpcQueryResponse::Variant4 {
326 block_hash,
327 nonce,
328 block_height,
329 permission,
330 } = response
331 {
332 info!(
333 target: QUERY_EXECUTOR_TARGET,
334 "Processed AccessKey response, nonce: {}, permission: {:?}",
335 nonce,
336 permission
337 );
338 Ok(Data {
339 data: AccessKey {
340 nonce: U64(nonce),
341 permission: permission
342 .try_into()
343 .map_err(|e| QueryError::ConversionError(Box::new(e)))?,
344 },
345 block_height,
346 block_hash: block_hash.into(),
347 })
348 } else {
349 warn!(target: QUERY_EXECUTOR_TARGET, "Unexpected response kind: {:?}", response);
350 Err(QueryError::UnexpectedResponse {
351 expected: "AccessKey",
352 got: query_to_kind(&response),
353 })
354 }
355 }
356}
357
358#[derive(Default, Debug, Clone)]
359pub struct ViewStateHandler;
360
361impl ResponseHandler for ViewStateHandler {
362 type Response = Data<ViewStateResult>;
363 type Query = SimpleQueryRpc;
364
365 fn process_response(
366 &self,
367 response: Vec<RpcQueryResponse>,
368 ) -> ResultWithMethod<Self::Response, <Self::Query as RpcType>::Error> {
369 let response = response
370 .into_iter()
371 .next()
372 .ok_or(QueryError::InternalErrorNoResponse)?;
373 if let RpcQueryResponse::Variant2 {
374 proof,
375 values,
376 block_height,
377 block_hash,
378 } = response
379 {
380 info!(
381 target: QUERY_EXECUTOR_TARGET,
382 "Processed ViewState response, values count: {}, proof nodes: {}",
383 values.len(),
384 proof.len()
385 );
386 Ok(Data {
387 data: ViewStateResult { proof, values },
388 block_height,
389 block_hash: block_hash.into(),
390 })
391 } else {
392 warn!(target: QUERY_EXECUTOR_TARGET, "Unexpected response kind: {:?}", response);
393 Err(QueryError::UnexpectedResponse {
394 expected: "ViewState",
395 got: query_to_kind(&response),
396 })
397 }
398 }
399}
400
401#[derive(Default, Debug, Clone)]
402pub struct ViewCodeHandler;
403
404impl ResponseHandler for ViewCodeHandler {
405 type Response = Data<ContractCodeView>;
406 type Query = SimpleQueryRpc;
407
408 fn process_response(
409 &self,
410 response: Vec<RpcQueryResponse>,
411 ) -> ResultWithMethod<Self::Response, <Self::Query as RpcType>::Error> {
412 let response = response
413 .into_iter()
414 .next()
415 .ok_or(QueryError::InternalErrorNoResponse)?;
416 if let RpcQueryResponse::Variant1 {
417 code_base64,
418 hash,
419 block_height,
420 block_hash,
421 } = response
422 {
423 info!(
424 target: QUERY_EXECUTOR_TARGET,
425 "Processed ViewCode response, code size: {} bytes, hash: {:?}",
426 code_base64.len(),
427 hash
428 );
429 Ok(Data {
430 data: ContractCodeView { code_base64, hash },
431 block_height,
432 block_hash: block_hash.into(),
433 })
434 } else {
435 warn!(target: QUERY_EXECUTOR_TARGET, "Unexpected response kind: {:?}", response);
436 Err(QueryError::UnexpectedResponse {
437 expected: "ViewCode",
438 got: query_to_kind(&response),
439 })
440 }
441 }
442}
443
444#[derive(Clone, Debug)]
445pub struct RpcValidatorHandler;
446
447impl ResponseHandler for RpcValidatorHandler {
448 type Response = RpcValidatorResponse;
449 type Query = SimpleValidatorRpc;
450
451 fn process_response(
452 &self,
453 response: Vec<RpcValidatorResponse>,
454 ) -> ResultWithMethod<Self::Response, <Self::Query as RpcType>::Error> {
455 let response = response
456 .into_iter()
457 .next()
458 .ok_or(QueryError::InternalErrorNoResponse)?;
459
460 info!(
461 target: QUERY_EXECUTOR_TARGET,
462 "Processed EpochValidatorInfo response, epoch height: {}, validators count: {}",
463 response.epoch_height,
464 response.current_validators.len()
465 );
466 Ok(response)
467 }
468}
469
470#[derive(Clone, Debug)]
471pub struct RpcBlockHandler;
472
473impl ResponseHandler for RpcBlockHandler {
474 type Response = RpcBlockResponse;
475 type Query = SimpleBlockRpc;
476
477 fn process_response(
478 &self,
479 response: Vec<RpcBlockResponse>,
480 ) -> ResultWithMethod<Self::Response, <Self::Query as RpcType>::Error> {
481 let response = response
482 .into_iter()
483 .next()
484 .ok_or(QueryError::InternalErrorNoResponse)?;
485
486 info!(
487 target: QUERY_EXECUTOR_TARGET,
488 "Processed Block response, height: {}, hash: {:?}",
489 response.header.height,
490 response.header.hash
491 );
492 Ok(response)
493 }
494
495 fn request_amount(&self) -> usize {
496 1
497 }
498}
499
500impl<T: RpcType> ResponseHandler for T {
501 type Response = <T as RpcType>::Response;
502 type Query = T;
503
504 fn process_response(
505 &self,
506 response: Vec<<Self::Query as RpcType>::Response>,
507 ) -> ResultWithMethod<Self::Response, <Self::Query as RpcType>::Error> {
508 let response = response
509 .into_iter()
510 .next()
511 .ok_or(QueryError::InternalErrorNoResponse)?;
512
513 trace!(target: QUERY_EXECUTOR_TARGET, "Processed empty response handler");
514
515 Ok(response)
516 }
517}