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