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 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    #[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    #[deprecated]
424    pub fn query_all_balances(&self, address: impl Into<String>) -> StdResult<Vec<Coin>> {
425        #[allow(deprecated)]
426        let request = BankQuery::AllBalances {
427            address: address.into(),
428        }
429        .into();
430        let res: AllBalanceResponse = 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, Uint128};
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, Uint128::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        #[allow(deprecated)]
712        let all_balances = wrapper.query_all_balances("foo").unwrap();
713        assert_eq!(all_balances, vec![coin(123, "ELF"), coin(777, "FLY")]);
714    }
715
716    #[test]
717    fn contract_info() {
718        const ACCT: &str = "foobar";
719        fn mock_resp() -> ContractInfoResponse {
720            ContractInfoResponse {
721                code_id: 0,
722                creator: Addr::unchecked("creator"),
723                admin: None,
724                pinned: false,
725                ibc_port: None,
726            }
727        }
728
729        let mut querier: MockQuerier<Empty> = MockQuerier::new(&[(ACCT, &coins(5, "BTC"))]);
730        querier.update_wasm(|q| -> QuerierResult {
731            if q == &(WasmQuery::ContractInfo {
732                contract_addr: ACCT.to_string(),
733            }) {
734                SystemResult::Ok(ContractResult::Ok(to_json_binary(&mock_resp()).unwrap()))
735            } else {
736                SystemResult::Err(crate::SystemError::NoSuchContract {
737                    addr: ACCT.to_string(),
738                })
739            }
740        });
741        let wrapper = QuerierWrapper::<Empty>::new(&querier);
742
743        let contract_info = wrapper.query_wasm_contract_info(ACCT).unwrap();
744        assert_eq!(contract_info, mock_resp());
745    }
746
747    #[test]
748    fn contract_info_err() {
749        const ACCT: &str = "foobar";
750        fn mock_resp() -> ContractInfoResponse {
751            ContractInfoResponse {
752                code_id: 0,
753                creator: Addr::unchecked("creator"),
754                admin: None,
755                pinned: false,
756                ibc_port: None,
757            }
758        }
759
760        let mut querier: MockQuerier<Empty> = MockQuerier::new(&[(ACCT, &coins(5, "BTC"))]);
761        querier.update_wasm(|q| -> QuerierResult {
762            if q == &(WasmQuery::ContractInfo {
763                contract_addr: ACCT.to_string(),
764            }) {
765                SystemResult::Ok(ContractResult::Ok(to_json_binary(&mock_resp()).unwrap()))
766            } else {
767                SystemResult::Err(crate::SystemError::NoSuchContract {
768                    addr: ACCT.to_string(),
769                })
770            }
771        });
772        let wrapper = QuerierWrapper::<Empty>::new(&querier);
773
774        let err = wrapper.query_wasm_contract_info("unknown").unwrap_err();
775        assert!(matches!(
776            err,
777            StdError::GenericErr {
778                msg,
779                ..
780            } if msg == "Querier system error: No such contract: foobar"
781        ));
782    }
783
784    #[test]
785    fn querier_into_empty() {
786        #[derive(Clone, Serialize, Deserialize)]
787        struct MyQuery;
788        impl CustomQuery for MyQuery {}
789
790        let querier: MockQuerier<MyQuery> = MockQuerier::new(&[]);
791        let wrapper = QuerierWrapper::<MyQuery>::new(&querier);
792
793        let _: QuerierWrapper<Empty> = wrapper.into_empty();
794    }
795}