near_api/common/
query.rs

1// TODO: root level doc might be needed here. It's pretty complicated.
2use std::{marker::PhantomData, sync::Arc};
3
4use futures::future::join_all;
5use near_jsonrpc_client::methods::{
6    block::{RpcBlockError, RpcBlockRequest},
7    query::{RpcQueryError, RpcQueryRequest, RpcQueryResponse},
8    validators::{RpcValidatorError, RpcValidatorRequest},
9    RpcMethod,
10};
11use near_primitives::{
12    types::{BlockReference, EpochReference},
13    views::{
14        AccessKeyList, AccessKeyView, AccountView, BlockView, ContractCodeView, EpochValidatorInfo,
15        QueryRequest, ViewStateResult,
16    },
17};
18use serde::de::DeserializeOwned;
19use tracing::{debug, error, info, instrument, trace, warn};
20
21use crate::{
22    config::{retry, NetworkConfig, RetryResponse},
23    errors::QueryError,
24    types::Data,
25};
26
27use super::utils::{
28    is_critical_blocks_error, is_critical_query_error, is_critical_validator_error,
29};
30
31const QUERY_EXECUTOR_TARGET: &str = "near_api::query::executor";
32
33type ResultWithMethod<T, Method> = core::result::Result<T, QueryError<Method>>;
34
35pub trait ResponseHandler
36where
37    <Self::Method as RpcMethod>::Error: std::fmt::Display + std::fmt::Debug,
38{
39    type QueryResponse;
40    type Response;
41    type Method: RpcMethod;
42
43    // TODO: Add error type
44
45    /// NOTE: responses should always >= 1
46    fn process_response(
47        &self,
48        responses: Vec<Self::QueryResponse>,
49    ) -> ResultWithMethod<Self::Response, Self::Method>;
50    fn request_amount(&self) -> usize {
51        1
52    }
53}
54
55pub trait QueryCreator<Method: RpcMethod>
56where
57    Method::Error: std::fmt::Display + std::fmt::Debug + Sync + Send,
58{
59    type RpcReference;
60    fn create_query(
61        &self,
62        network: &NetworkConfig,
63        reference: Self::RpcReference,
64    ) -> ResultWithMethod<Method, Method>;
65
66    fn is_critical_error(
67        &self,
68        error: &near_jsonrpc_client::errors::JsonRpcError<Method::Error>,
69    ) -> bool;
70}
71
72#[derive(Clone, Debug)]
73pub struct SimpleQuery {
74    pub request: QueryRequest,
75}
76
77impl QueryCreator<RpcQueryRequest> for SimpleQuery {
78    type RpcReference = BlockReference;
79    fn create_query(
80        &self,
81        _network: &NetworkConfig,
82        reference: BlockReference,
83    ) -> ResultWithMethod<RpcQueryRequest, RpcQueryRequest> {
84        Ok(RpcQueryRequest {
85            block_reference: reference,
86            request: self.request.clone(),
87        })
88    }
89
90    fn is_critical_error(
91        &self,
92        error: &near_jsonrpc_client::errors::JsonRpcError<RpcQueryError>,
93    ) -> bool {
94        is_critical_query_error(error)
95    }
96}
97
98#[derive(Clone, Debug)]
99pub struct SimpleValidatorRpc;
100
101impl QueryCreator<RpcValidatorRequest> for SimpleValidatorRpc {
102    type RpcReference = EpochReference;
103    fn create_query(
104        &self,
105        _network: &NetworkConfig,
106        reference: EpochReference,
107    ) -> ResultWithMethod<RpcValidatorRequest, RpcValidatorRequest> {
108        Ok(RpcValidatorRequest {
109            epoch_reference: reference,
110        })
111    }
112
113    fn is_critical_error(
114        &self,
115        error: &near_jsonrpc_client::errors::JsonRpcError<RpcValidatorError>,
116    ) -> bool {
117        is_critical_validator_error(error)
118    }
119}
120
121#[derive(Clone, Debug)]
122pub struct SimpleBlockRpc;
123
124impl QueryCreator<RpcBlockRequest> for SimpleBlockRpc {
125    type RpcReference = BlockReference;
126    fn create_query(
127        &self,
128        _network: &NetworkConfig,
129        reference: BlockReference,
130    ) -> ResultWithMethod<RpcBlockRequest, RpcBlockRequest> {
131        Ok(RpcBlockRequest {
132            block_reference: reference,
133        })
134    }
135
136    fn is_critical_error(
137        &self,
138        error: &near_jsonrpc_client::errors::JsonRpcError<RpcBlockError>,
139    ) -> bool {
140        is_critical_blocks_error(error)
141    }
142}
143
144pub type QueryBuilder<T> = RpcBuilder<T, RpcQueryRequest, BlockReference>;
145pub type MultiQueryBuilder<T> = MultiRpcBuilder<T, RpcQueryRequest, BlockReference>;
146
147pub type ValidatorQueryBuilder<T> = RpcBuilder<T, RpcValidatorRequest, EpochReference>;
148pub type BlockQueryBuilder<T> = RpcBuilder<T, RpcBlockRequest, BlockReference>;
149
150/// A builder for querying multiple items at once.
151///
152/// Sometimes to construct some complex type, you would need to query multiple items at once, and combine them into one.
153/// This is where this builder comes in handy. Almost every time, you would want to use [Self::map] method to combine the responses into your desired type.
154///
155/// Currently, `MultiQueryHandler` supports tuples of sizes 2 and 3.
156/// For single responses, use `QueryBuilder` instead.
157///
158/// Here is a list of examples on how to use this:
159/// - [Tokens::ft_balance](crate::tokens::Tokens::ft_balance)
160/// - [StakingPool::staking_pool_info](crate::stake::Staking::staking_pool_info)
161pub struct MultiRpcBuilder<Handler, Method, Reference>
162where
163    Reference: Send + Sync,
164    Handler: Send + Sync,
165{
166    reference: Reference,
167    requests: Vec<Arc<dyn QueryCreator<Method, RpcReference = Reference> + Send + Sync>>,
168    handler: Handler,
169}
170
171impl<Handler, Method, Reference> MultiRpcBuilder<Handler, Method, Reference>
172where
173    Reference: Send + Sync,
174    Handler: Default + Send + Sync,
175{
176    pub fn with_reference(reference: impl Into<Reference>) -> Self {
177        Self {
178            reference: reference.into(),
179            requests: vec![],
180            handler: Default::default(),
181        }
182    }
183}
184
185impl<Handler, Method, Reference> MultiRpcBuilder<Handler, Method, Reference>
186where
187    Handler: ResponseHandler<QueryResponse = Method::Response, Method = Method> + Send + Sync,
188    Method: RpcMethod + std::fmt::Debug + Send + Sync + 'static,
189    Method::Response: std::fmt::Debug + Send + Sync,
190    Method::Error: std::fmt::Display + std::fmt::Debug + Sync + Send,
191    Reference: Clone + Send + Sync,
192{
193    pub fn new(handler: Handler, reference: Reference) -> Self {
194        Self {
195            reference,
196            requests: vec![],
197            handler,
198        }
199    }
200
201    /// Map response of the queries to another type. The `map` function is executed after the queries are fetched.
202    ///
203    /// The `Handler::Response` is the type returned by the handler's `process_response` method.
204    ///
205    /// For single responses, use `QueryBuilder` instead.
206    ///
207    /// ## Example
208    /// ```rust,no_run
209    /// use near_api::advanced::{MultiQueryHandler, CallResultHandler, MultiRpcBuilder};
210    /// use near_api::types::Data;
211    /// use std::marker::PhantomData;
212    /// use near_primitives::types::BlockReference;
213    ///
214    /// // Create a handler for multiple query responses and specify the types of the responses
215    /// let handler = MultiQueryHandler::new((
216    ///     CallResultHandler::<String>::new(),
217    ///     CallResultHandler::<u128>::new(),
218    /// ));
219    ///
220    /// // Create the builder with the handler
221    /// let builder = MultiRpcBuilder::new(handler, BlockReference::latest());
222    ///
223    /// // Add queries to the builder
224    /// builder.add_query(todo!());
225    ///
226    /// // Map the tuple of responses to a combined type
227    /// let mapped_builder = builder.map(|(response1, response2): (Data<String>, Data<u128>)| {
228    ///     // Process the combined data
229    ///     format!("{}: {}", response1.data, response2.data)
230    /// });
231    /// ```
232    ///
233    /// See [Tokens::ft_balance](crate::tokens::Tokens::ft_balance) implementation for a real-world example.
234    pub fn map<MappedType>(
235        self,
236        map: impl Fn(Handler::Response) -> MappedType + Send + Sync + 'static,
237    ) -> MultiRpcBuilder<PostprocessHandler<MappedType, Handler>, Method, Reference> {
238        MultiRpcBuilder {
239            handler: PostprocessHandler::new(self.handler, map),
240            requests: self.requests,
241            reference: self.reference,
242        }
243    }
244
245    /// Add a query to the queried items. Sometimes you might need to query multiple items at once.
246    /// To combine the result of multiple queries into one.
247    pub fn add_query(
248        mut self,
249        request: Arc<dyn QueryCreator<Method, RpcReference = Reference> + Send + Sync>,
250    ) -> Self {
251        self.requests.push(request);
252        self
253    }
254
255    /// It might be easier to use this method to add a query builder to the queried items.
256    pub fn add_query_builder<T>(mut self, query_builder: RpcBuilder<T, Method, Reference>) -> Self {
257        self.requests.push(query_builder.request);
258        self
259    }
260
261    /// Set the block reference for the queries.
262    pub fn at(self, reference: impl Into<Reference>) -> Self {
263        Self {
264            reference: reference.into(),
265            ..self
266        }
267    }
268
269    /// Fetch the queries from the provided network.
270    #[instrument(skip(self, network), fields(request_count = self.requests.len()))]
271    pub async fn fetch_from(
272        self,
273        network: &NetworkConfig,
274    ) -> ResultWithMethod<Handler::Response, Method> {
275        debug!(target: QUERY_EXECUTOR_TARGET, "Preparing queries");
276        let requests: Vec<_> = self
277            .requests
278            .into_iter()
279            .map(|request| {
280                request
281                    .create_query(network, self.reference.clone())
282                    .map(|query| (query, request))
283            })
284            .collect::<Result<_, _>>()?;
285
286        info!(target: QUERY_EXECUTOR_TARGET, "Sending {} queries", requests.len());
287        let requests = requests.into_iter().map(|(query, request)| async move {
288            retry(network.clone(), |json_rpc_client| {
289                let query = &query;
290                let request = &request;
291
292                async move {
293                    let result = match json_rpc_client.call(&query).await {
294                        Ok(result) => RetryResponse::Ok(result),
295                        Err(err) if request.is_critical_error(&err) => RetryResponse::Critical(err),
296                        Err(err) => RetryResponse::Retry(err),
297                    };
298                    tracing::debug!(
299                        target: QUERY_EXECUTOR_TARGET,
300                        "Querying RPC with {:?} resulted in {:?}",
301                        query,
302                        result
303                    );
304                    result
305                }
306            })
307            .await
308        });
309
310        let requests: Vec<_> = join_all(requests)
311            .await
312            .into_iter()
313            .collect::<Result<_, _>>()?;
314        if requests.is_empty() {
315            error!(target: QUERY_EXECUTOR_TARGET, "No responses received");
316            return Err(QueryError::InternalErrorNoResponse);
317        }
318
319        debug!(target: QUERY_EXECUTOR_TARGET, "Processing {} responses", requests.len());
320        self.handler.process_response(requests)
321    }
322
323    /// Fetch the queries from the default mainnet network configuration.
324    pub async fn fetch_from_mainnet(self) -> ResultWithMethod<Handler::Response, Method> {
325        let network = NetworkConfig::mainnet();
326        self.fetch_from(&network).await
327    }
328
329    /// Fetch the queries from the default testnet network configuration.
330    pub async fn fetch_from_testnet(self) -> ResultWithMethod<Handler::Response, Method> {
331        let network = NetworkConfig::testnet();
332        self.fetch_from(&network).await
333    }
334}
335
336pub struct RpcBuilder<Handler, Method, Reference> {
337    reference: Reference,
338    request: Arc<dyn QueryCreator<Method, RpcReference = Reference> + Send + Sync>,
339    handler: Handler,
340}
341
342impl<Handler, Method, Reference> RpcBuilder<Handler, Method, Reference>
343where
344    Handler: ResponseHandler<QueryResponse = Method::Response, Method = Method> + Send + Sync,
345    Method: RpcMethod + std::fmt::Debug + Send + Sync + 'static,
346    Method::Response: std::fmt::Debug + Send + Sync,
347    Method::Error: std::fmt::Display + std::fmt::Debug + Sync + Send,
348    Reference: Send + Sync,
349{
350    pub fn new(
351        request: impl QueryCreator<Method, RpcReference = Reference> + 'static + Send + Sync,
352        reference: Reference,
353        handler: Handler,
354    ) -> Self {
355        Self {
356            reference,
357            request: Arc::new(request),
358            handler,
359        }
360    }
361
362    /// Set the block reference for the query.
363    pub fn at(self, reference: impl Into<Reference>) -> Self {
364        Self {
365            reference: reference.into(),
366            ..self
367        }
368    }
369
370    /// Post-process the response of the query.
371    ///
372    /// This is useful if you want to convert one type to another.
373    ///
374    /// ## Example
375    /// ```rust,no_run
376    /// use near_api::*;
377    ///
378    /// # async fn example() -> Result<(), Box<dyn std::error::Error>> {
379    /// let balance: NearToken = Contract("some_contract.testnet".parse()?)
380    ///         .call_function("get_balance", ())?
381    ///         .read_only()
382    ///         .map(|balance: Data<u128>| NearToken::from_yoctonear(balance.data))
383    ///         .fetch_from_testnet()
384    ///         .await?;
385    /// println!("Balance: {}", balance);
386    /// # Ok(())
387    /// # }
388    /// ```
389    pub fn map<MappedType>(
390        self,
391        map: impl Fn(Handler::Response) -> MappedType + Send + Sync + 'static,
392    ) -> RpcBuilder<PostprocessHandler<MappedType, Handler>, Method, Reference> {
393        RpcBuilder {
394            handler: PostprocessHandler::new(self.handler, map),
395            request: self.request,
396            reference: self.reference,
397        }
398    }
399
400    /// Fetch the query from the provided network.
401    #[instrument(skip(self, network))]
402    pub async fn fetch_from(
403        self,
404        network: &NetworkConfig,
405    ) -> ResultWithMethod<Handler::Response, Method> {
406        debug!(target: QUERY_EXECUTOR_TARGET, "Preparing query");
407        let query = self.request.create_query(network, self.reference)?;
408
409        let query_response = retry(network.clone(), |json_rpc_client| {
410            let query = &query;
411            let request = &self.request;
412            async move {
413                let result = match json_rpc_client.call(&query).await {
414                    Ok(result) => RetryResponse::Ok(result),
415                    Err(err) if request.is_critical_error(&err) => RetryResponse::Critical(err),
416                    Err(err) => RetryResponse::Retry(err),
417                };
418                tracing::debug!(
419                    target: QUERY_EXECUTOR_TARGET,
420                    "Querying RPC with {:?} resulted in {:?}",
421                    query,
422                    result
423                );
424                result
425            }
426        })
427        .await?;
428
429        debug!(target: QUERY_EXECUTOR_TARGET, "Processing query response");
430        self.handler.process_response(vec![query_response])
431    }
432
433    /// Fetch the query from the default mainnet network configuration.
434    pub async fn fetch_from_mainnet(self) -> ResultWithMethod<Handler::Response, Method> {
435        let network = NetworkConfig::mainnet();
436        self.fetch_from(&network).await
437    }
438
439    /// Fetch the query from the default testnet network configuration.
440    pub async fn fetch_from_testnet(self) -> ResultWithMethod<Handler::Response, Method> {
441        let network = NetworkConfig::testnet();
442        self.fetch_from(&network).await
443    }
444}
445
446#[derive(Clone, Debug)]
447pub struct MultiQueryHandler<Handlers> {
448    handlers: Handlers,
449}
450
451impl<QR, Method, H1, H2, R1, R2> ResponseHandler for MultiQueryHandler<(H1, H2)>
452where
453    Method: RpcMethod,
454    H1: ResponseHandler<QueryResponse = QR, Response = R1, Method = Method>,
455    H2: ResponseHandler<QueryResponse = QR, Response = R2, Method = Method>,
456    Method::Error: std::fmt::Display + std::fmt::Debug,
457{
458    type Response = (R1, R2);
459    type QueryResponse = QR;
460    type Method = Method;
461
462    fn process_response(&self, mut responses: Vec<QR>) -> ResultWithMethod<Self::Response, Method> {
463        let (h1, h2) = &self.handlers;
464
465        let first_response =
466            h1.process_response(responses.drain(0..h1.request_amount()).collect())?;
467        let second_response = h2.process_response(responses)?;
468
469        Ok((first_response, second_response))
470    }
471
472    fn request_amount(&self) -> usize {
473        self.handlers.0.request_amount() + self.handlers.1.request_amount()
474    }
475}
476
477impl<QR, Method, H1, H2, H3, R1, R2, R3> ResponseHandler for MultiQueryHandler<(H1, H2, H3)>
478where
479    Method: RpcMethod,
480    Method::Error: std::fmt::Display + std::fmt::Debug,
481    H1: ResponseHandler<QueryResponse = QR, Response = R1, Method = Method>,
482    H2: ResponseHandler<QueryResponse = QR, Response = R2, Method = Method>,
483    H3: ResponseHandler<QueryResponse = QR, Response = R3, Method = Method>,
484{
485    type Response = (R1, R2, R3);
486    type QueryResponse = QR;
487    type Method = Method;
488
489    fn process_response(&self, mut responses: Vec<QR>) -> ResultWithMethod<Self::Response, Method> {
490        let (h1, h2, h3) = &self.handlers;
491
492        let first_response =
493            h1.process_response(responses.drain(0..h1.request_amount()).collect())?;
494        let second_response = h2.process_response(
495            responses
496                .drain(h1.request_amount()..h2.request_amount())
497                .collect(),
498        )?;
499        let third_response = h3.process_response(responses)?;
500
501        Ok((first_response, second_response, third_response))
502    }
503
504    fn request_amount(&self) -> usize {
505        self.handlers.0.request_amount() + self.handlers.1.request_amount()
506    }
507}
508
509impl<Handlers> MultiQueryHandler<Handlers> {
510    pub const fn new(handlers: Handlers) -> Self {
511        Self { handlers }
512    }
513}
514
515impl<Handlers: Default> Default for MultiQueryHandler<Handlers> {
516    fn default() -> Self {
517        Self::new(Default::default())
518    }
519}
520
521pub struct PostprocessHandler<PostProcessed, Handler: ResponseHandler>
522where
523    <Handler::Method as RpcMethod>::Error: std::fmt::Display + std::fmt::Debug,
524{
525    post_process: Box<dyn Fn(Handler::Response) -> PostProcessed + Send + Sync>,
526    handler: Handler,
527}
528
529impl<PostProcessed, Handler: ResponseHandler> PostprocessHandler<PostProcessed, Handler>
530where
531    <Handler::Method as RpcMethod>::Error: std::fmt::Display + std::fmt::Debug,
532{
533    pub fn new<F>(handler: Handler, post_process: F) -> Self
534    where
535        F: Fn(Handler::Response) -> PostProcessed + Send + Sync + 'static,
536    {
537        Self {
538            post_process: Box::new(post_process),
539            handler,
540        }
541    }
542}
543
544impl<PostProcessed, Handler> ResponseHandler for PostprocessHandler<PostProcessed, Handler>
545where
546    Handler: ResponseHandler,
547    <Handler::Method as RpcMethod>::Error: std::fmt::Display + std::fmt::Debug,
548{
549    type Response = PostProcessed;
550    type QueryResponse = Handler::QueryResponse;
551    type Method = Handler::Method;
552
553    fn process_response(
554        &self,
555        response: Vec<Self::QueryResponse>,
556    ) -> ResultWithMethod<Self::Response, Self::Method> {
557        trace!(target: QUERY_EXECUTOR_TARGET, "Processing response with postprocessing, response count: {}", response.len());
558        Handler::process_response(&self.handler, response).map(|data| {
559            trace!(target: QUERY_EXECUTOR_TARGET, "Applying postprocessing");
560            (self.post_process)(data)
561        })
562    }
563
564    fn request_amount(&self) -> usize {
565        self.handler.request_amount()
566    }
567}
568
569#[derive(Default, Debug, Clone)]
570pub struct CallResultHandler<Response: Send + Sync>(PhantomData<Response>);
571
572impl<Response: Send + Sync> CallResultHandler<Response> {
573    pub const fn new() -> Self {
574        Self(PhantomData::<Response>)
575    }
576}
577
578impl<Response> ResponseHandler for CallResultHandler<Response>
579where
580    Response: DeserializeOwned + Send + Sync,
581{
582    type Response = Data<Response>;
583    type QueryResponse = RpcQueryResponse;
584    type Method = RpcQueryRequest;
585
586    fn process_response(
587        &self,
588        response: Vec<RpcQueryResponse>,
589    ) -> ResultWithMethod<Self::Response, Self::Method> {
590        let response = response
591            .into_iter()
592            .next()
593            .ok_or(QueryError::InternalErrorNoResponse)?;
594
595        if let near_jsonrpc_primitives::types::query::QueryResponseKind::CallResult(result) =
596            response.kind
597        {
598            trace!(target: QUERY_EXECUTOR_TARGET, "Deserializing CallResult, result size: {} bytes", result.result.len());
599            let data: Response = serde_json::from_slice(&result.result)?;
600            Ok(Data {
601                data,
602                block_height: response.block_height,
603                block_hash: response.block_hash.into(),
604            })
605        } else {
606            warn!(target: QUERY_EXECUTOR_TARGET, "Unexpected response kind: {:?}", response.kind);
607            Err(QueryError::UnexpectedResponse {
608                expected: "CallResult",
609                got: Box::new(response.kind),
610            })
611        }
612    }
613}
614
615#[derive(Default, Debug, Clone)]
616pub struct AccountViewHandler;
617
618impl ResponseHandler for AccountViewHandler {
619    type QueryResponse = RpcQueryResponse;
620    type Response = Data<AccountView>;
621    type Method = RpcQueryRequest;
622
623    fn process_response(
624        &self,
625        response: Vec<RpcQueryResponse>,
626    ) -> ResultWithMethod<Self::Response, Self::Method> {
627        let response = response
628            .into_iter()
629            .next()
630            .ok_or(QueryError::InternalErrorNoResponse)?;
631
632        if let near_jsonrpc_primitives::types::query::QueryResponseKind::ViewAccount(account) =
633            response.kind
634        {
635            info!(
636                target: QUERY_EXECUTOR_TARGET,
637                "Processed ViewAccount response: balance: {}, locked: {}",
638                 account.amount, account.locked
639            );
640            Ok(Data {
641                data: account,
642                block_height: response.block_height,
643                block_hash: response.block_hash.into(),
644            })
645        } else {
646            warn!(target: QUERY_EXECUTOR_TARGET, "Unexpected response kind: {:?}", response.kind);
647            Err(QueryError::UnexpectedResponse {
648                expected: "ViewAccount",
649                got: Box::new(response.kind),
650            })
651        }
652    }
653}
654
655#[derive(Default, Debug, Clone)]
656pub struct AccessKeyListHandler;
657
658impl ResponseHandler for AccessKeyListHandler {
659    type Response = AccessKeyList;
660    type QueryResponse = RpcQueryResponse;
661    type Method = RpcQueryRequest;
662
663    fn process_response(
664        &self,
665        response: Vec<RpcQueryResponse>,
666    ) -> ResultWithMethod<Self::Response, Self::Method> {
667        let response = response
668            .into_iter()
669            .next()
670            .ok_or(QueryError::InternalErrorNoResponse)?;
671        if let near_jsonrpc_primitives::types::query::QueryResponseKind::AccessKeyList(
672            access_key_list,
673        ) = response.kind
674        {
675            info!(
676                target: QUERY_EXECUTOR_TARGET,
677                "Processed AccessKeyList response, keys count: {}",
678                access_key_list.keys.len()
679            );
680            Ok(access_key_list)
681        } else {
682            warn!(target: QUERY_EXECUTOR_TARGET, "Unexpected response kind: {:?}", response.kind);
683            Err(QueryError::UnexpectedResponse {
684                expected: "AccessKeyList",
685                got: Box::new(response.kind),
686            })
687        }
688    }
689}
690
691#[derive(Default, Debug, Clone)]
692pub struct AccessKeyHandler;
693
694impl ResponseHandler for AccessKeyHandler {
695    type Response = Data<AccessKeyView>;
696    type QueryResponse = RpcQueryResponse;
697    type Method = RpcQueryRequest;
698
699    fn process_response(
700        &self,
701        response: Vec<RpcQueryResponse>,
702    ) -> ResultWithMethod<Self::Response, Self::Method> {
703        let response = response
704            .into_iter()
705            .next()
706            .ok_or(QueryError::InternalErrorNoResponse)?;
707        if let near_jsonrpc_primitives::types::query::QueryResponseKind::AccessKey(key) =
708            response.kind
709        {
710            info!(
711                target: QUERY_EXECUTOR_TARGET,
712                "Processed AccessKey response, nonce: {}, permission: {:?}",
713                key.nonce,
714                key.permission
715            );
716            Ok(Data {
717                data: key,
718                block_height: response.block_height,
719                block_hash: response.block_hash.into(),
720            })
721        } else {
722            warn!(target: QUERY_EXECUTOR_TARGET, "Unexpected response kind: {:?}", response.kind);
723            Err(QueryError::UnexpectedResponse {
724                expected: "AccessKey",
725                got: Box::new(response.kind),
726            })
727        }
728    }
729}
730
731#[derive(Default, Debug, Clone)]
732pub struct ViewStateHandler;
733
734impl ResponseHandler for ViewStateHandler {
735    type Response = Data<ViewStateResult>;
736    type QueryResponse = RpcQueryResponse;
737    type Method = RpcQueryRequest;
738
739    fn process_response(
740        &self,
741        response: Vec<RpcQueryResponse>,
742    ) -> ResultWithMethod<Self::Response, Self::Method> {
743        let response = response
744            .into_iter()
745            .next()
746            .ok_or(QueryError::InternalErrorNoResponse)?;
747        if let near_jsonrpc_primitives::types::query::QueryResponseKind::ViewState(data) =
748            response.kind
749        {
750            info!(
751                target: QUERY_EXECUTOR_TARGET,
752                "Processed ViewState response, values count: {}, proof nodes: {}",
753                data.values.len(),
754                data.proof.len()
755            );
756            Ok(Data {
757                data,
758                block_height: response.block_height,
759                block_hash: response.block_hash.into(),
760            })
761        } else {
762            warn!(target: QUERY_EXECUTOR_TARGET, "Unexpected response kind: {:?}", response.kind);
763            Err(QueryError::UnexpectedResponse {
764                expected: "ViewState",
765                got: Box::new(response.kind),
766            })
767        }
768    }
769}
770
771#[derive(Default, Debug, Clone)]
772pub struct ViewCodeHandler;
773
774impl ResponseHandler for ViewCodeHandler {
775    type Response = Data<ContractCodeView>;
776    type QueryResponse = RpcQueryResponse;
777    type Method = RpcQueryRequest;
778
779    fn process_response(
780        &self,
781        response: Vec<RpcQueryResponse>,
782    ) -> ResultWithMethod<Self::Response, Self::Method> {
783        let response = response
784            .into_iter()
785            .next()
786            .ok_or(QueryError::InternalErrorNoResponse)?;
787        if let near_jsonrpc_primitives::types::query::QueryResponseKind::ViewCode(code) =
788            response.kind
789        {
790            info!(
791                target: QUERY_EXECUTOR_TARGET,
792                "Processed ViewCode response, code size: {} bytes, hash: {:?}",
793                code.code.len(),
794                code.hash
795            );
796            Ok(Data {
797                data: code,
798                block_height: response.block_height,
799                block_hash: response.block_hash.into(),
800            })
801        } else {
802            warn!(target: QUERY_EXECUTOR_TARGET, "Unexpected response kind: {:?}", response.kind);
803            Err(QueryError::UnexpectedResponse {
804                expected: "ViewCode",
805                got: Box::new(response.kind),
806            })
807        }
808    }
809}
810
811#[derive(Clone, Debug)]
812pub struct RpcValidatorHandler;
813
814impl ResponseHandler for RpcValidatorHandler {
815    type Response = EpochValidatorInfo;
816    type QueryResponse = EpochValidatorInfo;
817    type Method = RpcValidatorRequest;
818
819    fn process_response(
820        &self,
821        response: Vec<EpochValidatorInfo>,
822    ) -> ResultWithMethod<Self::Response, Self::Method> {
823        let response = response
824            .into_iter()
825            .next()
826            .ok_or(QueryError::InternalErrorNoResponse)?;
827
828        info!(
829            target: QUERY_EXECUTOR_TARGET,
830            "Processed EpochValidatorInfo response, epoch height: {}, validators count: {}",
831            response.epoch_height,
832            response.current_validators.len()
833        );
834        Ok(response)
835    }
836}
837
838#[derive(Clone, Debug)]
839pub struct RpcBlockHandler;
840
841impl ResponseHandler for RpcBlockHandler {
842    type Response = BlockView;
843    type QueryResponse = BlockView;
844    type Method = RpcBlockRequest;
845
846    fn process_response(
847        &self,
848        response: Vec<BlockView>,
849    ) -> ResultWithMethod<Self::Response, Self::Method> {
850        let response = response
851            .into_iter()
852            .next()
853            .ok_or(QueryError::InternalErrorNoResponse)?;
854
855        info!(
856            target: QUERY_EXECUTOR_TARGET,
857            "Processed Block response, height: {}, hash: {:?}",
858            response.header.height,
859            response.header.hash
860        );
861        Ok(response)
862    }
863}
864
865impl ResponseHandler for () {
866    type Response = ();
867    type QueryResponse = RpcQueryResponse;
868    type Method = RpcQueryRequest;
869
870    fn process_response(
871        &self,
872        _response: Vec<RpcQueryResponse>,
873    ) -> ResultWithMethod<Self::Response, Self::Method> {
874        trace!(target: QUERY_EXECUTOR_TARGET, "Processed empty response handler");
875        Ok(())
876    }
877}