layer_climb_core/querier/
contract.rs

1use crate::{contract_helpers::contract_msg_to_vec, prelude::*};
2use serde::{de::DeserializeOwned, Serialize};
3use tracing::instrument;
4
5impl QueryClient {
6    #[instrument]
7    pub async fn contract_smart<
8        'a,
9        D: DeserializeOwned + Send + std::fmt::Debug + Sync,
10        S: Serialize + std::fmt::Debug,
11    >(
12        &self,
13        address: &Address,
14        msg: &S,
15    ) -> Result<D> {
16        self.run_with_middleware(ContractSmartReq {
17            address: address.clone(),
18            msg: contract_msg_to_vec(&msg)?,
19            _phantom: std::marker::PhantomData,
20        })
21        .await
22    }
23    #[instrument]
24    pub async fn contract_smart_raw<'a, S: Serialize + std::fmt::Debug>(
25        &self,
26        address: &Address,
27        msg: &S,
28    ) -> Result<Vec<u8>> {
29        self.run_with_middleware(ContractSmartRawReq {
30            address: address.clone(),
31            msg: contract_msg_to_vec(&msg)?,
32        })
33        .await
34    }
35
36    #[instrument]
37    pub async fn contract_code_info(
38        &self,
39        code_id: u64,
40    ) -> Result<layer_climb_proto::wasm::CodeInfoResponse> {
41        self.run_with_middleware(ContractCodeInfoReq { code_id })
42            .await
43    }
44
45    #[instrument]
46    pub async fn contract_info(
47        &self,
48        address: &Address,
49    ) -> Result<layer_climb_proto::wasm::QueryContractInfoResponse> {
50        self.run_with_middleware(ContractInfoReq {
51            address: address.clone(),
52        })
53        .await
54    }
55}
56
57#[derive(Debug)]
58struct ContractSmartReq<D> {
59    pub address: Address,
60    pub msg: Vec<u8>,
61    _phantom: std::marker::PhantomData<D>,
62}
63
64impl<D> Clone for ContractSmartReq<D> {
65    fn clone(&self) -> Self {
66        Self {
67            address: self.address.clone(),
68            msg: self.msg.clone(),
69            _phantom: std::marker::PhantomData,
70        }
71    }
72}
73
74impl<D: DeserializeOwned + Send + std::fmt::Debug + Sync> QueryRequest for ContractSmartReq<D> {
75    type QueryResponse = D;
76
77    async fn request(&self, client: QueryClient) -> Result<D> {
78        let res = ContractSmartRawReq {
79            address: self.address.clone(),
80            msg: self.msg.clone(),
81        }
82        .request(client)
83        .await?;
84
85        let res = cosmwasm_std::from_json(res).context("couldn't deserialize response")?;
86
87        Ok(res)
88    }
89}
90
91#[derive(Clone, Debug)]
92struct ContractSmartRawReq {
93    pub address: Address,
94    pub msg: Vec<u8>,
95}
96
97impl QueryRequest for ContractSmartRawReq {
98    type QueryResponse = Vec<u8>;
99
100    async fn request(&self, client: QueryClient) -> Result<Vec<u8>> {
101        let req = layer_climb_proto::wasm::QuerySmartContractStateRequest {
102            address: self.address.to_string(),
103            query_data: self.msg.clone(),
104        };
105
106        let res = match client.get_connection_mode() {
107            ConnectionMode::Grpc => {
108                let mut query_client = layer_climb_proto::wasm::query_client::QueryClient::new(
109                    client.clone_grpc_channel()?,
110                );
111
112                query_client
113                    .smart_contract_state(req)
114                    .await
115                    .map(|res| res.into_inner())?
116            }
117            ConnectionMode::Rpc => {
118                client
119                    .rpc_client()?
120                    .abci_protobuf_query("/cosmwasm.wasm.v1.Query/SmartContractState", req, None)
121                    .await?
122            }
123        };
124
125        Ok(res.data)
126    }
127}
128
129#[derive(Clone, Debug)]
130struct ContractCodeInfoReq {
131    pub code_id: u64,
132}
133
134impl QueryRequest for ContractCodeInfoReq {
135    type QueryResponse = layer_climb_proto::wasm::CodeInfoResponse;
136
137    async fn request(
138        &self,
139        client: QueryClient,
140    ) -> Result<layer_climb_proto::wasm::CodeInfoResponse> {
141        let req = layer_climb_proto::wasm::QueryCodeRequest {
142            code_id: self.code_id,
143        };
144
145        let res = match client.get_connection_mode() {
146            ConnectionMode::Grpc => {
147                let mut query_client = layer_climb_proto::wasm::query_client::QueryClient::new(
148                    client.clone_grpc_channel()?,
149                );
150
151                query_client.code(req).await.map(|res| res.into_inner())?
152            }
153            ConnectionMode::Rpc => {
154                client
155                    .rpc_client()?
156                    .abci_protobuf_query("/cosmwasm.wasm.v1.Query/Code", req, None)
157                    .await?
158            }
159        };
160
161        res.code_info.context("no code info found")
162    }
163}
164
165#[derive(Clone, Debug)]
166pub struct ContractInfoReq {
167    pub address: Address,
168}
169
170impl QueryRequest for ContractInfoReq {
171    type QueryResponse = layer_climb_proto::wasm::QueryContractInfoResponse;
172
173    async fn request(
174        &self,
175        client: QueryClient,
176    ) -> Result<layer_climb_proto::wasm::QueryContractInfoResponse> {
177        let req = layer_climb_proto::wasm::QueryContractInfoRequest {
178            address: self.address.to_string(),
179        };
180
181        match client.get_connection_mode() {
182            ConnectionMode::Grpc => {
183                let mut query_client = layer_climb_proto::wasm::query_client::QueryClient::new(
184                    client.clone_grpc_channel()?,
185                );
186
187                let resp = query_client
188                    .contract_info(req)
189                    .await
190                    .map(|res| res.into_inner())?;
191
192                Ok(resp)
193            }
194            ConnectionMode::Rpc => {
195                let resp = client
196                    .rpc_client()?
197                    .abci_protobuf_query::<_, layer_climb_proto::wasm::QueryContractInfoResponse>(
198                        "/cosmwasm.wasm.v1.Query/ContractInfo",
199                        req,
200                        None,
201                    )
202                    .await?;
203
204                Ok(resp)
205            }
206        }
207    }
208}