jk_cosmwasm_std/
traits.rs

1use serde::{de::DeserializeOwned, Serialize};
2use std::ops::Deref;
3
4use crate::addresses::{Addr, CanonicalAddr};
5use crate::binary::Binary;
6use crate::coins::Coin;
7use crate::errors::{RecoverPubkeyError, StdError, StdResult, VerificationError};
8#[cfg(feature = "iterator")]
9use crate::iterator::{Order, Pair};
10use crate::query::{
11    AllBalanceResponse, BalanceResponse, BankQuery, CustomQuery, QueryRequest, WasmQuery,
12};
13#[cfg(feature = "staking")]
14use crate::query::{
15    AllDelegationsResponse, AllValidatorsResponse, BondedDenomResponse, Delegation,
16    DelegationResponse, FullDelegation, StakingQuery, Validator, ValidatorResponse,
17};
18use crate::results::{ContractResult, Empty, SystemResult};
19use crate::serde::{from_binary, to_binary, to_vec};
20
21/// Storage provides read and write access to a persistent storage.
22/// If you only want to provide read access, provide `&Storage`
23pub trait Storage {
24    /// Returns None when key does not exist.
25    /// Returns Some(Vec<u8>) when key exists.
26    ///
27    /// Note: Support for differentiating between a non-existent key and a key with empty value
28    /// is not great yet and might not be possible in all backends. But we're trying to get there.
29    fn get(&self, key: &[u8]) -> Option<Vec<u8>>;
30
31    #[cfg(feature = "iterator")]
32    /// Allows iteration over a set of key/value pairs, either forwards or backwards.
33    ///
34    /// The bound `start` is inclusive and `end` is exclusive.
35    ///
36    /// If `start` is lexicographically greater than or equal to `end`, an empty range is described, mo matter of the order.
37    fn range<'a>(
38        &'a self,
39        start: Option<&[u8]>,
40        end: Option<&[u8]>,
41        order: Order,
42    ) -> Box<dyn Iterator<Item = Pair> + 'a>;
43
44    fn set(&mut self, key: &[u8], value: &[u8]);
45    /// Removes a database entry at `key`.
46    ///
47    /// The current interface does not allow to differentiate between a key that existed
48    /// before and one that didn't exist. See https://github.com/CosmWasm/cosmwasm/issues/290
49    fn remove(&mut self, key: &[u8]);
50}
51
52/// Api are callbacks to system functions implemented outside of the wasm modules.
53/// Currently it just supports address conversion but we could add eg. crypto functions here.
54///
55/// This is a trait to allow mocks in the test code. Its members have a read-only
56/// reference to the Api instance to allow accessing configuration.
57/// Implementations must not have mutable state, such that an instance can freely
58/// be copied and shared between threads without affecting the behaviour.
59/// Given an Api instance, all members should return the same value when called with the same
60/// arguments. In particular this means the result must not depend in the state of the chain.
61/// If you need to access chaim state, you probably want to use the Querier.
62/// Side effects (such as logging) are allowed.
63///
64/// We can use feature flags to opt-in to non-essential methods
65/// for backwards compatibility in systems that don't have them all.
66pub trait Api {
67    /// Takes a human readable address and validates if it's correctly formatted.
68    /// If it succeeds, a Addr is returned.
69    ///
70    /// ## Examples
71    ///
72    /// ```
73    /// # use cosmwasm_std::{Api, Addr};
74    /// # use cosmwasm_std::testing::MockApi;
75    /// # let api = MockApi::default();
76    /// let input = "what-users-provide";
77    /// let validated: Addr = api.addr_validate(input).unwrap();
78    /// assert_eq!(validated, input);
79    /// ```
80    fn addr_validate(&self, human: &str) -> StdResult<Addr>;
81
82    /// Takes a human readable address and returns a canonical binary representation of it.
83    /// This can be used when a compact fixed length representation is needed.
84    fn addr_canonicalize(&self, human: &str) -> StdResult<CanonicalAddr>;
85
86    /// Takes a canonical address and returns a human readble address.
87    /// This is the inverse of [`addr_canonicalize`].
88    ///
89    /// [`addr_canonicalize`]: Api::addr_canonicalize
90    fn addr_humanize(&self, canonical: &CanonicalAddr) -> StdResult<Addr>;
91
92    fn secp256k1_verify(
93        &self,
94        message_hash: &[u8],
95        signature: &[u8],
96        public_key: &[u8],
97    ) -> Result<bool, VerificationError>;
98
99    fn secp256k1_recover_pubkey(
100        &self,
101        message_hash: &[u8],
102        signature: &[u8],
103        recovery_param: u8,
104    ) -> Result<Vec<u8>, RecoverPubkeyError>;
105
106    fn ed25519_verify(
107        &self,
108        message: &[u8],
109        signature: &[u8],
110        public_key: &[u8],
111    ) -> Result<bool, VerificationError>;
112
113    fn ed25519_batch_verify(
114        &self,
115        messages: &[&[u8]],
116        signatures: &[&[u8]],
117        public_keys: &[&[u8]],
118    ) -> Result<bool, VerificationError>;
119
120    /// Emits a debugging message that is handled depending on the environment (typically printed to console or ignored).
121    /// Those messages are not persisted to chain.
122    fn debug(&self, message: &str);
123}
124
125/// A short-hand alias for the two-level query result (1. accessing the contract, 2. executing query in the contract)
126pub type QuerierResult = SystemResult<ContractResult<Binary>>;
127
128pub trait Querier {
129    /// raw_query is all that must be implemented for the Querier.
130    /// This allows us to pass through binary queries from one level to another without
131    /// knowing the custom format, or we can decode it, with the knowledge of the allowed
132    /// types. People using the querier probably want one of the simpler auto-generated
133    /// helper methods
134    fn raw_query(&self, bin_request: &[u8]) -> QuerierResult;
135}
136
137#[derive(Copy, Clone)]
138pub struct QuerierWrapper<'a>(&'a dyn Querier);
139
140/// This allows us to use self.raw_query to access the querier.
141/// It also allows external callers to access the querier easily.
142impl<'a> Deref for QuerierWrapper<'a> {
143    type Target = dyn Querier + 'a;
144
145    fn deref(&self) -> &Self::Target {
146        self.0
147    }
148}
149
150impl<'a> QuerierWrapper<'a> {
151    pub fn new(querier: &'a dyn Querier) -> Self {
152        QuerierWrapper(querier)
153    }
154
155    /// query is a shorthand for custom_query when we are not using a custom type,
156    /// this allows us to avoid specifying "Empty" in all the type definitions.
157    pub fn query<T: DeserializeOwned>(&self, request: &QueryRequest<Empty>) -> StdResult<T> {
158        self.custom_query(request)
159    }
160
161    /// Makes the query and parses the response. Also handles custom queries,
162    /// so you need to specify the custom query type in the function parameters.
163    /// If you are no using a custom query, just use `query` for easier interface.
164    ///
165    /// Any error (System Error, Error or called contract, or Parse Error) are flattened into
166    /// one level. Only use this if you don't need to check the SystemError
167    /// eg. If you don't differentiate between contract missing and contract returned error
168    pub fn custom_query<C: CustomQuery, U: DeserializeOwned>(
169        &self,
170        request: &QueryRequest<C>,
171    ) -> StdResult<U> {
172        let raw = to_vec(request).map_err(|serialize_err| {
173            StdError::generic_err(format!("Serializing QueryRequest: {}", serialize_err))
174        })?;
175        match self.raw_query(&raw) {
176            SystemResult::Err(system_err) => Err(StdError::generic_err(format!(
177                "Querier system error: {}",
178                system_err
179            ))),
180            SystemResult::Ok(ContractResult::Err(contract_err)) => Err(StdError::generic_err(
181                format!("Querier contract error: {}", contract_err),
182            )),
183            SystemResult::Ok(ContractResult::Ok(value)) => from_binary(&value),
184        }
185    }
186
187    pub fn query_balance(
188        &self,
189        address: impl Into<String>,
190        denom: impl Into<String>,
191    ) -> StdResult<Coin> {
192        let request = BankQuery::Balance {
193            address: address.into(),
194            denom: denom.into(),
195        }
196        .into();
197        let res: BalanceResponse = self.query(&request)?;
198        Ok(res.amount)
199    }
200
201    pub fn query_all_balances(&self, address: impl Into<String>) -> StdResult<Vec<Coin>> {
202        let request = BankQuery::AllBalances {
203            address: address.into(),
204        }
205        .into();
206        let res: AllBalanceResponse = self.query(&request)?;
207        Ok(res.amount)
208    }
209
210    // this queries another wasm contract. You should know a priori the proper types for T and U
211    // (response and request) based on the contract API
212    pub fn query_wasm_smart<T: DeserializeOwned>(
213        &self,
214        contract_addr: impl Into<String>,
215        msg: &impl Serialize,
216    ) -> StdResult<T> {
217        let request = WasmQuery::Smart {
218            contract_addr: contract_addr.into(),
219            msg: to_binary(msg)?,
220        }
221        .into();
222        self.query(&request)
223    }
224
225    // this queries the raw storage from another wasm contract.
226    // you must know the exact layout and are implementation dependent
227    // (not tied to an interface like query_wasm_smart)
228    // that said, if you are building a few contracts together, this is a much cheaper approach
229    //
230    // Similar return value to Storage.get(). Returns Some(val) or None if the data is there.
231    // It only returns error on some runtime issue, not on any data cases.
232    pub fn query_wasm_raw(
233        &self,
234        contract_addr: impl Into<String>,
235        key: impl Into<Binary>,
236    ) -> StdResult<Option<Vec<u8>>> {
237        let request: QueryRequest<Empty> = WasmQuery::Raw {
238            contract_addr: contract_addr.into(),
239            key: key.into(),
240        }
241        .into();
242        // we cannot use query, as it will try to parse the binary data, when we just want to return it,
243        // so a bit of code copy here...
244        let raw = to_vec(&request).map_err(|serialize_err| {
245            StdError::generic_err(format!("Serializing QueryRequest: {}", serialize_err))
246        })?;
247        match self.raw_query(&raw) {
248            SystemResult::Err(system_err) => Err(StdError::generic_err(format!(
249                "Querier system error: {}",
250                system_err
251            ))),
252            SystemResult::Ok(ContractResult::Err(contract_err)) => Err(StdError::generic_err(
253                format!("Querier contract error: {}", contract_err),
254            )),
255            SystemResult::Ok(ContractResult::Ok(value)) => {
256                if value.is_empty() {
257                    Ok(None)
258                } else {
259                    Ok(Some(value.into()))
260                }
261            }
262        }
263    }
264
265    #[cfg(feature = "staking")]
266    pub fn query_all_validators(&self) -> StdResult<Vec<Validator>> {
267        let request = StakingQuery::AllValidators {}.into();
268        let res: AllValidatorsResponse = self.query(&request)?;
269        Ok(res.validators)
270    }
271
272    #[cfg(feature = "staking")]
273    pub fn query_validator(&self, address: impl Into<String>) -> StdResult<Option<Validator>> {
274        let request = StakingQuery::Validator {
275            address: address.into(),
276        }
277        .into();
278        let res: ValidatorResponse = self.query(&request)?;
279        Ok(res.validator)
280    }
281
282    #[cfg(feature = "staking")]
283    pub fn query_bonded_denom(&self) -> StdResult<String> {
284        let request = StakingQuery::BondedDenom {}.into();
285        let res: BondedDenomResponse = self.query(&request)?;
286        Ok(res.denom)
287    }
288
289    #[cfg(feature = "staking")]
290    pub fn query_all_delegations(
291        &self,
292        delegator: impl Into<String>,
293    ) -> StdResult<Vec<Delegation>> {
294        let request = StakingQuery::AllDelegations {
295            delegator: delegator.into(),
296        }
297        .into();
298        let res: AllDelegationsResponse = self.query(&request)?;
299        Ok(res.delegations)
300    }
301
302    #[cfg(feature = "staking")]
303    pub fn query_delegation(
304        &self,
305        delegator: impl Into<String>,
306        validator: impl Into<String>,
307    ) -> StdResult<Option<FullDelegation>> {
308        let request = StakingQuery::Delegation {
309            delegator: delegator.into(),
310            validator: validator.into(),
311        }
312        .into();
313        let res: DelegationResponse = self.query(&request)?;
314        Ok(res.delegation)
315    }
316}
317
318#[cfg(test)]
319mod tests {
320    use super::*;
321    use crate::mock::MockQuerier;
322    use crate::{coins, from_slice, Uint128};
323
324    // this is a simple demo helper to prove we can use it
325    fn demo_helper(_querier: &dyn Querier) -> u64 {
326        2
327    }
328
329    // this just needs to compile to prove we can use it
330    #[test]
331    fn use_querier_wrapper_as_querier() {
332        let querier: MockQuerier<Empty> = MockQuerier::new(&[]);
333        let wrapper = QuerierWrapper::new(&querier);
334
335        // call with deref shortcut
336        let res = demo_helper(&*wrapper);
337        assert_eq!(2, res);
338
339        // call with explicit deref
340        let res = demo_helper(wrapper.deref());
341        assert_eq!(2, res);
342    }
343
344    #[test]
345    fn auto_deref_raw_query() {
346        let acct = String::from("foobar");
347        let querier: MockQuerier<Empty> = MockQuerier::new(&[(&acct, &coins(5, "BTC"))]);
348        let wrapper = QuerierWrapper::new(&querier);
349        let query = QueryRequest::<Empty>::Bank(BankQuery::Balance {
350            address: acct,
351            denom: "BTC".to_string(),
352        });
353
354        let raw = wrapper
355            .raw_query(&to_vec(&query).unwrap())
356            .unwrap()
357            .unwrap();
358        let balance: BalanceResponse = from_slice(&raw).unwrap();
359        assert_eq!(balance.amount.amount, Uint128::new(5));
360    }
361}