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