cosmwasm_std/
traits.rs

1use core::any::Any;
2use core::marker::PhantomData;
3use core::ops::Deref;
4use serde::{de::DeserializeOwned, Serialize};
5
6use crate::coin::Coin;
7#[cfg(feature = "iterator")]
8use crate::iterator::{Order, Record};
9use crate::prelude::*;
10#[cfg(feature = "cosmwasm_1_2")]
11use crate::query::CodeInfoResponse;
12#[cfg(feature = "cosmwasm_1_1")]
13use crate::query::SupplyResponse;
14#[cfg(feature = "staking")]
15use crate::query::{
16    AllDelegationsResponse, AllValidatorsResponse, BondedDenomResponse, Delegation,
17    DelegationResponse, FullDelegation, StakingQuery, Validator, ValidatorResponse,
18};
19#[cfg(feature = "cosmwasm_1_3")]
20use crate::query::{
21    AllDenomMetadataResponse, DelegatorWithdrawAddressResponse, DenomMetadataResponse,
22    DistributionQuery,
23};
24use crate::query::{BalanceResponse, BankQuery, CustomQuery, QueryRequest, WasmQuery};
25use crate::results::{ContractResult, Empty, SystemResult};
26use crate::ContractInfoResponse;
27use crate::{from_json, to_json_binary, to_json_vec, Binary};
28use crate::{Addr, CanonicalAddr};
29#[cfg(feature = "cosmwasm_1_3")]
30use crate::{DenomMetadata, PageRequest};
31use crate::{RecoverPubkeyError, StdError, StdResult, VerificationError};
32
33#[derive(Clone, Copy, Debug)]
34#[non_exhaustive]
35pub enum HashFunction {
36    Sha256 = 0,
37}
38
39#[cfg(not(target_arch = "wasm32"))]
40impl From<HashFunction> for cosmwasm_crypto::HashFunction {
41    fn from(value: HashFunction) -> Self {
42        match value {
43            HashFunction::Sha256 => cosmwasm_crypto::HashFunction::Sha256,
44        }
45    }
46}
47
48/// Storage provides read and write access to a persistent storage.
49/// If you only want to provide read access, provide `&Storage`
50pub trait Storage {
51    /// Returns None when key does not exist.
52    /// Returns Some(Vec<u8>) when key exists.
53    ///
54    /// Note: Support for differentiating between a non-existent key and a key with empty value
55    /// is not great yet and might not be possible in all backends. But we're trying to get there.
56    fn get(&self, key: &[u8]) -> Option<Vec<u8>>;
57
58    /// Allows iteration over a set of key/value pairs, either forwards or backwards.
59    ///
60    /// The bound `start` is inclusive and `end` is exclusive.
61    /// If `start` is lexicographically greater than or equal to `end`, an empty range is described, mo matter of the order.
62    #[cfg(feature = "iterator")]
63    #[allow(unused_variables)]
64    fn range<'a>(
65        &'a self,
66        start: Option<&[u8]>,
67        end: Option<&[u8]>,
68        order: Order,
69    ) -> Box<dyn Iterator<Item = Record> + 'a> {
70        // This default implementation is just to avoid breaking code when enabling the `iterator` feature.
71        // Any actual `Storage` impl should override this method.
72        unimplemented!("This storage does not support ranging. Make sure to override the `range` method in your `Storage` implementation.")
73    }
74
75    /// Allows iteration over a set of keys, either forwards or backwards.
76    ///
77    /// The bound `start` is inclusive and `end` is exclusive.
78    /// If `start` is lexicographically greater than or equal to `end`, an empty range is described, mo matter of the order.
79    ///
80    /// The default implementation uses [`Storage::range`] and discards the values. More efficient
81    /// implementations might be possible depending on the storage.
82    #[cfg(feature = "iterator")]
83    fn range_keys<'a>(
84        &'a self,
85        start: Option<&[u8]>,
86        end: Option<&[u8]>,
87        order: Order,
88    ) -> Box<dyn Iterator<Item = Vec<u8>> + 'a> {
89        Box::new(self.range(start, end, order).map(|(k, _v)| k))
90    }
91
92    /// Allows iteration over a set of values, either forwards or backwards.
93    ///
94    /// The bound `start` is inclusive and `end` is exclusive.
95    /// If `start` is lexicographically greater than or equal to `end`, an empty range is described, mo matter of the order.
96    ///
97    /// The default implementation uses [`Storage::range`] and discards the keys. More efficient implementations
98    /// might be possible depending on the storage.
99    #[cfg(feature = "iterator")]
100    fn range_values<'a>(
101        &'a self,
102        start: Option<&[u8]>,
103        end: Option<&[u8]>,
104        order: Order,
105    ) -> Box<dyn Iterator<Item = Vec<u8>> + 'a> {
106        Box::new(self.range(start, end, order).map(|(_k, v)| v))
107    }
108
109    fn set(&mut self, key: &[u8], value: &[u8]);
110
111    /// Removes a database entry at `key`.
112    ///
113    /// The current interface does not allow to differentiate between a key that existed
114    /// before and one that didn't exist. See https://github.com/CosmWasm/cosmwasm/issues/290
115    fn remove(&mut self, key: &[u8]);
116}
117
118/// Api are callbacks to system functions implemented outside of the wasm modules.
119/// Currently it just supports address conversion but we could add eg. crypto functions here.
120///
121/// This is a trait to allow mocks in the test code. Its members have a read-only
122/// reference to the Api instance to allow accessing configuration.
123/// Implementations must not have mutable state, such that an instance can freely
124/// be copied and shared between threads without affecting the behaviour.
125/// Given an Api instance, all members should return the same value when called with the same
126/// arguments. In particular this means the result must not depend in the state of the chain.
127/// If you need to access chaim state, you probably want to use the Querier.
128/// Side effects (such as logging) are allowed.
129///
130/// We can use feature flags to opt-in to non-essential methods
131/// for backwards compatibility in systems that don't have them all.
132pub trait Api: Any {
133    /// Takes a human readable address and validates if it is valid.
134    /// If it the validation succeeds, a `Addr` containing the same data as the input is returned.
135    ///
136    /// This validation checks two things:
137    /// 1. The address is valid in the sense that it can be converted to a canonical representation by the backend.
138    /// 2. The address is normalized, i.e. `humanize(canonicalize(input)) == input`.
139    ///
140    /// Check #2 is typically needed for upper/lower case representations of the same
141    /// address that are both valid according to #1. This way we ensure uniqueness
142    /// of the human readable address. Clients should perform the normalization before sending
143    /// the addresses to the CosmWasm stack. But please note that the definition of normalized
144    /// depends on the backend.
145    ///
146    /// ## Examples
147    ///
148    /// ```
149    /// # use cosmwasm_std::{Api, Addr};
150    /// # use cosmwasm_std::testing::MockApi;
151    /// let api = MockApi::default().with_prefix("juno");
152    /// let input = "juno1v82su97skv6ucfqvuvswe0t5fph7pfsrtraxf0x33d8ylj5qnrysdvkc95";
153    /// let validated: Addr = api.addr_validate(input).unwrap();
154    /// assert_eq!(validated.as_str(), input);
155    /// ```
156    fn addr_validate(&self, human: &str) -> StdResult<Addr>;
157
158    /// Takes a human readable address and returns a canonical binary representation of it.
159    /// This can be used when a compact representation is needed.
160    ///
161    /// Please note that the length of the resulting address is defined by the chain and
162    /// can vary from address to address. On Cosmos chains 20 and 32 bytes are typically used.
163    /// But that might change. So your contract should not make assumptions on the size.
164    fn addr_canonicalize(&self, human: &str) -> StdResult<CanonicalAddr>;
165
166    /// Takes a canonical address and returns a human readable address.
167    /// This is the inverse of [`addr_canonicalize`].
168    ///
169    /// [`addr_canonicalize`]: Api::addr_canonicalize
170    fn addr_humanize(&self, canonical: &CanonicalAddr) -> StdResult<Addr>;
171
172    fn secp256k1_verify(
173        &self,
174        message_hash: &[u8],
175        signature: &[u8],
176        public_key: &[u8],
177    ) -> Result<bool, VerificationError>;
178
179    fn secp256k1_recover_pubkey(
180        &self,
181        message_hash: &[u8],
182        signature: &[u8],
183        recovery_param: u8,
184    ) -> Result<Vec<u8>, RecoverPubkeyError>;
185
186    /// Add up points of the G1 subgroup on the BLS12-381 curve
187    ///
188    /// The length of `g1s` must be a multiple of 48 (each point is encoded in 48 bytes).
189    #[allow(unused_variables)]
190    fn bls12_381_aggregate_g1(&self, g1s: &[u8]) -> Result<[u8; 48], VerificationError> {
191        // Support for BLS12-381 is added in 2.1, i.e. we can't add a compile time requirement for new function.
192        // Any implementation of the Api trait which does not implement this function but tries to call it will
193        // panic at runtime. We don't assume such cases exist.
194        // See also https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-default-item
195        unimplemented!()
196    }
197
198    /// Add up points of the G2 subgroup on the BLS12-381 curve
199    ///
200    /// The length of `g2s` must be a multiple of 96 (each point is encoded in 96 bytes)
201    #[allow(unused_variables)]
202    fn bls12_381_aggregate_g2(&self, g2s: &[u8]) -> Result<[u8; 96], VerificationError> {
203        // Support for BLS12-381 is added in 2.1, i.e. we can't add a compile time requirement for new function.
204        // Any implementation of the Api trait which does not implement this function but tries to call it will
205        // panic at runtime. We don't assume such cases exist.
206        // See also https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-default-item
207        unimplemented!()
208    }
209
210    /// Checks the following pairing equality:
211    ///
212    /// e(p_1, q_1) × e(p_2, q_2) × … × e(p_n, q_n) = e(s, q)
213    ///
214    /// The argument `ps` contain the points p_1, ..., p_n ∈ G1 as a concatenation of 48 byte elements.
215    /// The argument `qs` contain the points q_1, ..., q_n ∈ G2 as a concatenation of 96 byte elements.
216    ///
217    /// ## Examples
218    ///
219    /// A simple signature check with one pairing on the left hand side (e(p, q) = e(s, q)):
220    ///
221    /// ```
222    /// # use cosmwasm_std::{Api, HashFunction, StdResult};
223    /// pub fn verify(
224    ///     api: &dyn Api,
225    ///     g1_generator: &[u8],
226    ///     signature: &[u8],
227    ///     pubkey: &[u8],
228    ///     msg: &[u8],
229    ///     dst: &[u8],
230    /// ) -> StdResult<bool> {
231    ///     let msg_hashed = api.bls12_381_hash_to_g2(HashFunction::Sha256, msg, dst)?;
232    ///     api.bls12_381_pairing_equality(g1_generator, signature, pubkey, &msg_hashed)
233    ///         .map_err(Into::into)
234    /// }
235    /// ```
236    #[allow(unused_variables)]
237    fn bls12_381_pairing_equality(
238        &self,
239        ps: &[u8],
240        qs: &[u8],
241        r: &[u8],
242        s: &[u8],
243    ) -> Result<bool, VerificationError> {
244        // Support for BLS12-381 is added in 2.1, i.e. we can't add a compile time requirement for new function.
245        // Any implementation of the Api trait which does not implement this function but tries to call it will
246        // panic at runtime. We don't assume such cases exist.
247        // See also https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-default-item
248        unimplemented!()
249    }
250
251    /// Take some arbitrary data and hash it to a point on the G1 subgroup of the curve.
252    ///
253    /// The `dst` parameter should be a constant is actually something similar to the "context" parameter in key derivation functions.
254    #[allow(unused_variables)]
255    fn bls12_381_hash_to_g1(
256        &self,
257        hash_function: HashFunction,
258        msg: &[u8],
259        dst: &[u8],
260    ) -> Result<[u8; 48], VerificationError> {
261        // Support for BLS12-381 is added in 2.1, i.e. we can't add a compile time requirement for new function.
262        // Any implementation of the Api trait which does not implement this function but tries to call it will
263        // panic at runtime. We don't assume such cases exist.
264        // See also https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-default-item
265        unimplemented!()
266    }
267
268    /// Take some arbitrary data and hash it to a point on the G2 subgroup of the curve.
269    ///
270    /// The `dst` parameter should be a constant is actually something similar to the "context" parameter in key derivation functions.
271    #[allow(unused_variables)]
272    fn bls12_381_hash_to_g2(
273        &self,
274        hash_function: HashFunction,
275        msg: &[u8],
276        dst: &[u8],
277    ) -> Result<[u8; 96], VerificationError> {
278        // Support for BLS12-381 is added in 2.1, i.e. we can't add a compile time requirement for new function.
279        // Any implementation of the Api trait which does not implement this function but tries to call it will
280        // panic at runtime. We don't assume such cases exist.
281        // See also https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-default-item
282        unimplemented!()
283    }
284
285    #[allow(unused_variables)]
286    fn secp256r1_verify(
287        &self,
288        message_hash: &[u8],
289        signature: &[u8],
290        public_key: &[u8],
291    ) -> Result<bool, VerificationError> {
292        // Support for secp256r1 is added in 2.1, i.e. we can't add a compile time requirement for new function.
293        // Any implementation of the Api trait which does not implement this function but tries to call it will
294        // panic at runtime. We don't assume such cases exist.
295        // See also https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-default-item
296        unimplemented!()
297    }
298
299    #[allow(unused_variables)]
300    fn secp256r1_recover_pubkey(
301        &self,
302        message_hash: &[u8],
303        signature: &[u8],
304        recovery_param: u8,
305    ) -> Result<Vec<u8>, RecoverPubkeyError> {
306        // Support for secp256r1 was added in 2.1, i.e. we can't add a compile time requirement for new function.
307        // Any implementation of the Api trait which does not implement this function but tries to call it will
308        // panic at runtime. We don't assume such cases exist.
309        // See also https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-default-item
310        unimplemented!()
311    }
312
313    fn ed25519_verify(
314        &self,
315        message: &[u8],
316        signature: &[u8],
317        public_key: &[u8],
318    ) -> Result<bool, VerificationError>;
319
320    fn ed25519_batch_verify(
321        &self,
322        messages: &[&[u8]],
323        signatures: &[&[u8]],
324        public_keys: &[&[u8]],
325    ) -> Result<bool, VerificationError>;
326
327    /// Emits a debugging message that is handled depending on the environment (typically printed to console or ignored).
328    /// Those messages are not persisted to chain.
329    fn debug(&self, message: &str);
330}
331
332/// A short-hand alias for the two-level query result (1. accessing the contract, 2. executing query in the contract)
333pub type QuerierResult = SystemResult<ContractResult<Binary>>;
334
335pub trait Querier {
336    /// raw_query is all that must be implemented for the Querier.
337    /// This allows us to pass through binary queries from one level to another without
338    /// knowing the custom format, or we can decode it, with the knowledge of the allowed
339    /// types. People using the querier probably want one of the simpler auto-generated
340    /// helper methods
341    fn raw_query(&self, bin_request: &[u8]) -> QuerierResult;
342}
343
344#[derive(Clone)]
345pub struct QuerierWrapper<'a, C: CustomQuery = Empty> {
346    querier: &'a dyn Querier,
347    custom_query_type: PhantomData<C>,
348}
349
350// Use custom implementation on order to implement Copy in case `C` is not `Copy`.
351// See "There is a small difference between the two: the derive strategy will also
352// place a Copy bound on type parameters, which isn’t always desired."
353// https://doc.rust-lang.org/std/marker/trait.Copy.html
354impl<C: CustomQuery> Copy for QuerierWrapper<'_, C> {}
355
356/// This allows us to use self.raw_query to access the querier.
357/// It also allows external callers to access the querier easily.
358impl<'a, C: CustomQuery> Deref for QuerierWrapper<'a, C> {
359    type Target = dyn Querier + 'a;
360
361    fn deref(&self) -> &Self::Target {
362        self.querier
363    }
364}
365
366impl<'a, C: CustomQuery> QuerierWrapper<'a, C> {
367    pub fn new(querier: &'a dyn Querier) -> Self {
368        QuerierWrapper {
369            querier,
370            custom_query_type: PhantomData,
371        }
372    }
373
374    /// This allows to convert any `QuerierWrapper` into a `QuerierWrapper` generic
375    /// over `Empty` custom query type.
376    pub fn into_empty(self) -> QuerierWrapper<'a, Empty> {
377        QuerierWrapper {
378            querier: self.querier,
379            custom_query_type: PhantomData,
380        }
381    }
382
383    /// Makes the query and parses the response.
384    ///
385    /// Any error (System Error, Error or called contract, or Parse Error) are flattened into
386    /// one level. Only use this if you don't need to check the SystemError
387    /// eg. If you don't differentiate between contract missing and contract returned error
388    pub fn query<U: DeserializeOwned>(&self, request: &QueryRequest<C>) -> StdResult<U> {
389        self.query_raw(request).and_then(|raw| from_json(raw))
390    }
391
392    /// Internal helper to avoid code duplication.
393    /// Performs a query and returns the binary result without deserializing it,
394    /// wrapping any errors that may occur into `StdError`.
395    fn query_raw(&self, request: &QueryRequest<C>) -> StdResult<Binary> {
396        let raw = to_json_vec(request).map_err(|serialize_err| {
397            StdError::generic_err(format!("Serializing QueryRequest: {serialize_err}"))
398        })?;
399        match self.raw_query(&raw) {
400            SystemResult::Err(system_err) => Err(StdError::generic_err(format!(
401                "Querier system error: {system_err}"
402            ))),
403            SystemResult::Ok(ContractResult::Err(contract_err)) => Err(StdError::generic_err(
404                format!("Querier contract error: {contract_err}"),
405            )),
406            SystemResult::Ok(ContractResult::Ok(value)) => Ok(value),
407        }
408    }
409
410    #[cfg(feature = "cosmwasm_1_1")]
411    pub fn query_supply(&self, denom: impl Into<String>) -> StdResult<Coin> {
412        let request = BankQuery::Supply {
413            denom: denom.into(),
414        }
415        .into();
416        let res: SupplyResponse = self.query(&request)?;
417        Ok(res.amount)
418    }
419
420    pub fn query_balance(
421        &self,
422        address: impl Into<String>,
423        denom: impl Into<String>,
424    ) -> StdResult<Coin> {
425        let request = BankQuery::Balance {
426            address: address.into(),
427            denom: denom.into(),
428        }
429        .into();
430        let res: BalanceResponse = self.query(&request)?;
431        Ok(res.amount)
432    }
433
434    #[cfg(feature = "cosmwasm_1_3")]
435    pub fn query_delegator_withdraw_address(
436        &self,
437        delegator: impl Into<String>,
438    ) -> StdResult<Addr> {
439        let request = DistributionQuery::DelegatorWithdrawAddress {
440            delegator_address: delegator.into(),
441        }
442        .into();
443        let res: DelegatorWithdrawAddressResponse = self.query(&request)?;
444        Ok(res.withdraw_address)
445    }
446
447    #[cfg(feature = "cosmwasm_1_3")]
448    pub fn query_denom_metadata(&self, denom: impl Into<String>) -> StdResult<DenomMetadata> {
449        let request = BankQuery::DenomMetadata {
450            denom: denom.into(),
451        }
452        .into();
453        let res: DenomMetadataResponse = self.query(&request)?;
454        Ok(res.metadata)
455    }
456
457    #[cfg(feature = "cosmwasm_1_3")]
458    pub fn query_all_denom_metadata(
459        &self,
460        pagination: PageRequest,
461    ) -> StdResult<AllDenomMetadataResponse> {
462        let request = BankQuery::AllDenomMetadata {
463            pagination: Some(pagination),
464        }
465        .into();
466        self.query(&request)
467    }
468
469    #[cfg(feature = "cosmwasm_1_4")]
470    pub fn query_delegation_rewards(
471        &self,
472        delegator: impl Into<String>,
473        validator: impl Into<String>,
474    ) -> StdResult<Vec<crate::DecCoin>> {
475        use crate::DelegationRewardsResponse;
476
477        let request = DistributionQuery::DelegationRewards {
478            delegator_address: delegator.into(),
479            validator_address: validator.into(),
480        }
481        .into();
482        let DelegationRewardsResponse { rewards } = self.query(&request)?;
483
484        Ok(rewards)
485    }
486
487    #[cfg(feature = "cosmwasm_1_4")]
488    pub fn query_delegation_total_rewards(
489        &self,
490        delegator: impl Into<String>,
491    ) -> StdResult<crate::DelegationTotalRewardsResponse> {
492        let request = DistributionQuery::DelegationTotalRewards {
493            delegator_address: delegator.into(),
494        }
495        .into();
496        self.query(&request)
497    }
498
499    #[cfg(feature = "cosmwasm_1_4")]
500    pub fn query_delegator_validators(
501        &self,
502        delegator: impl Into<String>,
503    ) -> StdResult<Vec<String>> {
504        use crate::DelegatorValidatorsResponse;
505
506        let request = DistributionQuery::DelegatorValidators {
507            delegator_address: delegator.into(),
508        }
509        .into();
510        let res: DelegatorValidatorsResponse = self.query(&request)?;
511        Ok(res.validators)
512    }
513
514    /// See [`GrpcQuery`](crate::GrpcQuery) for more information.
515    #[cfg(feature = "cosmwasm_2_0")]
516    pub fn query_grpc(&self, path: String, data: Binary) -> StdResult<Binary> {
517        use crate::GrpcQuery;
518        self.query_raw(&QueryRequest::Grpc(GrpcQuery { path, data }))
519    }
520
521    /// Queries another wasm contract. You should know a priori the proper types for T and U
522    /// (response and request) based on the contract API
523    pub fn query_wasm_smart<T: DeserializeOwned>(
524        &self,
525        contract_addr: impl Into<String>,
526        msg: &impl Serialize,
527    ) -> StdResult<T> {
528        let request = WasmQuery::Smart {
529            contract_addr: contract_addr.into(),
530            msg: to_json_binary(msg)?,
531        }
532        .into();
533        self.query(&request)
534    }
535
536    /// Queries the raw storage from another wasm contract.
537    ///
538    /// You must know the exact layout and are implementation dependent
539    /// (not tied to an interface like query_wasm_smart).
540    /// That said, if you are building a few contracts together, this is a much cheaper approach
541    ///
542    /// Similar return value to [`Storage::get`]. Returns `Some(val)` or `None` if the data is there.
543    /// It only returns error on some runtime issue, not on any data cases.
544    pub fn query_wasm_raw(
545        &self,
546        contract_addr: impl Into<String>,
547        key: impl Into<Binary>,
548    ) -> StdResult<Option<Vec<u8>>> {
549        let request: QueryRequest<Empty> = WasmQuery::Raw {
550            contract_addr: contract_addr.into(),
551            key: key.into(),
552        }
553        .into();
554        // we cannot use query, as it will try to parse the binary data, when we just want to return it,
555        // so a bit of code copy here...
556        let raw = to_json_vec(&request).map_err(|serialize_err| {
557            StdError::generic_err(format!("Serializing QueryRequest: {serialize_err}"))
558        })?;
559        match self.raw_query(&raw) {
560            SystemResult::Err(system_err) => Err(StdError::generic_err(format!(
561                "Querier system error: {system_err}"
562            ))),
563            SystemResult::Ok(ContractResult::Err(contract_err)) => Err(StdError::generic_err(
564                format!("Querier contract error: {contract_err}"),
565            )),
566            SystemResult::Ok(ContractResult::Ok(value)) => {
567                if value.is_empty() {
568                    Ok(None)
569                } else {
570                    Ok(Some(value.into()))
571                }
572            }
573        }
574    }
575
576    /// Given a contract address, query information about that contract.
577    pub fn query_wasm_contract_info(
578        &self,
579        contract_addr: impl Into<String>,
580    ) -> StdResult<ContractInfoResponse> {
581        let request = WasmQuery::ContractInfo {
582            contract_addr: contract_addr.into(),
583        }
584        .into();
585        self.query(&request)
586    }
587
588    /// Given a code ID, query information about that code.
589    #[cfg(feature = "cosmwasm_1_2")]
590    pub fn query_wasm_code_info(&self, code_id: u64) -> StdResult<CodeInfoResponse> {
591        let request = WasmQuery::CodeInfo { code_id }.into();
592        self.query(&request)
593    }
594
595    #[cfg(feature = "staking")]
596    pub fn query_all_validators(&self) -> StdResult<Vec<Validator>> {
597        let request = StakingQuery::AllValidators {}.into();
598        let res: AllValidatorsResponse = self.query(&request)?;
599        Ok(res.validators)
600    }
601
602    #[cfg(feature = "staking")]
603    pub fn query_validator(&self, address: impl Into<String>) -> StdResult<Option<Validator>> {
604        let request = StakingQuery::Validator {
605            address: address.into(),
606        }
607        .into();
608        let res: ValidatorResponse = self.query(&request)?;
609        Ok(res.validator)
610    }
611
612    #[cfg(feature = "staking")]
613    pub fn query_bonded_denom(&self) -> StdResult<String> {
614        let request = StakingQuery::BondedDenom {}.into();
615        let res: BondedDenomResponse = self.query(&request)?;
616        Ok(res.denom)
617    }
618
619    #[cfg(feature = "staking")]
620    pub fn query_all_delegations(
621        &self,
622        delegator: impl Into<String>,
623    ) -> StdResult<Vec<Delegation>> {
624        let request = StakingQuery::AllDelegations {
625            delegator: delegator.into(),
626        }
627        .into();
628        let res: AllDelegationsResponse = self.query(&request)?;
629        Ok(res.delegations)
630    }
631
632    #[cfg(feature = "staking")]
633    pub fn query_delegation(
634        &self,
635        delegator: impl Into<String>,
636        validator: impl Into<String>,
637    ) -> StdResult<Option<FullDelegation>> {
638        let request = StakingQuery::Delegation {
639            delegator: delegator.into(),
640            validator: validator.into(),
641        }
642        .into();
643        let res: DelegationResponse = self.query(&request)?;
644        Ok(res.delegation)
645    }
646}
647
648#[cfg(test)]
649mod tests {
650    use serde::Deserialize;
651
652    use super::*;
653    use crate::testing::MockQuerier;
654    use crate::{coins, Uint256};
655
656    // this is a simple demo helper to prove we can use it
657    fn demo_helper(_querier: &dyn Querier) -> u64 {
658        2
659    }
660
661    // this just needs to compile to prove we can use it
662    #[test]
663    fn use_querier_wrapper_as_querier() {
664        let querier: MockQuerier<Empty> = MockQuerier::new(&[]);
665        let wrapper = QuerierWrapper::<Empty>::new(&querier);
666
667        // call with deref shortcut
668        let res = demo_helper(&*wrapper);
669        assert_eq!(2, res);
670
671        // call with explicit deref
672        let res = demo_helper(wrapper.deref());
673        assert_eq!(2, res);
674    }
675
676    #[test]
677    fn auto_deref_raw_query() {
678        let acct = String::from("foobar");
679        let querier: MockQuerier<Empty> = MockQuerier::new(&[(&acct, &coins(5, "BTC"))]);
680        let wrapper = QuerierWrapper::<Empty>::new(&querier);
681        let query = QueryRequest::<Empty>::Bank(BankQuery::Balance {
682            address: acct,
683            denom: "BTC".to_string(),
684        });
685
686        let raw = wrapper
687            .raw_query(&to_json_vec(&query).unwrap())
688            .unwrap()
689            .unwrap();
690        let balance: BalanceResponse = from_json(raw).unwrap();
691        assert_eq!(balance.amount.amount, Uint256::new(5));
692    }
693
694    #[cfg(feature = "cosmwasm_1_1")]
695    #[test]
696    fn bank_query_helpers_work() {
697        use crate::coin;
698
699        let querier: MockQuerier<Empty> = MockQuerier::new(&[
700            ("foo", &[coin(123, "ELF"), coin(777, "FLY")]),
701            ("bar", &[coin(321, "ELF")]),
702        ]);
703        let wrapper = QuerierWrapper::<Empty>::new(&querier);
704
705        let supply = wrapper.query_supply("ELF").unwrap();
706        assert_eq!(supply, coin(444, "ELF"));
707
708        let balance = wrapper.query_balance("foo", "ELF").unwrap();
709        assert_eq!(balance, coin(123, "ELF"));
710    }
711
712    #[test]
713    fn contract_info() {
714        const ACCT: &str = "foobar";
715        fn mock_resp() -> ContractInfoResponse {
716            ContractInfoResponse {
717                code_id: 0,
718                creator: Addr::unchecked("creator"),
719                admin: None,
720                pinned: false,
721                ibc_port: None,
722                ibc2_port: None,
723            }
724        }
725
726        let mut querier: MockQuerier<Empty> = MockQuerier::new(&[(ACCT, &coins(5, "BTC"))]);
727        querier.update_wasm(|q| -> QuerierResult {
728            if q == &(WasmQuery::ContractInfo {
729                contract_addr: ACCT.to_string(),
730            }) {
731                SystemResult::Ok(ContractResult::Ok(to_json_binary(&mock_resp()).unwrap()))
732            } else {
733                SystemResult::Err(crate::SystemError::NoSuchContract {
734                    addr: ACCT.to_string(),
735                })
736            }
737        });
738        let wrapper = QuerierWrapper::<Empty>::new(&querier);
739
740        let contract_info = wrapper.query_wasm_contract_info(ACCT).unwrap();
741        assert_eq!(contract_info, mock_resp());
742    }
743
744    #[test]
745    fn contract_info_err() {
746        const ACCT: &str = "foobar";
747        fn mock_resp() -> ContractInfoResponse {
748            ContractInfoResponse {
749                code_id: 0,
750                creator: Addr::unchecked("creator"),
751                admin: None,
752                pinned: false,
753                ibc_port: None,
754                ibc2_port: None,
755            }
756        }
757
758        let mut querier: MockQuerier<Empty> = MockQuerier::new(&[(ACCT, &coins(5, "BTC"))]);
759        querier.update_wasm(|q| -> QuerierResult {
760            if q == &(WasmQuery::ContractInfo {
761                contract_addr: ACCT.to_string(),
762            }) {
763                SystemResult::Ok(ContractResult::Ok(to_json_binary(&mock_resp()).unwrap()))
764            } else {
765                SystemResult::Err(crate::SystemError::NoSuchContract {
766                    addr: ACCT.to_string(),
767                })
768            }
769        });
770        let wrapper = QuerierWrapper::<Empty>::new(&querier);
771
772        let err = wrapper.query_wasm_contract_info("unknown").unwrap_err();
773        assert!(matches!(
774            err,
775            StdError::GenericErr {
776                msg,
777                ..
778            } if msg == "Querier system error: No such contract: foobar"
779        ));
780    }
781
782    #[test]
783    fn querier_into_empty() {
784        #[derive(Clone, Serialize, Deserialize)]
785        struct MyQuery;
786        impl CustomQuery for MyQuery {}
787
788        let querier: MockQuerier<MyQuery> = MockQuerier::new(&[]);
789        let wrapper = QuerierWrapper::<MyQuery>::new(&querier);
790
791        let _: QuerierWrapper<Empty> = wrapper.into_empty();
792    }
793}