hedera/query/
any.rs

1// SPDX-License-Identifier: Apache-2.0
2
3use hedera_proto::services;
4use tonic::transport::Channel;
5
6use super::ToQueryProtobuf;
7use crate::account::{
8    AccountBalanceQueryData,
9    AccountInfoQueryData,
10    AccountRecordsQueryData,
11};
12use crate::contract::{
13    ContractBytecodeQueryData,
14    ContractCallQueryData,
15    ContractInfoQueryData,
16};
17use crate::entity_id::ValidateChecksums;
18use crate::file::{
19    FileContentsQueryData,
20    FileInfoQueryData,
21};
22use crate::ledger_id::RefLedgerId;
23use crate::query::QueryExecute;
24use crate::schedule::ScheduleInfoQueryData;
25use crate::token::{
26    TokenInfoQueryData,
27    TokenNftInfoQueryData,
28};
29use crate::topic::TopicInfoQueryData;
30use crate::transaction_receipt_query::TransactionReceiptQueryData;
31use crate::{
32    AccountBalance,
33    AccountInfo,
34    AllProxyStakers,
35    BoxGrpcFuture,
36    ContractFunctionResult,
37    ContractInfo,
38    Error,
39    FileContentsResponse,
40    FileInfo,
41    FromProtobuf,
42    Hbar,
43    NetworkVersionInfo,
44    NetworkVersionInfoQueryData,
45    Query,
46    ScheduleInfo,
47    TokenInfo,
48    TokenNftInfo,
49    TopicInfo,
50    TransactionReceipt,
51    TransactionRecord,
52    TransactionRecordQueryData,
53};
54
55/// Any possible query that may be executed on the Hiero network.
56pub type AnyQuery = Query<AnyQueryData>;
57
58#[derive(Debug, Clone)]
59pub enum AnyQueryData {
60    AccountBalance(AccountBalanceQueryData),
61    AccountInfo(AccountInfoQueryData),
62    AccountRecords(AccountRecordsQueryData),
63    TransactionReceipt(TransactionReceiptQueryData),
64    TransactionRecord(TransactionRecordQueryData),
65    FileContents(FileContentsQueryData),
66    FileInfo(FileInfoQueryData),
67    ContractBytecode(ContractBytecodeQueryData),
68    ContractCall(ContractCallQueryData),
69    TokenInfo(TokenInfoQueryData),
70    ContractInfo(ContractInfoQueryData),
71    TokenNftInfo(TokenNftInfoQueryData),
72    TopicInfo(TopicInfoQueryData),
73    ScheduleInfo(ScheduleInfoQueryData),
74    NetworkVersionInfo(NetworkVersionInfoQueryData),
75}
76
77// todo: strategically box fields of variants, rather than the entire structs.
78/// Common response type for *all* queries.
79#[derive(Debug, Clone)]
80pub enum AnyQueryResponse {
81    /// Response from [`AccountBalanceQuery`](crate::AccountBalanceQuery).
82    AccountBalance(AccountBalance),
83
84    /// Response from [`AccountInfoQuery`](crate::AccountInfoQuery).
85    AccountInfo(AccountInfo),
86
87    /// Response from [`AccountStakersQuery`](crate::AccountStakersQuery).
88    AccountStakers(AllProxyStakers),
89
90    /// Response from [`AccountRecordsQuery`](crate::AccountRecordsQuery).
91    AccountRecords(Vec<TransactionRecord>),
92
93    /// Response from [`TransactionReceiptQuery`](crate::TransactionReceiptQuery).
94    TransactionReceipt(TransactionReceipt),
95
96    /// Response from [`TransactionRecordQuery`](crate::TransactionRecordQuery).
97    TransactionRecord(Box<TransactionRecord>),
98
99    /// Response from [`FileContentsQuery`](crate::FileContentsQuery).
100    FileContents(FileContentsResponse),
101
102    /// Response from [`FileInfoQuery`](crate::FileInfoQuery).
103    FileInfo(FileInfo),
104
105    /// Response from [`ContractBytecodeQuery`](crate::ContractBytecodeQuery).
106    ContractBytecode(Vec<u8>),
107
108    /// Response from [`ContractCallQuery`](crate::ContractCallQuery).
109    ContractCall(ContractFunctionResult),
110
111    /// Response from [`TokenInfoQuery`](crate::TokenInfoQuery).
112    TokenInfo(Box<TokenInfo>),
113
114    /// Response from [`TopicInfoQuery`](crate::TopicInfoQuery).
115    TopicInfo(TopicInfo),
116
117    /// Response from [`ContractInfoQuery`](crate::ContractInfoQuery).
118    ContractInfo(ContractInfo),
119
120    /// Response from [`TokenNftInfoQuery`](crate::TokenNftInfoQuery).
121    TokenNftInfo(TokenNftInfo),
122
123    /// Response from [`ScheduleInfoQuery`](crate::ScheduleInfoQuery).
124    ScheduleInfo(ScheduleInfo),
125
126    /// Response from [`NetworkVersionInfoQuery`](crate::NetworkVersionInfoQuery).
127    NetworkVersionInfo(NetworkVersionInfo),
128}
129
130impl ToQueryProtobuf for AnyQueryData {
131    fn to_query_protobuf(&self, header: services::QueryHeader) -> services::Query {
132        match self {
133            Self::AccountBalance(data) => data.to_query_protobuf(header),
134            Self::AccountInfo(data) => data.to_query_protobuf(header),
135            Self::AccountRecords(data) => data.to_query_protobuf(header),
136            Self::TransactionReceipt(data) => data.to_query_protobuf(header),
137            Self::TransactionRecord(data) => data.to_query_protobuf(header),
138            Self::FileContents(data) => data.to_query_protobuf(header),
139            Self::FileInfo(data) => data.to_query_protobuf(header),
140            Self::ContractBytecode(data) => data.to_query_protobuf(header),
141            Self::ContractCall(data) => data.to_query_protobuf(header),
142            Self::ContractInfo(data) => data.to_query_protobuf(header),
143            Self::TokenNftInfo(data) => data.to_query_protobuf(header),
144            Self::TokenInfo(data) => data.to_query_protobuf(header),
145            Self::TopicInfo(data) => data.to_query_protobuf(header),
146            Self::ScheduleInfo(data) => data.to_query_protobuf(header),
147            Self::NetworkVersionInfo(data) => data.to_query_protobuf(header),
148        }
149    }
150}
151
152impl QueryExecute for AnyQueryData {
153    type Response = AnyQueryResponse;
154
155    fn is_payment_required(&self) -> bool {
156        match self {
157            Self::AccountInfo(query) => query.is_payment_required(),
158            Self::AccountBalance(query) => query.is_payment_required(),
159            Self::AccountRecords(query) => query.is_payment_required(),
160            Self::TransactionReceipt(query) => query.is_payment_required(),
161            Self::TransactionRecord(query) => query.is_payment_required(),
162            Self::FileContents(query) => query.is_payment_required(),
163            Self::FileInfo(query) => query.is_payment_required(),
164            Self::ContractBytecode(query) => query.is_payment_required(),
165            Self::ContractCall(query) => query.is_payment_required(),
166            Self::ContractInfo(query) => query.is_payment_required(),
167            Self::TokenNftInfo(query) => query.is_payment_required(),
168            Self::TokenInfo(query) => query.is_payment_required(),
169            Self::TopicInfo(query) => query.is_payment_required(),
170            Self::ScheduleInfo(query) => query.is_payment_required(),
171            Self::NetworkVersionInfo(query) => query.is_payment_required(),
172        }
173    }
174
175    fn map_cost(&self, cost: Hbar) -> Hbar {
176        match self {
177            Self::AccountInfo(query) => query.map_cost(cost),
178            Self::AccountBalance(query) => query.map_cost(cost),
179            Self::AccountRecords(query) => query.map_cost(cost),
180            Self::TransactionReceipt(query) => query.map_cost(cost),
181            Self::TransactionRecord(query) => query.map_cost(cost),
182            Self::FileContents(query) => query.map_cost(cost),
183            Self::FileInfo(query) => query.map_cost(cost),
184            Self::ContractBytecode(query) => query.map_cost(cost),
185            Self::ContractCall(query) => query.map_cost(cost),
186            Self::ContractInfo(query) => query.map_cost(cost),
187            Self::TokenNftInfo(query) => query.map_cost(cost),
188            Self::TokenInfo(query) => query.map_cost(cost),
189            Self::TopicInfo(query) => query.map_cost(cost),
190            Self::ScheduleInfo(query) => query.map_cost(cost),
191            Self::NetworkVersionInfo(query) => query.map_cost(cost),
192        }
193    }
194
195    fn execute(
196        &self,
197        channel: Channel,
198        request: services::Query,
199    ) -> BoxGrpcFuture<'_, services::Response> {
200        match self {
201            Self::AccountInfo(query) => query.execute(channel, request),
202            Self::AccountBalance(query) => query.execute(channel, request),
203            Self::AccountRecords(query) => query.execute(channel, request),
204            Self::TransactionReceipt(query) => query.execute(channel, request),
205            Self::TransactionRecord(query) => query.execute(channel, request),
206            Self::FileContents(query) => query.execute(channel, request),
207            Self::FileInfo(query) => query.execute(channel, request),
208            Self::ContractBytecode(query) => query.execute(channel, request),
209            Self::ContractCall(query) => query.execute(channel, request),
210            Self::ContractInfo(query) => query.execute(channel, request),
211            Self::TokenNftInfo(query) => query.execute(channel, request),
212            Self::TokenInfo(query) => query.execute(channel, request),
213            Self::TopicInfo(query) => query.execute(channel, request),
214            Self::ScheduleInfo(query) => query.execute(channel, request),
215            Self::NetworkVersionInfo(query) => query.execute(channel, request),
216        }
217    }
218
219    fn should_retry_pre_check(&self, status: crate::Status) -> bool {
220        match self {
221            Self::AccountInfo(query) => query.should_retry_pre_check(status),
222            Self::AccountBalance(query) => query.should_retry_pre_check(status),
223            Self::AccountRecords(query) => query.should_retry_pre_check(status),
224            Self::TransactionReceipt(query) => query.should_retry_pre_check(status),
225            Self::TransactionRecord(query) => query.should_retry_pre_check(status),
226            Self::FileContents(query) => query.should_retry_pre_check(status),
227            Self::FileInfo(query) => query.should_retry_pre_check(status),
228            Self::ContractBytecode(query) => query.should_retry_pre_check(status),
229            Self::ContractCall(query) => query.should_retry_pre_check(status),
230            Self::ContractInfo(query) => query.should_retry_pre_check(status),
231            Self::TokenNftInfo(query) => query.should_retry_pre_check(status),
232            Self::TokenInfo(query) => query.should_retry_pre_check(status),
233            Self::TopicInfo(query) => query.should_retry_pre_check(status),
234            Self::ScheduleInfo(query) => query.should_retry_pre_check(status),
235            Self::NetworkVersionInfo(query) => query.should_retry_pre_check(status),
236        }
237    }
238
239    fn should_retry(&self, response: &services::Response) -> bool {
240        match self {
241            Self::AccountInfo(query) => query.should_retry(response),
242            Self::AccountBalance(query) => query.should_retry(response),
243            Self::AccountRecords(query) => query.should_retry(response),
244            Self::TransactionReceipt(query) => query.should_retry(response),
245            Self::TransactionRecord(query) => query.should_retry(response),
246            Self::FileContents(query) => query.should_retry(response),
247            Self::FileInfo(query) => query.should_retry(response),
248            Self::ContractBytecode(query) => query.should_retry(response),
249            Self::ContractCall(query) => query.should_retry(response),
250            Self::ContractInfo(query) => query.should_retry(response),
251            Self::TokenNftInfo(query) => query.should_retry(response),
252            Self::TokenInfo(query) => query.should_retry(response),
253            Self::TopicInfo(query) => query.should_retry(response),
254            Self::ScheduleInfo(query) => query.should_retry(response),
255            Self::NetworkVersionInfo(query) => query.should_retry(response),
256        }
257    }
258
259    fn transaction_id(&self) -> Option<crate::TransactionId> {
260        match self {
261            Self::AccountBalance(query) => query.transaction_id(),
262            Self::AccountInfo(query) => query.transaction_id(),
263            Self::AccountRecords(query) => query.transaction_id(),
264            Self::TransactionReceipt(query) => query.transaction_id(),
265            Self::TransactionRecord(query) => query.transaction_id(),
266            Self::FileContents(query) => query.transaction_id(),
267            Self::FileInfo(query) => query.transaction_id(),
268            Self::ContractBytecode(query) => query.transaction_id(),
269            Self::ContractCall(query) => query.transaction_id(),
270            Self::TokenInfo(query) => query.transaction_id(),
271            Self::ContractInfo(query) => query.transaction_id(),
272            Self::TokenNftInfo(query) => query.transaction_id(),
273            Self::TopicInfo(query) => query.transaction_id(),
274            Self::ScheduleInfo(query) => query.transaction_id(),
275            Self::NetworkVersionInfo(query) => query.transaction_id(),
276        }
277    }
278
279    fn make_response(
280        &self,
281        response: services::response::Response,
282    ) -> crate::Result<Self::Response> {
283        match self {
284            Self::AccountBalance(query) => {
285                query.make_response(response).map(AnyQueryResponse::AccountBalance)
286            }
287            Self::AccountInfo(query) => {
288                query.make_response(response).map(AnyQueryResponse::AccountInfo)
289            }
290            Self::AccountRecords(query) => {
291                query.make_response(response).map(AnyQueryResponse::AccountRecords)
292            }
293            Self::TransactionReceipt(query) => {
294                query.make_response(response).map(AnyQueryResponse::TransactionReceipt)
295            }
296            Self::TransactionRecord(query) => {
297                query.make_response(response).map(Box::new).map(AnyQueryResponse::TransactionRecord)
298            }
299            Self::FileContents(query) => {
300                query.make_response(response).map(AnyQueryResponse::FileContents)
301            }
302            Self::FileInfo(query) => query.make_response(response).map(AnyQueryResponse::FileInfo),
303            Self::ContractBytecode(query) => {
304                query.make_response(response).map(AnyQueryResponse::ContractBytecode)
305            }
306            Self::ContractCall(query) => {
307                query.make_response(response).map(AnyQueryResponse::ContractCall)
308            }
309            Self::TokenInfo(query) => {
310                query.make_response(response).map(Box::new).map(AnyQueryResponse::TokenInfo)
311            }
312            Self::ContractInfo(query) => {
313                query.make_response(response).map(AnyQueryResponse::ContractInfo)
314            }
315            Self::TokenNftInfo(query) => {
316                query.make_response(response).map(AnyQueryResponse::TokenNftInfo)
317            }
318            Self::TopicInfo(query) => {
319                query.make_response(response).map(AnyQueryResponse::TopicInfo)
320            }
321            Self::ScheduleInfo(query) => {
322                query.make_response(response).map(AnyQueryResponse::ScheduleInfo)
323            }
324            Self::NetworkVersionInfo(query) => {
325                query.make_response(response).map(AnyQueryResponse::NetworkVersionInfo)
326            }
327        }
328    }
329}
330
331impl ValidateChecksums for AnyQueryData {
332    fn validate_checksums(&self, ledger_id: &RefLedgerId) -> Result<(), Error> {
333        match self {
334            Self::AccountBalance(query) => query.validate_checksums(ledger_id),
335            Self::AccountInfo(query) => query.validate_checksums(ledger_id),
336            Self::AccountRecords(query) => query.validate_checksums(ledger_id),
337            Self::TransactionReceipt(query) => query.validate_checksums(ledger_id),
338            Self::TransactionRecord(query) => query.validate_checksums(ledger_id),
339            Self::FileContents(query) => query.validate_checksums(ledger_id),
340            Self::FileInfo(query) => query.validate_checksums(ledger_id),
341            Self::ContractBytecode(query) => query.validate_checksums(ledger_id),
342            Self::ContractCall(query) => query.validate_checksums(ledger_id),
343            Self::TokenInfo(query) => query.validate_checksums(ledger_id),
344            Self::ContractInfo(query) => query.validate_checksums(ledger_id),
345            Self::TokenNftInfo(query) => query.validate_checksums(ledger_id),
346            Self::TopicInfo(query) => query.validate_checksums(ledger_id),
347            Self::ScheduleInfo(query) => query.validate_checksums(ledger_id),
348            Self::NetworkVersionInfo(query) => query.validate_checksums(ledger_id),
349        }
350    }
351}
352
353impl FromProtobuf<services::response::Response> for AnyQueryResponse {
354    fn from_protobuf(response: services::response::Response) -> crate::Result<Self>
355    where
356        Self: Sized,
357    {
358        use services::response::Response::*;
359
360        Ok(match response {
361            TransactionGetReceipt(_) => {
362                Self::TransactionReceipt(TransactionReceipt::from_protobuf(response)?)
363            }
364            CryptoGetInfo(_) => Self::AccountInfo(AccountInfo::from_protobuf(response)?),
365            CryptogetAccountBalance(_) => {
366                Self::AccountBalance(AccountBalance::from_protobuf(response)?)
367            }
368            FileGetContents(_) => {
369                Self::FileContents(FileContentsResponse::from_protobuf(response)?)
370            }
371            ContractGetBytecodeResponse(_) => {
372                Self::ContractBytecode(Vec::<u8>::from_protobuf(response)?)
373            }
374            ContractCallLocal(_) => {
375                Self::ContractCall(ContractFunctionResult::from_protobuf(response)?)
376            }
377            ContractGetInfo(_) => Self::ContractInfo(ContractInfo::from_protobuf(response)?),
378            ConsensusGetTopicInfo(_) => Self::TopicInfo(TopicInfo::from_protobuf(response)?),
379            ScheduleGetInfo(_) => Self::ScheduleInfo(ScheduleInfo::from_protobuf(response)?),
380            CryptoGetProxyStakers(_) => {
381                Self::AccountStakers(AllProxyStakers::from_protobuf(response)?)
382            }
383            CryptoGetAccountRecords(_) => {
384                Self::AccountRecords(Vec::<TransactionRecord>::from_protobuf(response)?)
385            }
386            TransactionGetRecord(_) => {
387                Self::TransactionRecord(Box::new(TransactionRecord::from_protobuf(response)?))
388            }
389            NetworkGetVersionInfo(_) => {
390                Self::NetworkVersionInfo(NetworkVersionInfo::from_protobuf(response)?)
391            }
392            FileGetInfo(_) => Self::FileInfo(FileInfo::from_protobuf(response)?),
393            TokenGetInfo(_) => Self::TokenInfo(Box::new(TokenInfo::from_protobuf(response)?)),
394            TokenGetNftInfo(_) | TokenGetNftInfos(_) => {
395                Self::TokenNftInfo(TokenNftInfo::from_protobuf(response)?)
396            }
397            // Unimplemented on hedera services
398            TransactionGetFastRecord(_)
399            | CryptoGetLiveHash(_)
400            | GetBySolidityId(_)
401            | TokenGetAccountNftInfos(_)
402            | NetworkGetExecutionTime(_)
403            | ContractGetRecordsResponse(_)
404            | AccountDetails(_)
405            | GetByKey(_) => unreachable!(),
406        })
407    }
408}