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