1use crate::error::CosmosClient;
2use crate::error::CosmosClient::{ProstDecodeError, RpcError};
3use cosmos_sdk_proto::cosmos::base::query::v1beta1::PageRequest;
4use cosmos_sdk_proto::cosmwasm::wasm::v1::{
5 QueryAllContractStateRequest, QueryAllContractStateResponse, QueryCodeRequest,
6 QueryCodeResponse, QueryCodesRequest, QueryCodesResponse, QueryContractHistoryRequest,
7 QueryContractHistoryResponse, QueryContractInfoRequest, QueryContractInfoResponse,
8 QueryContractsByCodeRequest, QueryContractsByCodeResponse, QueryPinnedCodesRequest,
9 QueryPinnedCodesResponse, QueryRawContractStateRequest, QueryRawContractStateResponse,
10 QuerySmartContractStateRequest,
11};
12use prost::Message;
13use serde::de::DeserializeOwned;
14use serde::Serialize;
15use std::rc::Rc;
16use tendermint::abci::Code;
17use tendermint_rpc::{Client, HttpClient};
18
19pub struct Module {
20 rpc: Rc<HttpClient>,
21}
22
23impl Module {
24 pub fn new(rpc: Rc<HttpClient>) -> Self {
25 Module { rpc }
26 }
27
28 pub async fn contract_info(
35 &self,
36 address: &str,
37 ) -> Result<QueryContractInfoResponse, CosmosClient> {
38 let query = QueryContractInfoRequest {
39 address: address.to_string(),
40 };
41 let query = self
42 .rpc
43 .abci_query(
44 Some("/cosmwasm.wasm.v1.Query/ContractInfo".to_string()),
45 query.encode_to_vec(),
46 None,
47 false,
48 )
49 .await?;
50
51 if query.code != Code::Ok {
52 return Err(RpcError(query.log));
53 }
54 QueryContractInfoResponse::decode(query.value.as_slice()).map_err(ProstDecodeError)
55 }
56
57 pub async fn contract_history(
64 &self,
65 address: &str,
66 pagination: Option<PageRequest>,
67 ) -> Result<QueryContractHistoryResponse, CosmosClient> {
68 let query = QueryContractHistoryRequest {
69 address: address.to_string(),
70 pagination,
71 };
72 let query = self
73 .rpc
74 .abci_query(
75 Some("/cosmwasm.wasm.v1.Query/ContractHistory".to_string()),
76 query.encode_to_vec(),
77 None,
78 false,
79 )
80 .await?;
81
82 if query.code != Code::Ok {
83 return Err(RpcError(query.log));
84 }
85 QueryContractHistoryResponse::decode(query.value.as_slice()).map_err(ProstDecodeError)
86 }
87
88 pub async fn contracts_by_code(
95 &self,
96 code_id: u64,
97 pagination: Option<PageRequest>,
98 ) -> Result<QueryContractsByCodeResponse, CosmosClient> {
99 let query = QueryContractsByCodeRequest {
100 code_id,
101 pagination,
102 };
103 let query = self
104 .rpc
105 .abci_query(
106 Some("/cosmwasm.wasm.v1.Query/ContractsByCode".to_string()),
107 query.encode_to_vec(),
108 None,
109 false,
110 )
111 .await?;
112
113 if query.code != Code::Ok {
114 return Err(RpcError(query.log));
115 }
116 QueryContractsByCodeResponse::decode(query.value.as_slice()).map_err(ProstDecodeError)
117 }
118
119 pub async fn all_contract_state(
126 &self,
127 address: &str,
128 pagination: Option<PageRequest>,
129 ) -> Result<QueryAllContractStateResponse, CosmosClient> {
130 let query = QueryAllContractStateRequest {
131 address: address.to_string(),
132 pagination,
133 };
134 let query = self
135 .rpc
136 .abci_query(
137 Some("/cosmwasm.wasm.v1.Query/AllContractState".to_string()),
138 query.encode_to_vec(),
139 None,
140 false,
141 )
142 .await?;
143
144 if query.code != Code::Ok {
145 return Err(RpcError(query.log));
146 }
147 QueryAllContractStateResponse::decode(query.value.as_slice()).map_err(ProstDecodeError)
148 }
149
150 pub async fn raw_contract_state(
157 &self,
158 address: &str,
159 query_data: Vec<u8>,
160 ) -> Result<QueryRawContractStateResponse, CosmosClient> {
161 let query = QueryRawContractStateRequest {
162 address: address.to_string(),
163 query_data,
164 };
165 let query = self
166 .rpc
167 .abci_query(
168 Some("/cosmwasm.wasm.v1.Query/RawContractState".to_string()),
169 query.encode_to_vec(),
170 None,
171 false,
172 )
173 .await?;
174
175 if query.code != Code::Ok {
176 return Err(RpcError(query.log));
177 }
178 QueryRawContractStateResponse::decode(query.value.as_slice()).map_err(ProstDecodeError)
179 }
180
181 pub async fn smart_contract_state<T: Serialize + Clone, U: DeserializeOwned>(
189 &self,
190 address: &str,
191 msg: T,
192 ) -> Result<U, CosmosClient> {
193 let query = QuerySmartContractStateRequest {
194 address: address.to_string(),
195 query_data: serde_json::to_vec(&msg)?,
196 };
197 let ret = self
198 .rpc
199 .abci_query(
200 Some("/cosmwasm.wasm.v1.Query/SmartContractState".to_string()),
201 query.encode_to_vec(),
202 None,
203 false,
204 )
205 .await?;
206
207 if ret.code != Code::Ok {
208 return Err(RpcError(ret.log));
209 }
210 let resp: QueryRawContractStateResponse =
211 QueryRawContractStateResponse::decode(ret.value.as_slice())?;
212
213 serde_json::from_slice::<U>(resp.data.as_slice()).map_err(CosmosClient::JsonError)
214 }
215
216 pub async fn code(&self, code_id: u64) -> Result<QueryCodeResponse, CosmosClient> {
223 let query = QueryCodeRequest { code_id };
224 let query = self
225 .rpc
226 .abci_query(
227 Some("/cosmwasm.wasm.v1.Query/Code".to_string()),
228 query.encode_to_vec(),
229 None,
230 false,
231 )
232 .await?;
233
234 if query.code != Code::Ok {
235 return Err(RpcError(query.log));
236 }
237 QueryCodeResponse::decode(query.value.as_slice()).map_err(ProstDecodeError)
238 }
239
240 pub async fn codes(
247 &self,
248 pagination: Option<PageRequest>,
249 ) -> Result<QueryCodesResponse, CosmosClient> {
250 let query = QueryCodesRequest { pagination };
251 let query = self
252 .rpc
253 .abci_query(
254 Some("/cosmwasm.wasm.v1.Query/Codes".to_string()),
255 query.encode_to_vec(),
256 None,
257 false,
258 )
259 .await?;
260
261 if query.code != Code::Ok {
262 return Err(RpcError(query.log));
263 }
264 QueryCodesResponse::decode(query.value.as_slice()).map_err(ProstDecodeError)
265 }
266
267 pub async fn pinned_codes(
274 &self,
275 pagination: Option<PageRequest>,
276 ) -> Result<QueryPinnedCodesResponse, CosmosClient> {
277 let query = QueryPinnedCodesRequest { pagination };
278 let query = self
279 .rpc
280 .abci_query(
281 Some("/cosmwasm.wasm.v1.Query/PinnedCodes".to_string()),
282 query.encode_to_vec(),
283 None,
284 false,
285 )
286 .await?;
287
288 if query.code != Code::Ok {
289 return Err(RpcError(query.log));
290 }
291 QueryPinnedCodesResponse::decode(query.value.as_slice()).map_err(ProstDecodeError)
292 }
293}