cosmwasm_std/
traits.rs

1use core::marker::PhantomData;
2use core::ops::Deref;
3use serde::{de::DeserializeOwned, Serialize};
4
5use crate::coin::Coin;
6#[cfg(feature = "iterator")]
7use crate::iterator::{Order, Record};
8use crate::prelude::*;
9#[cfg(feature = "cosmwasm_1_2")]
10use crate::query::CodeInfoResponse;
11#[cfg(feature = "cosmwasm_1_1")]
12use crate::query::SupplyResponse;
13use crate::query::{
14    AllBalanceResponse, BalanceResponse, BankQuery, CustomQuery, QueryRequest, WasmQuery,
15};
16#[cfg(feature = "staking")]
17use crate::query::{
18    AllDelegationsResponse, AllValidatorsResponse, BondedDenomResponse, Delegation,
19    DelegationResponse, FullDelegation, StakingQuery, Validator, ValidatorResponse,
20};
21#[cfg(feature = "cosmwasm_1_3")]
22use crate::query::{
23    AllDenomMetadataResponse, DelegatorWithdrawAddressResponse, DenomMetadataResponse,
24    DistributionQuery,
25};
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 {
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 readble 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    #[allow(unused_variables)]
188    fn bls12_381_aggregate_g1(&self, g1s: &[u8]) -> Result<[u8; 48], VerificationError> {
189        // Support for BLS12-381 is added in 2.1, i.e. we can't add a compile time requirement for new function.
190        // Any implementation of the Api trait which does not implement this function but tries to call it will
191        // panic at runtime. We don't assume such cases exist.
192        // See also https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-default-item
193        unimplemented!()
194    }
195
196    #[allow(unused_variables)]
197    fn bls12_381_aggregate_g2(&self, g2s: &[u8]) -> Result<[u8; 96], VerificationError> {
198        // Support for BLS12-381 is added in 2.1, i.e. we can't add a compile time requirement for new function.
199        // Any implementation of the Api trait which does not implement this function but tries to call it will
200        // panic at runtime. We don't assume such cases exist.
201        // See also https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-default-item
202        unimplemented!()
203    }
204
205    /// Checks the following pairing equality:
206    ///
207    /// e(p_1, q_1) × e(p_2, q_2) × … × e(p_n, q_n) = e(s, q)
208    ///
209    /// The argument `ps` contain the points p_1, ..., p_n ∈ G1 as a concatenation of 48 byte elements.
210    /// The argument `qs` contain the points q_1, ..., q_n ∈ G2 as a concatenation of 96 byte elements.
211    ///
212    /// ## Examples
213    ///
214    /// A simple signature check with one pairing on the left hand side (e(p, q) = e(s, q)):
215    ///
216    /// ```
217    /// # use cosmwasm_std::{Api, HashFunction, StdResult};
218    /// pub fn verify(
219    ///     api: &dyn Api,
220    ///     g1_generator: &[u8],
221    ///     signature: &[u8],
222    ///     pubkey: &[u8],
223    ///     msg: &[u8],
224    ///     dst: &[u8],
225    /// ) -> StdResult<bool> {
226    ///     let msg_hashed = api.bls12_381_hash_to_g2(HashFunction::Sha256, msg, dst)?;
227    ///     api.bls12_381_pairing_equality(g1_generator, signature, pubkey, &msg_hashed)
228    ///         .map_err(Into::into)
229    /// }
230    /// ```
231    #[allow(unused_variables)]
232    fn bls12_381_pairing_equality(
233        &self,
234        ps: &[u8],
235        qs: &[u8],
236        r: &[u8],
237        s: &[u8],
238    ) -> Result<bool, VerificationError> {
239        // Support for BLS12-381 is added in 2.1, i.e. we can't add a compile time requirement for new function.
240        // Any implementation of the Api trait which does not implement this function but tries to call it will
241        // panic at runtime. We don't assume such cases exist.
242        // See also https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-default-item
243        unimplemented!()
244    }
245
246    #[allow(unused_variables)]
247    fn bls12_381_hash_to_g1(
248        &self,
249        hash_function: HashFunction,
250        msg: &[u8],
251        dst: &[u8],
252    ) -> Result<[u8; 48], VerificationError> {
253        // Support for BLS12-381 is added in 2.1, i.e. we can't add a compile time requirement for new function.
254        // Any implementation of the Api trait which does not implement this function but tries to call it will
255        // panic at runtime. We don't assume such cases exist.
256        // See also https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-default-item
257        unimplemented!()
258    }
259
260    #[allow(unused_variables)]
261    fn bls12_381_hash_to_g2(
262        &self,
263        hash_function: HashFunction,
264        msg: &[u8],
265        dst: &[u8],
266    ) -> Result<[u8; 96], VerificationError> {
267        // Support for BLS12-381 is added in 2.1, i.e. we can't add a compile time requirement for new function.
268        // Any implementation of the Api trait which does not implement this function but tries to call it will
269        // panic at runtime. We don't assume such cases exist.
270        // See also https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-default-item
271        unimplemented!()
272    }
273
274    #[allow(unused_variables)]
275    fn secp256r1_verify(
276        &self,
277        message_hash: &[u8],
278        signature: &[u8],
279        public_key: &[u8],
280    ) -> Result<bool, VerificationError> {
281        // Support for secp256r1 is added in 2.1, i.e. we can't add a compile time requirement for new function.
282        // Any implementation of the Api trait which does not implement this function but tries to call it will
283        // panic at runtime. We don't assume such cases exist.
284        // See also https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-default-item
285        unimplemented!()
286    }
287
288    #[allow(unused_variables)]
289    fn secp256r1_recover_pubkey(
290        &self,
291        message_hash: &[u8],
292        signature: &[u8],
293        recovery_param: u8,
294    ) -> Result<Vec<u8>, RecoverPubkeyError> {
295        // Support for secp256r1 was added in 2.1, i.e. we can't add a compile time requirement for new function.
296        // Any implementation of the Api trait which does not implement this function but tries to call it will
297        // panic at runtime. We don't assume such cases exist.
298        // See also https://doc.rust-lang.org/cargo/reference/semver.html#trait-new-default-item
299        unimplemented!()
300    }
301
302    fn ed25519_verify(
303        &self,
304        message: &[u8],
305        signature: &[u8],
306        public_key: &[u8],
307    ) -> Result<bool, VerificationError>;
308
309    fn ed25519_batch_verify(
310        &self,
311        messages: &[&[u8]],
312        signatures: &[&[u8]],
313        public_keys: &[&[u8]],
314    ) -> Result<bool, VerificationError>;
315
316    /// Emits a debugging message that is handled depending on the environment (typically printed to console or ignored).
317    /// Those messages are not persisted to chain.
318    fn debug(&self, message: &str);
319}
320
321/// A short-hand alias for the two-level query result (1. accessing the contract, 2. executing query in the contract)
322pub type QuerierResult = SystemResult<ContractResult<Binary>>;
323
324pub trait Querier {
325    /// raw_query is all that must be implemented for the Querier.
326    /// This allows us to pass through binary queries from one level to another without
327    /// knowing the custom format, or we can decode it, with the knowledge of the allowed
328    /// types. People using the querier probably want one of the simpler auto-generated
329    /// helper methods
330    fn raw_query(&self, bin_request: &[u8]) -> QuerierResult;
331}
332
333#[derive(Clone)]
334pub struct QuerierWrapper<'a, C: CustomQuery = Empty> {
335    querier: &'a dyn Querier,
336    custom_query_type: PhantomData<C>,
337}
338
339// Use custom implementation on order to implement Copy in case `C` is not `Copy`.
340// See "There is a small difference between the two: the derive strategy will also
341// place a Copy bound on type parameters, which isn’t always desired."
342// https://doc.rust-lang.org/std/marker/trait.Copy.html
343impl<'a, C: CustomQuery> Copy for QuerierWrapper<'a, C> {}
344
345/// This allows us to use self.raw_query to access the querier.
346/// It also allows external callers to access the querier easily.
347impl<'a, C: CustomQuery> Deref for QuerierWrapper<'a, C> {
348    type Target = dyn Querier + 'a;
349
350    fn deref(&self) -> &Self::Target {
351        self.querier
352    }
353}
354
355impl<'a, C: CustomQuery> QuerierWrapper<'a, C> {
356    pub fn new(querier: &'a dyn Querier) -> Self {
357        QuerierWrapper {
358            querier,
359            custom_query_type: PhantomData,
360        }
361    }
362
363    /// This allows to convert any `QuerierWrapper` into a `QuerierWrapper` generic
364    /// over `Empty` custom query type.
365    pub fn into_empty(self) -> QuerierWrapper<'a, Empty> {
366        QuerierWrapper {
367            querier: self.querier,
368            custom_query_type: PhantomData,
369        }
370    }
371
372    /// Makes the query and parses the response.
373    ///
374    /// Any error (System Error, Error or called contract, or Parse Error) are flattened into
375    /// one level. Only use this if you don't need to check the SystemError
376    /// eg. If you don't differentiate between contract missing and contract returned error
377    pub fn query<U: DeserializeOwned>(&self, request: &QueryRequest<C>) -> StdResult<U> {
378        self.query_raw(request).and_then(|raw| from_json(raw))
379    }
380
381    /// Internal helper to avoid code duplication.
382    /// Performs a query and returns the binary result without deserializing it,
383    /// wrapping any errors that may occur into `StdError`.
384    fn query_raw(&self, request: &QueryRequest<C>) -> StdResult<Binary> {
385        let raw = to_json_vec(request).map_err(|serialize_err| {
386            StdError::generic_err(format!("Serializing QueryRequest: {serialize_err}"))
387        })?;
388        match self.raw_query(&raw) {
389            SystemResult::Err(system_err) => Err(StdError::generic_err(format!(
390                "Querier system error: {system_err}"
391            ))),
392            SystemResult::Ok(ContractResult::Err(contract_err)) => Err(StdError::generic_err(
393                format!("Querier contract error: {contract_err}"),
394            )),
395            SystemResult::Ok(ContractResult::Ok(value)) => Ok(value),
396        }
397    }
398
399    #[cfg(feature = "cosmwasm_1_1")]
400    pub fn query_supply(&self, denom: impl Into<String>) -> StdResult<Coin> {
401        let request = BankQuery::Supply {
402            denom: denom.into(),
403        }
404        .into();
405        let res: SupplyResponse = self.query(&request)?;
406        Ok(res.amount)
407    }
408
409    pub fn query_balance(
410        &self,
411        address: impl Into<String>,
412        denom: impl Into<String>,
413    ) -> StdResult<Coin> {
414        let request = BankQuery::Balance {
415            address: address.into(),
416            denom: denom.into(),
417        }
418        .into();
419        let res: BalanceResponse = self.query(&request)?;
420        Ok(res.amount)
421    }
422
423    pub fn query_all_balances(&self, address: impl Into<String>) -> StdResult<Vec<Coin>> {
424        let request = BankQuery::AllBalances {
425            address: address.into(),
426        }
427        .into();
428        let res: AllBalanceResponse = self.query(&request)?;
429        Ok(res.amount)
430    }
431
432    #[cfg(feature = "cosmwasm_1_3")]
433    pub fn query_delegator_withdraw_address(
434        &self,
435        delegator: impl Into<String>,
436    ) -> StdResult<Addr> {
437        let request = DistributionQuery::DelegatorWithdrawAddress {
438            delegator_address: delegator.into(),
439        }
440        .into();
441        let res: DelegatorWithdrawAddressResponse = self.query(&request)?;
442        Ok(res.withdraw_address)
443    }
444
445    #[cfg(feature = "cosmwasm_1_3")]
446    pub fn query_denom_metadata(&self, denom: impl Into<String>) -> StdResult<DenomMetadata> {
447        let request = BankQuery::DenomMetadata {
448            denom: denom.into(),
449        }
450        .into();
451        let res: DenomMetadataResponse = self.query(&request)?;
452        Ok(res.metadata)
453    }
454
455    #[cfg(feature = "cosmwasm_1_3")]
456    pub fn query_all_denom_metadata(
457        &self,
458        pagination: PageRequest,
459    ) -> StdResult<AllDenomMetadataResponse> {
460        let request = BankQuery::AllDenomMetadata {
461            pagination: Some(pagination),
462        }
463        .into();
464        self.query(&request)
465    }
466
467    #[cfg(feature = "cosmwasm_1_4")]
468    pub fn query_delegation_rewards(
469        &self,
470        delegator: impl Into<String>,
471        validator: impl Into<String>,
472    ) -> StdResult<Vec<crate::DecCoin>> {
473        use crate::DelegationRewardsResponse;
474
475        let request = DistributionQuery::DelegationRewards {
476            delegator_address: delegator.into(),
477            validator_address: validator.into(),
478        }
479        .into();
480        let DelegationRewardsResponse { rewards } = self.query(&request)?;
481
482        Ok(rewards)
483    }
484
485    #[cfg(feature = "cosmwasm_1_4")]
486    pub fn query_delegation_total_rewards(
487        &self,
488        delegator: impl Into<String>,
489    ) -> StdResult<crate::DelegationTotalRewardsResponse> {
490        let request = DistributionQuery::DelegationTotalRewards {
491            delegator_address: delegator.into(),
492        }
493        .into();
494        self.query(&request)
495    }
496
497    #[cfg(feature = "cosmwasm_1_4")]
498    pub fn query_delegator_validators(
499        &self,
500        delegator: impl Into<String>,
501    ) -> StdResult<Vec<String>> {
502        use crate::DelegatorValidatorsResponse;
503
504        let request = DistributionQuery::DelegatorValidators {
505            delegator_address: delegator.into(),
506        }
507        .into();
508        let res: DelegatorValidatorsResponse = self.query(&request)?;
509        Ok(res.validators)
510    }
511
512    /// See [`GrpcQuery`](crate::GrpcQuery) for more information.
513    #[cfg(feature = "cosmwasm_2_0")]
514    pub fn query_grpc(&self, path: String, data: Binary) -> StdResult<Binary> {
515        use crate::GrpcQuery;
516        self.query_raw(&QueryRequest::Grpc(GrpcQuery { path, data }))
517    }
518
519    /// Queries another wasm contract. You should know a priori the proper types for T and U
520    /// (response and request) based on the contract API
521    pub fn query_wasm_smart<T: DeserializeOwned>(
522        &self,
523        contract_addr: impl Into<String>,
524        msg: &impl Serialize,
525    ) -> StdResult<T> {
526        let request = WasmQuery::Smart {
527            contract_addr: contract_addr.into(),
528            msg: to_json_binary(msg)?,
529        }
530        .into();
531        self.query(&request)
532    }
533
534    /// Queries the raw storage from another wasm contract.
535    ///
536    /// You must know the exact layout and are implementation dependent
537    /// (not tied to an interface like query_wasm_smart).
538    /// That said, if you are building a few contracts together, this is a much cheaper approach
539    ///
540    /// Similar return value to [`Storage::get`]. Returns `Some(val)` or `None` if the data is there.
541    /// It only returns error on some runtime issue, not on any data cases.
542    pub fn query_wasm_raw(
543        &self,
544        contract_addr: impl Into<String>,
545        key: impl Into<Binary>,
546    ) -> StdResult<Option<Vec<u8>>> {
547        let request: QueryRequest<Empty> = WasmQuery::Raw {
548            contract_addr: contract_addr.into(),
549            key: key.into(),
550        }
551        .into();
552        // we cannot use query, as it will try to parse the binary data, when we just want to return it,
553        // so a bit of code copy here...
554        let raw = to_json_vec(&request).map_err(|serialize_err| {
555            StdError::generic_err(format!("Serializing QueryRequest: {serialize_err}"))
556        })?;
557        match self.raw_query(&raw) {
558            SystemResult::Err(system_err) => Err(StdError::generic_err(format!(
559                "Querier system error: {system_err}"
560            ))),
561            SystemResult::Ok(ContractResult::Err(contract_err)) => Err(StdError::generic_err(
562                format!("Querier contract error: {contract_err}"),
563            )),
564            SystemResult::Ok(ContractResult::Ok(value)) => {
565                if value.is_empty() {
566                    Ok(None)
567                } else {
568                    Ok(Some(value.into()))
569                }
570            }
571        }
572    }
573
574    /// Given a contract address, query information about that contract.
575    pub fn query_wasm_contract_info(
576        &self,
577        contract_addr: impl Into<String>,
578    ) -> StdResult<ContractInfoResponse> {
579        let request = WasmQuery::ContractInfo {
580            contract_addr: contract_addr.into(),
581        }
582        .into();
583        self.query(&request)
584    }
585
586    /// Given a code ID, query information about that code.
587    #[cfg(feature = "cosmwasm_1_2")]
588    pub fn query_wasm_code_info(&self, code_id: u64) -> StdResult<CodeInfoResponse> {
589        let request = WasmQuery::CodeInfo { code_id }.into();
590        self.query(&request)
591    }
592
593    #[cfg(feature = "staking")]
594    pub fn query_all_validators(&self) -> StdResult<Vec<Validator>> {
595        let request = StakingQuery::AllValidators {}.into();
596        let res: AllValidatorsResponse = self.query(&request)?;
597        Ok(res.validators)
598    }
599
600    #[cfg(feature = "staking")]
601    pub fn query_validator(&self, address: impl Into<String>) -> StdResult<Option<Validator>> {
602        let request = StakingQuery::Validator {
603            address: address.into(),
604        }
605        .into();
606        let res: ValidatorResponse = self.query(&request)?;
607        Ok(res.validator)
608    }
609
610    #[cfg(feature = "staking")]
611    pub fn query_bonded_denom(&self) -> StdResult<String> {
612        let request = StakingQuery::BondedDenom {}.into();
613        let res: BondedDenomResponse = self.query(&request)?;
614        Ok(res.denom)
615    }
616
617    #[cfg(feature = "staking")]
618    pub fn query_all_delegations(
619        &self,
620        delegator: impl Into<String>,
621    ) -> StdResult<Vec<Delegation>> {
622        let request = StakingQuery::AllDelegations {
623            delegator: delegator.into(),
624        }
625        .into();
626        let res: AllDelegationsResponse = self.query(&request)?;
627        Ok(res.delegations)
628    }
629
630    #[cfg(feature = "staking")]
631    pub fn query_delegation(
632        &self,
633        delegator: impl Into<String>,
634        validator: impl Into<String>,
635    ) -> StdResult<Option<FullDelegation>> {
636        let request = StakingQuery::Delegation {
637            delegator: delegator.into(),
638            validator: validator.into(),
639        }
640        .into();
641        let res: DelegationResponse = self.query(&request)?;
642        Ok(res.delegation)
643    }
644}
645
646#[cfg(test)]
647mod tests {
648    use serde::Deserialize;
649
650    use super::*;
651    use crate::testing::MockQuerier;
652    use crate::{coins, Uint128};
653
654    // this is a simple demo helper to prove we can use it
655    fn demo_helper(_querier: &dyn Querier) -> u64 {
656        2
657    }
658
659    // this just needs to compile to prove we can use it
660    #[test]
661    fn use_querier_wrapper_as_querier() {
662        let querier: MockQuerier<Empty> = MockQuerier::new(&[]);
663        let wrapper = QuerierWrapper::<Empty>::new(&querier);
664
665        // call with deref shortcut
666        let res = demo_helper(&*wrapper);
667        assert_eq!(2, res);
668
669        // call with explicit deref
670        let res = demo_helper(wrapper.deref());
671        assert_eq!(2, res);
672    }
673
674    #[test]
675    fn auto_deref_raw_query() {
676        let acct = String::from("foobar");
677        let querier: MockQuerier<Empty> = MockQuerier::new(&[(&acct, &coins(5, "BTC"))]);
678        let wrapper = QuerierWrapper::<Empty>::new(&querier);
679        let query = QueryRequest::<Empty>::Bank(BankQuery::Balance {
680            address: acct,
681            denom: "BTC".to_string(),
682        });
683
684        let raw = wrapper
685            .raw_query(&to_json_vec(&query).unwrap())
686            .unwrap()
687            .unwrap();
688        let balance: BalanceResponse = from_json(raw).unwrap();
689        assert_eq!(balance.amount.amount, Uint128::new(5));
690    }
691
692    #[cfg(feature = "cosmwasm_1_1")]
693    #[test]
694    fn bank_query_helpers_work() {
695        use crate::coin;
696
697        let querier: MockQuerier<Empty> = MockQuerier::new(&[
698            ("foo", &[coin(123, "ELF"), coin(777, "FLY")]),
699            ("bar", &[coin(321, "ELF")]),
700        ]);
701        let wrapper = QuerierWrapper::<Empty>::new(&querier);
702
703        let supply = wrapper.query_supply("ELF").unwrap();
704        assert_eq!(supply, coin(444, "ELF"));
705
706        let balance = wrapper.query_balance("foo", "ELF").unwrap();
707        assert_eq!(balance, coin(123, "ELF"));
708
709        let all_balances = wrapper.query_all_balances("foo").unwrap();
710        assert_eq!(all_balances, vec![coin(123, "ELF"), coin(777, "FLY")]);
711    }
712
713    #[test]
714    fn contract_info() {
715        const ACCT: &str = "foobar";
716        fn mock_resp() -> ContractInfoResponse {
717            ContractInfoResponse {
718                code_id: 0,
719                creator: Addr::unchecked("creator"),
720                admin: None,
721                pinned: false,
722                ibc_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            }
755        }
756
757        let mut querier: MockQuerier<Empty> = MockQuerier::new(&[(ACCT, &coins(5, "BTC"))]);
758        querier.update_wasm(|q| -> QuerierResult {
759            if q == &(WasmQuery::ContractInfo {
760                contract_addr: ACCT.to_string(),
761            }) {
762                SystemResult::Ok(ContractResult::Ok(to_json_binary(&mock_resp()).unwrap()))
763            } else {
764                SystemResult::Err(crate::SystemError::NoSuchContract {
765                    addr: ACCT.to_string(),
766                })
767            }
768        });
769        let wrapper = QuerierWrapper::<Empty>::new(&querier);
770
771        let err = wrapper.query_wasm_contract_info("unknown").unwrap_err();
772        assert!(matches!(
773            err,
774            StdError::GenericErr {
775                msg,
776                ..
777            } if msg == "Querier system error: No such contract: foobar"
778        ));
779    }
780
781    #[test]
782    fn querier_into_empty() {
783        #[derive(Clone, Serialize, Deserialize)]
784        struct MyQuery;
785        impl CustomQuery for MyQuery {}
786
787        let querier: MockQuerier<MyQuery> = MockQuerier::new(&[]);
788        let wrapper = QuerierWrapper::<MyQuery>::new(&querier);
789
790        let _: QuerierWrapper<Empty> = wrapper.into_empty();
791    }
792}