near_api/common/query/handlers/
mod.rs

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