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 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}