Skip to main content

hiero_sdk/contract/
contract_bytecode_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    BoxGrpcFuture,
15    ContractId,
16    Error,
17    FromProtobuf,
18    Query,
19    ToProtobuf,
20    ValidateChecksums,
21};
22
23/// Get the runtime bytecode for a smart contract instance.
24pub type ContractBytecodeQuery = Query<ContractBytecodeQueryData>;
25
26#[derive(Default, Debug, Clone)]
27pub struct ContractBytecodeQueryData {
28    /// The contract for which information is requested.
29    contract_id: Option<ContractId>,
30}
31
32impl ContractBytecodeQuery {
33    /// Gets the contract for which information is requested.
34    #[must_use]
35    pub fn get_contract_id(&self) -> Option<ContractId> {
36        self.data.contract_id
37    }
38
39    /// Sets the contract for which information is requested.
40    pub fn contract_id(&mut self, contract_id: ContractId) -> &mut Self {
41        self.data.contract_id = Some(contract_id);
42        self
43    }
44}
45
46impl From<ContractBytecodeQueryData> for AnyQueryData {
47    #[inline]
48    fn from(data: ContractBytecodeQueryData) -> Self {
49        Self::ContractBytecode(data)
50    }
51}
52
53impl ToQueryProtobuf for ContractBytecodeQueryData {
54    fn to_query_protobuf(&self, header: services::QueryHeader) -> services::Query {
55        let contract_id = self.contract_id.to_protobuf();
56
57        services::Query {
58            query: Some(services::query::Query::ContractGetBytecode(
59                services::ContractGetBytecodeQuery { contract_id, header: Some(header) },
60            )),
61        }
62    }
63}
64
65impl QueryExecute for ContractBytecodeQueryData {
66    type Response = Vec<u8>;
67
68    fn execute(
69        &self,
70        channel: Channel,
71        request: services::Query,
72    ) -> BoxGrpcFuture<'_, services::Response> {
73        Box::pin(async {
74            SmartContractServiceClient::new(channel).contract_get_bytecode(request).await
75        })
76    }
77}
78
79impl ValidateChecksums for ContractBytecodeQueryData {
80    fn validate_checksums(&self, ledger_id: &RefLedgerId) -> Result<(), Error> {
81        self.contract_id.validate_checksums(ledger_id)
82    }
83}
84
85impl FromProtobuf<services::response::Response> for Vec<u8> {
86    fn from_protobuf(pb: services::response::Response) -> crate::Result<Self>
87    where
88        Self: Sized,
89    {
90        let pb = pb_getv!(pb, ContractGetBytecodeResponse, services::response::Response);
91
92        Ok(pb.bytecode)
93    }
94}
95
96#[cfg(test)]
97mod tests {
98    use expect_test::expect;
99
100    use crate::query::ToQueryProtobuf;
101    use crate::{
102        ContractBytecodeQuery,
103        ContractId,
104        Hbar,
105    };
106
107    #[test]
108    fn serialize() {
109        expect![[r#"
110            Query {
111                query: Some(
112                    ContractGetBytecode(
113                        ContractGetBytecodeQuery {
114                            header: Some(
115                                QueryHeader {
116                                    payment: None,
117                                    response_type: AnswerOnly,
118                                },
119                            ),
120                            contract_id: Some(
121                                ContractId {
122                                    shard_num: 0,
123                                    realm_num: 0,
124                                    contract: Some(
125                                        ContractNum(
126                                            5005,
127                                        ),
128                                    ),
129                                },
130                            ),
131                        },
132                    ),
133                ),
134            }
135        "#]]
136        .assert_debug_eq(
137            &ContractBytecodeQuery::new()
138                .contract_id(crate::ContractId::new(0, 0, 5005))
139                .max_payment_amount(Hbar::from_tinybars(100_000))
140                .data
141                .to_query_protobuf(Default::default()),
142        );
143    }
144
145    #[test]
146    fn get_set_contract_id() {
147        let mut query = ContractBytecodeQuery::new();
148        query.contract_id(ContractId::new(0, 0, 5005));
149
150        assert_eq!(query.get_contract_id(), Some(ContractId::new(0, 0, 5005)));
151    }
152}