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        D: DeserializeOwned + Send + std::fmt::Debug + Sync,
9        S: Serialize + std::fmt::Debug,
10    >(
11        &self,
12        address: &Address,
13        msg: &S,
14    ) -> Result<D> {
15        self.run_with_middleware(ContractSmartReq {
16            address: address.clone(),
17            msg: contract_msg_to_vec(&msg)?,
18            _phantom: std::marker::PhantomData,
19        })
20        .await
21    }
22    #[instrument]
23    pub async fn contract_smart_raw<S: Serialize + std::fmt::Debug>(
24        &self,
25        address: &Address,
26        msg: &S,
27    ) -> Result<Vec<u8>> {
28        self.run_with_middleware(ContractSmartRawReq {
29            address: address.clone(),
30            msg: contract_msg_to_vec(&msg)?,
31        })
32        .await
33    }
34
35    #[instrument]
36    pub async fn contract_code_info(
37        &self,
38        code_id: u64,
39    ) -> Result<layer_climb_proto::wasm::CodeInfoResponse> {
40        self.run_with_middleware(ContractCodeInfoReq { code_id })
41            .await
42    }
43
44    #[instrument]
45    pub async fn contract_info(
46        &self,
47        address: &Address,
48    ) -> Result<layer_climb_proto::wasm::QueryContractInfoResponse> {
49        self.run_with_middleware(ContractInfoReq {
50            address: address.clone(),
51        })
52        .await
53    }
54}
55
56#[derive(Debug)]
57struct ContractSmartReq<D> {
58    pub address: Address,
59    pub msg: Vec<u8>,
60    _phantom: std::marker::PhantomData<D>,
61}
62
63impl<D> Clone for ContractSmartReq<D> {
64    fn clone(&self) -> Self {
65        Self {
66            address: self.address.clone(),
67            msg: self.msg.clone(),
68            _phantom: std::marker::PhantomData,
69        }
70    }
71}
72
73impl<D: DeserializeOwned + Send + std::fmt::Debug + Sync> QueryRequest for ContractSmartReq<D> {
74    type QueryResponse = D;
75
76    async fn request(&self, client: QueryClient) -> Result<D> {
77        let res = ContractSmartRawReq {
78            address: self.address.clone(),
79            msg: self.msg.clone(),
80        }
81        .request(client)
82        .await?;
83
84        let res = cosmwasm_std::from_json(res)
85            .map_err(|e| anyhow::anyhow!("couldn't deserialize response {}", e))?;
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}