1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
use serde::de::DeserializeOwned; use crate::encoding::Binary; use crate::errors::{generic_err, StdResult, SystemResult}; #[cfg(feature = "iterator")] use crate::iterator::{Order, KV}; use crate::query::{AllBalanceResponse, BalanceResponse, BankQuery, QueryRequest}; use crate::serde::from_binary; use crate::to_vec; use crate::types::{CanonicalAddr, HumanAddr, Never}; use serde::Serialize; /// Holds all external dependencies of the contract. /// Designed to allow easy dependency injection at runtime. /// This cannot be copied or cloned since it would behave differently /// for mock storages and a bridge storage in the VM. pub struct Extern<S: Storage, A: Api, Q: Querier> { pub storage: S, pub api: A, pub querier: Q, } impl<S: Storage, A: Api, Q: Querier> Extern<S, A, Q> { /// change_querier is a helper mainly for test code when swapping out the Querier /// from the auto-generated one from mock_dependencies. This changes the type of /// Extern so replaces requires some boilerplate. pub fn change_querier<T: Querier, F: Fn(Q) -> T>(self, transform: F) -> Extern<S, A, T> { Extern { storage: self.storage, api: self.api, querier: transform(self.querier), } } } /// ReadonlyStorage is access to the contracts persistent data store pub trait ReadonlyStorage { /// Returns Err on error. /// Returns Ok(None) when key does not exist. /// Returns Ok(Some(Vec<u8>)) when key exists. /// /// Note: Support for differentiating between a non-existent key and a key with empty value /// is not great yet and might not be possible in all backends. But we're trying to get there. fn get(&self, key: &[u8]) -> StdResult<Option<Vec<u8>>>; #[cfg(feature = "iterator")] /// Allows iteration over a set of key/value pairs, either forwards or backwards. /// /// The bound `start` is inclusive and `end` is exclusive. /// /// If `start` is lexicographically greater than or equal to `end`, an empty range is described, mo matter of the order. fn range<'a>( &'a self, start: Option<&[u8]>, end: Option<&[u8]>, order: Order, ) -> StdResult<Box<dyn Iterator<Item = StdResult<KV>> + 'a>>; } // Storage extends ReadonlyStorage to give mutable access pub trait Storage: ReadonlyStorage { fn set(&mut self, key: &[u8], value: &[u8]) -> StdResult<()>; /// Removes a database entry at `key`. /// /// The current interface does not allow to differentiate between a key that existed /// before and one that didn't exist. See https://github.com/CosmWasm/cosmwasm/issues/290 fn remove(&mut self, key: &[u8]) -> StdResult<()>; } /// Api are callbacks to system functions defined outside of the wasm modules. /// This is a trait to allow Mocks in the test code. /// /// Currently it just supports address conversion, we could add eg. crypto functions here. /// These should all be pure (stateless) functions. If you need state, you probably want /// to use the Querier. /// /// We can use feature flags to opt-in to non-essential methods /// for backwards compatibility in systems that don't have them all. pub trait Api: Copy + Clone + Send { fn canonical_address(&self, human: &HumanAddr) -> StdResult<CanonicalAddr>; fn human_address(&self, canonical: &CanonicalAddr) -> StdResult<HumanAddr>; } /// A short-hand alias for the two-level query result (1. accessing the contract, 2. executing query in the contract) pub type QuerierResult = SystemResult<StdResult<Binary>>; pub trait Querier: Clone + Send { /// raw_query is all that must be implemented for the Querier. /// This allows us to pass through binary queries from one level to another without /// knowing the custom format, or we can decode it, with the knowledge of the allowed /// types. People using the querier probably want one of the simpler auto-generated /// helper methods fn raw_query(&self, bin_request: &[u8]) -> QuerierResult; /// query is a shorthand for custom_query when we are not using a custom type, /// this allows us to avoid specifying "Never" in all the type definitions. fn query<T: DeserializeOwned>(&self, request: &QueryRequest<Never>) -> StdResult<T> { self.custom_query(request) } /// Makes the query and parses the response. Also handles custom queries, /// so you need to specify the custom query type in the function parameters. /// If you are no using a custom query, just use `query` for easier interface. /// /// Any error (System Error, Error or called contract, or Parse Error) are flattened into /// one level. Only use this if you don't need to check the SystemError /// eg. If you don't differentiate between contract missing and contract returned error fn custom_query<T: Serialize, U: DeserializeOwned>( &self, request: &QueryRequest<T>, ) -> StdResult<U> { let raw = match to_vec(request) { Ok(raw) => raw, // TODO: maybe I want to make this a SystemError::InvalidRequest ? Err(e) => return Err(e), }; match self.raw_query(&raw) { Err(sys) => Err(generic_err(format!("Querier system error: {}", sys))), Ok(Err(err)) => Err(generic_err(format!("Querier contract error: {}", err))), // in theory we would process the response, but here it is the same type, so just pass through Ok(Ok(res)) => from_binary(&res), } } // TODO: a non-flattened version? fn query_balance<U: Into<HumanAddr>>( &self, address: U, denom: &str, ) -> StdResult<BalanceResponse> { let request = BankQuery::Balance { address: address.into(), denom: denom.to_string(), } .into(); self.query(&request) } fn query_all_balances<U: Into<HumanAddr>>(&self, address: U) -> StdResult<AllBalanceResponse> { let request = BankQuery::AllBalances { address: address.into(), } .into(); self.query(&request) } }