Skip to main content

hiero_sdk/contract/
contract_call_query.rs

1// SPDX-License-Identifier: Apache-2.0
2
3use hiero_sdk_proto::services;
4use hiero_sdk_proto::services::smart_contract_service_client::SmartContractServiceClient;
5use tonic::transport::Channel;
6
7use crate::ledger_id::RefLedgerId;
8use crate::query::{
9    AnyQueryData,
10    QueryExecute,
11    ToQueryProtobuf,
12};
13use crate::{
14    AccountId,
15    BoxGrpcFuture,
16    ContractFunctionParameters,
17    ContractFunctionResult,
18    ContractId,
19    Error,
20    Query,
21    ToProtobuf,
22    ValidateChecksums,
23};
24
25/// Call a function of the given smart contract instance.
26/// It will consume the entire given amount of gas.
27///
28/// This is performed locally on the particular node that the client is communicating with.
29/// It cannot change the state of the contract instance (and so, cannot spend
30/// anything from the instance's cryptocurrency account).
31///
32pub type ContractCallQuery = Query<ContractCallQueryData>;
33
34#[derive(Default, Debug, Clone)]
35pub struct ContractCallQueryData {
36    /// The contract instance to call.
37    contract_id: Option<ContractId>,
38
39    /// The amount of gas to use for the call.
40    gas: u64,
41
42    /// The function parameters as their raw bytes.
43    function_parameters: Vec<u8>,
44
45    /// The sender for this transaction.
46    sender_account_id: Option<AccountId>,
47}
48
49impl ContractCallQuery {
50    /// Gets the contract instance to call.
51    #[must_use]
52    pub fn get_contract_id(&self) -> Option<ContractId> {
53        self.data.contract_id
54    }
55
56    /// Sets the contract to make a static call against.
57    pub fn contract_id(&mut self, contract_id: ContractId) -> &mut Self {
58        self.data.contract_id = Some(contract_id);
59        self
60    }
61
62    /// Gets the amount of gas to use for the call.
63    #[must_use]
64    pub fn get_gas(&self) -> u64 {
65        self.data.gas
66    }
67
68    /// Sets the amount of gas to use for the call.
69    pub fn gas(&mut self, gas: u64) -> &mut Self {
70        self.data.gas = gas;
71        self
72    }
73
74    /// Gets the function parameters as their raw bytes.
75    #[must_use]
76    pub fn get_contract_parameters(&self) -> &[u8] {
77        self.data.function_parameters.as_ref()
78    }
79
80    /// Sets the function parameters as their raw bytes.
81    pub fn function_parameters(&mut self, data: Vec<u8>) -> &mut Self {
82        self.data.function_parameters = data;
83        self
84    }
85
86    /// Sets the function with no parameters.
87    pub fn function(&mut self, name: &str) -> &mut Self {
88        self.function_with_parameters(name, &ContractFunctionParameters::new())
89    }
90
91    /// Sets the function with parameters.
92    pub fn function_with_parameters(
93        &mut self,
94        name: &str,
95        parameters: &ContractFunctionParameters,
96    ) -> &mut Self {
97        self.function_parameters(parameters.to_bytes(Some(name)))
98    }
99
100    /// Gets the sender for this transaction.
101    #[must_use]
102    pub fn get_sender_account_id(&self) -> Option<AccountId> {
103        self.data.sender_account_id
104    }
105
106    /// Sets the sender for this transaction.
107    pub fn sender_account_id(&mut self, sender_account_id: AccountId) -> &mut Self {
108        self.data.sender_account_id = Some(sender_account_id);
109        self
110    }
111}
112
113impl From<ContractCallQueryData> for AnyQueryData {
114    #[inline]
115    fn from(data: ContractCallQueryData) -> Self {
116        Self::ContractCall(data)
117    }
118}
119
120impl ToQueryProtobuf for ContractCallQueryData {
121    fn to_query_protobuf(&self, header: services::QueryHeader) -> services::Query {
122        let contract_id = self.contract_id.to_protobuf();
123        let sender_id = self.sender_account_id.to_protobuf();
124
125        services::Query {
126            query: Some(services::query::Query::ContractCallLocal(
127                #[allow(deprecated)]
128                services::ContractCallLocalQuery {
129                    contract_id,
130                    gas: self.gas as i64,
131                    function_parameters: self.function_parameters.clone(),
132                    max_result_size: 0,
133                    header: Some(header),
134                    sender_id,
135                },
136            )),
137        }
138    }
139}
140
141impl QueryExecute for ContractCallQueryData {
142    type Response = ContractFunctionResult;
143
144    fn execute(
145        &self,
146        channel: Channel,
147        request: services::Query,
148    ) -> BoxGrpcFuture<'_, services::Response> {
149        Box::pin(async {
150            SmartContractServiceClient::new(channel).contract_call_local_method(request).await
151        })
152    }
153}
154
155impl ValidateChecksums for ContractCallQueryData {
156    fn validate_checksums(&self, ledger_id: &RefLedgerId) -> Result<(), Error> {
157        self.contract_id.validate_checksums(ledger_id)?;
158        self.sender_account_id.validate_checksums(ledger_id)
159    }
160}
161
162#[cfg(test)]
163mod tests {
164    use expect_test::expect;
165    use hiero_sdk_proto::services;
166
167    use crate::query::ToQueryProtobuf;
168    use crate::{
169        AccountId,
170        ContractCallQuery,
171        ContractFunctionParameters,
172        ContractId,
173        Hbar,
174    };
175
176    fn make_query() -> ContractCallQuery {
177        let mut query = ContractCallQuery::new();
178
179        query
180            .contract_id(crate::ContractId::new(0, 0, 5005))
181            .gas(1541)
182            .sender_account_id("1.2.3".parse().unwrap())
183            .max_payment_amount(Hbar::from_tinybars(100_000));
184
185        query
186    }
187
188    #[test]
189    fn serialize() {
190        expect![[r#"
191            Query {
192                query: Some(
193                    ContractCallLocal(
194                        ContractCallLocalQuery {
195                            header: Some(
196                                QueryHeader {
197                                    payment: None,
198                                    response_type: AnswerOnly,
199                                },
200                            ),
201                            contract_id: Some(
202                                ContractId {
203                                    shard_num: 0,
204                                    realm_num: 0,
205                                    contract: Some(
206                                        ContractNum(
207                                            5005,
208                                        ),
209                                    ),
210                                },
211                            ),
212                            gas: 1541,
213                            function_parameters: [
214                                18,
215                                74,
216                                131,
217                                250,
218                                0,
219                                0,
220                                0,
221                                0,
222                                0,
223                                0,
224                                0,
225                                0,
226                                0,
227                                0,
228                                0,
229                                0,
230                                0,
231                                0,
232                                0,
233                                0,
234                                0,
235                                0,
236                                0,
237                                0,
238                                0,
239                                0,
240                                0,
241                                0,
242                                0,
243                                0,
244                                0,
245                                0,
246                                0,
247                                0,
248                                0,
249                                64,
250                                0,
251                                0,
252                                0,
253                                0,
254                                0,
255                                0,
256                                0,
257                                0,
258                                0,
259                                0,
260                                0,
261                                0,
262                                0,
263                                0,
264                                0,
265                                0,
266                                0,
267                                0,
268                                0,
269                                0,
270                                0,
271                                0,
272                                0,
273                                0,
274                                0,
275                                0,
276                                0,
277                                0,
278                                0,
279                                0,
280                                0,
281                                128,
282                                0,
283                                0,
284                                0,
285                                0,
286                                0,
287                                0,
288                                0,
289                                0,
290                                0,
291                                0,
292                                0,
293                                0,
294                                0,
295                                0,
296                                0,
297                                0,
298                                0,
299                                0,
300                                0,
301                                0,
302                                0,
303                                0,
304                                0,
305                                0,
306                                0,
307                                0,
308                                0,
309                                0,
310                                0,
311                                0,
312                                0,
313                                5,
314                                72,
315                                101,
316                                108,
317                                108,
318                                111,
319                                0,
320                                0,
321                                0,
322                                0,
323                                0,
324                                0,
325                                0,
326                                0,
327                                0,
328                                0,
329                                0,
330                                0,
331                                0,
332                                0,
333                                0,
334                                0,
335                                0,
336                                0,
337                                0,
338                                0,
339                                0,
340                                0,
341                                0,
342                                0,
343                                0,
344                                0,
345                                0,
346                                0,
347                                0,
348                                0,
349                                0,
350                                0,
351                                0,
352                                0,
353                                0,
354                                0,
355                                0,
356                                0,
357                                0,
358                                0,
359                                0,
360                                0,
361                                0,
362                                0,
363                                0,
364                                0,
365                                0,
366                                0,
367                                0,
368                                0,
369                                0,
370                                0,
371                                0,
372                                0,
373                                0,
374                                0,
375                                0,
376                                0,
377                                6,
378                                119,
379                                111,
380                                114,
381                                108,
382                                100,
383                                33,
384                                0,
385                                0,
386                                0,
387                                0,
388                                0,
389                                0,
390                                0,
391                                0,
392                                0,
393                                0,
394                                0,
395                                0,
396                                0,
397                                0,
398                                0,
399                                0,
400                                0,
401                                0,
402                                0,
403                                0,
404                                0,
405                                0,
406                                0,
407                                0,
408                                0,
409                                0,
410                            ],
411                            max_result_size: 0,
412                            sender_id: Some(
413                                AccountId {
414                                    shard_num: 1,
415                                    realm_num: 2,
416                                    account: Some(
417                                        AccountNum(
418                                            3,
419                                        ),
420                                    ),
421                                },
422                            ),
423                        },
424                    ),
425                ),
426            }
427        "#]]
428        .assert_debug_eq(
429            &make_query()
430                .function_with_parameters(
431                    "foo",
432                    ContractFunctionParameters::new().add_string("Hello").add_string("world!"),
433                )
434                .data
435                .to_query_protobuf(services::QueryHeader::default()),
436        );
437    }
438
439    #[test]
440    fn function_parameters() {
441        expect![[r#"
442            Query {
443                query: Some(
444                    ContractCallLocal(
445                        ContractCallLocalQuery {
446                            header: Some(
447                                QueryHeader {
448                                    payment: None,
449                                    response_type: AnswerOnly,
450                                },
451                            ),
452                            contract_id: Some(
453                                ContractId {
454                                    shard_num: 0,
455                                    realm_num: 0,
456                                    contract: Some(
457                                        ContractNum(
458                                            5005,
459                                        ),
460                                    ),
461                                },
462                            ),
463                            gas: 1541,
464                            function_parameters: [
465                                0,
466                                0,
467                                0,
468                                0,
469                                0,
470                                0,
471                                0,
472                                0,
473                                0,
474                                0,
475                                0,
476                                0,
477                                0,
478                                0,
479                                0,
480                                0,
481                                0,
482                                0,
483                                0,
484                                0,
485                                0,
486                                0,
487                                0,
488                                0,
489                                0,
490                                0,
491                                0,
492                                0,
493                                0,
494                                0,
495                                0,
496                                64,
497                                0,
498                                0,
499                                0,
500                                0,
501                                0,
502                                0,
503                                0,
504                                0,
505                                0,
506                                0,
507                                0,
508                                0,
509                                0,
510                                0,
511                                0,
512                                0,
513                                0,
514                                0,
515                                0,
516                                0,
517                                0,
518                                0,
519                                0,
520                                0,
521                                0,
522                                0,
523                                0,
524                                0,
525                                0,
526                                0,
527                                0,
528                                128,
529                                0,
530                                0,
531                                0,
532                                0,
533                                0,
534                                0,
535                                0,
536                                0,
537                                0,
538                                0,
539                                0,
540                                0,
541                                0,
542                                0,
543                                0,
544                                0,
545                                0,
546                                0,
547                                0,
548                                0,
549                                0,
550                                0,
551                                0,
552                                0,
553                                0,
554                                0,
555                                0,
556                                0,
557                                0,
558                                0,
559                                0,
560                                5,
561                                72,
562                                101,
563                                108,
564                                108,
565                                111,
566                                0,
567                                0,
568                                0,
569                                0,
570                                0,
571                                0,
572                                0,
573                                0,
574                                0,
575                                0,
576                                0,
577                                0,
578                                0,
579                                0,
580                                0,
581                                0,
582                                0,
583                                0,
584                                0,
585                                0,
586                                0,
587                                0,
588                                0,
589                                0,
590                                0,
591                                0,
592                                0,
593                                0,
594                                0,
595                                0,
596                                0,
597                                0,
598                                0,
599                                0,
600                                0,
601                                0,
602                                0,
603                                0,
604                                0,
605                                0,
606                                0,
607                                0,
608                                0,
609                                0,
610                                0,
611                                0,
612                                0,
613                                0,
614                                0,
615                                0,
616                                0,
617                                0,
618                                0,
619                                0,
620                                0,
621                                0,
622                                0,
623                                0,
624                                6,
625                                119,
626                                111,
627                                114,
628                                108,
629                                100,
630                                33,
631                                0,
632                                0,
633                                0,
634                                0,
635                                0,
636                                0,
637                                0,
638                                0,
639                                0,
640                                0,
641                                0,
642                                0,
643                                0,
644                                0,
645                                0,
646                                0,
647                                0,
648                                0,
649                                0,
650                                0,
651                                0,
652                                0,
653                                0,
654                                0,
655                                0,
656                                0,
657                            ],
658                            max_result_size: 0,
659                            sender_id: Some(
660                                AccountId {
661                                    shard_num: 1,
662                                    realm_num: 2,
663                                    account: Some(
664                                        AccountNum(
665                                            3,
666                                        ),
667                                    ),
668                                },
669                            ),
670                        },
671                    ),
672                ),
673            }
674        "#]]
675        .assert_debug_eq(
676            &make_query()
677                .function_parameters(
678                    ContractFunctionParameters::new()
679                        .add_string("Hello")
680                        .add_string("world!")
681                        .to_bytes(None),
682                )
683                .data
684                .to_query_protobuf(services::QueryHeader::default()),
685        );
686    }
687
688    #[test]
689    fn get_set_contract_id() {
690        let mut query = ContractCallQuery::new();
691        query.contract_id(ContractId::new(0, 0, 5005));
692
693        assert_eq!(query.get_contract_id(), Some(ContractId::new(0, 0, 5005)));
694    }
695
696    #[test]
697    fn get_set_gas() {
698        let mut query = ContractCallQuery::new();
699        query.gas(1541);
700
701        assert_eq!(query.get_gas(), 1541);
702    }
703
704    #[test]
705    fn get_set_contract_parameters() {
706        const BYTES: [u8; 6] = [0x0a, 0x0b, 0x0c, 0x01, 0x02, 0x03];
707        let mut query = ContractCallQuery::new();
708        query.function_parameters(Vec::from(BYTES));
709
710        assert_eq!(query.get_contract_parameters(), &BYTES);
711    }
712
713    #[test]
714    fn get_set_sender_account_id() {
715        let mut query = ContractCallQuery::new();
716        query.sender_account_id(AccountId::new(1, 2, 3));
717
718        assert_eq!(query.get_sender_account_id(), Some(AccountId::new(1, 2, 3)));
719    }
720}