1use core::marker::PhantomData;
2use core::ops::Deref;
3use serde::{de::DeserializeOwned, Serialize};
4
5use crate::addresses::{Addr, CanonicalAddr};
6use crate::binary::Binary;
7use crate::coin::Coin;
8use crate::errors::{RecoverPubkeyError, StdError, StdResult, VerificationError};
9#[cfg(feature = "iterator")]
10use crate::iterator::{Order, Record};
11#[cfg(feature = "cosmwasm_1_2")]
12use crate::query::CodeInfoResponse;
13#[cfg(feature = "cosmwasm_1_1")]
14use crate::query::SupplyResponse;
15use crate::query::{
16 AllBalanceResponse, BalanceResponse, BankQuery, CustomQuery, QueryRequest, WasmQuery,
17};
18#[cfg(feature = "staking")]
19use crate::query::{
20 AllDelegationsResponse, AllValidatorsResponse, BondedDenomResponse, Delegation,
21 DelegationResponse, FullDelegation, StakingQuery, Validator, ValidatorResponse,
22};
23#[cfg(feature = "cosmwasm_1_3")]
24use crate::query::{
25 AllDenomMetadataResponse, DelegatorWithdrawAddressResponse, DenomMetadataResponse,
26 DistributionQuery,
27};
28use crate::results::{ContractResult, Empty, SystemResult};
29use crate::serde::{from_json, to_json_binary, to_json_vec};
30use crate::ContractInfoResponse;
31#[cfg(feature = "cosmwasm_1_3")]
32use crate::{DenomMetadata, PageRequest};
33
34pub trait Storage {
37 fn get(&self, key: &[u8]) -> Option<Vec<u8>>;
43
44 #[cfg(feature = "iterator")]
49 fn range<'a>(
50 &'a self,
51 start: Option<&[u8]>,
52 end: Option<&[u8]>,
53 order: Order,
54 ) -> Box<dyn Iterator<Item = Record> + 'a>;
55
56 #[cfg(feature = "iterator")]
64 fn range_keys<'a>(
65 &'a self,
66 start: Option<&[u8]>,
67 end: Option<&[u8]>,
68 order: Order,
69 ) -> Box<dyn Iterator<Item = Vec<u8>> + 'a> {
70 Box::new(self.range(start, end, order).map(|(k, _v)| k))
71 }
72
73 #[cfg(feature = "iterator")]
81 fn range_values<'a>(
82 &'a self,
83 start: Option<&[u8]>,
84 end: Option<&[u8]>,
85 order: Order,
86 ) -> Box<dyn Iterator<Item = Vec<u8>> + 'a> {
87 Box::new(self.range(start, end, order).map(|(_k, v)| v))
88 }
89
90 fn set(&mut self, key: &[u8], value: &[u8]);
91
92 fn remove(&mut self, key: &[u8]);
97}
98
99pub trait Api {
114 fn addr_validate(&self, human: &str) -> StdResult<Addr>;
138
139 fn addr_canonicalize(&self, human: &str) -> StdResult<CanonicalAddr>;
146
147 fn addr_humanize(&self, canonical: &CanonicalAddr) -> StdResult<Addr>;
152
153 fn secp256k1_verify(
154 &self,
155 message_hash: &[u8],
156 signature: &[u8],
157 public_key: &[u8],
158 ) -> Result<bool, VerificationError>;
159
160 fn secp256k1_recover_pubkey(
161 &self,
162 message_hash: &[u8],
163 signature: &[u8],
164 recovery_param: u8,
165 ) -> Result<Vec<u8>, RecoverPubkeyError>;
166
167 fn ed25519_verify(
168 &self,
169 message: &[u8],
170 signature: &[u8],
171 public_key: &[u8],
172 ) -> Result<bool, VerificationError>;
173
174 fn ed25519_batch_verify(
175 &self,
176 messages: &[&[u8]],
177 signatures: &[&[u8]],
178 public_keys: &[&[u8]],
179 ) -> Result<bool, VerificationError>;
180
181 fn debug(&self, message: &str);
184}
185
186pub type QuerierResult = SystemResult<ContractResult<Binary>>;
188
189pub trait Querier {
190 fn raw_query(&self, bin_request: &[u8]) -> QuerierResult;
196}
197
198#[derive(Clone)]
199pub struct QuerierWrapper<'a, C: CustomQuery = Empty> {
200 querier: &'a dyn Querier,
201 custom_query_type: PhantomData<C>,
202}
203
204impl<'a, C: CustomQuery> Copy for QuerierWrapper<'a, C> {}
209
210impl<'a, C: CustomQuery> Deref for QuerierWrapper<'a, C> {
213 type Target = dyn Querier + 'a;
214
215 fn deref(&self) -> &Self::Target {
216 self.querier
217 }
218}
219
220impl<'a, C: CustomQuery> QuerierWrapper<'a, C> {
221 pub fn new(querier: &'a dyn Querier) -> Self {
222 QuerierWrapper {
223 querier,
224 custom_query_type: PhantomData,
225 }
226 }
227
228 pub fn into_empty(self) -> QuerierWrapper<'a, Empty> {
231 QuerierWrapper {
232 querier: self.querier,
233 custom_query_type: PhantomData,
234 }
235 }
236
237 pub fn query<U: DeserializeOwned>(&self, request: &QueryRequest<C>) -> StdResult<U> {
243 let raw = to_json_vec(request).map_err(|serialize_err| {
244 StdError::generic_err(format!("Serializing QueryRequest: {serialize_err}"))
245 })?;
246 match self.raw_query(&raw) {
247 SystemResult::Err(system_err) => Err(StdError::generic_err(format!(
248 "Querier system error: {system_err}"
249 ))),
250 SystemResult::Ok(ContractResult::Err(contract_err)) => Err(StdError::generic_err(
251 format!("Querier contract error: {contract_err}"),
252 )),
253 SystemResult::Ok(ContractResult::Ok(value)) => from_json(value),
254 }
255 }
256
257 #[cfg(feature = "cosmwasm_1_1")]
258 pub fn query_supply(&self, denom: impl Into<String>) -> StdResult<Coin> {
259 let request = BankQuery::Supply {
260 denom: denom.into(),
261 }
262 .into();
263 let res: SupplyResponse = self.query(&request)?;
264 Ok(res.amount)
265 }
266
267 pub fn query_balance(
268 &self,
269 address: impl Into<String>,
270 denom: impl Into<String>,
271 ) -> StdResult<Coin> {
272 let request = BankQuery::Balance {
273 address: address.into(),
274 denom: denom.into(),
275 }
276 .into();
277 let res: BalanceResponse = self.query(&request)?;
278 Ok(res.amount)
279 }
280
281 pub fn query_all_balances(&self, address: impl Into<String>) -> StdResult<Vec<Coin>> {
282 let request = BankQuery::AllBalances {
283 address: address.into(),
284 }
285 .into();
286 let res: AllBalanceResponse = self.query(&request)?;
287 Ok(res.amount)
288 }
289
290 #[cfg(feature = "cosmwasm_1_3")]
291 pub fn query_delegator_withdraw_address(
292 &self,
293 delegator: impl Into<String>,
294 ) -> StdResult<Addr> {
295 let request = DistributionQuery::DelegatorWithdrawAddress {
296 delegator_address: delegator.into(),
297 }
298 .into();
299 let res: DelegatorWithdrawAddressResponse = self.query(&request)?;
300 Ok(res.withdraw_address)
301 }
302
303 #[cfg(feature = "cosmwasm_1_3")]
304 pub fn query_denom_metadata(&self, denom: impl Into<String>) -> StdResult<DenomMetadata> {
305 let request = BankQuery::DenomMetadata {
306 denom: denom.into(),
307 }
308 .into();
309 let res: DenomMetadataResponse = self.query(&request)?;
310 Ok(res.metadata)
311 }
312
313 #[cfg(feature = "cosmwasm_1_3")]
314 pub fn query_all_denom_metadata(
315 &self,
316 pagination: PageRequest,
317 ) -> StdResult<AllDenomMetadataResponse> {
318 let request = BankQuery::AllDenomMetadata {
319 pagination: Some(pagination),
320 }
321 .into();
322 self.query(&request)
323 }
324
325 #[cfg(feature = "cosmwasm_1_4")]
326 pub fn query_delegation_rewards(
327 &self,
328 delegator: impl Into<String>,
329 validator: impl Into<String>,
330 ) -> StdResult<Vec<crate::DecCoin>> {
331 use crate::DelegationRewardsResponse;
332
333 let request = DistributionQuery::DelegationRewards {
334 delegator_address: delegator.into(),
335 validator_address: validator.into(),
336 }
337 .into();
338 let DelegationRewardsResponse { rewards } = self.query(&request)?;
339
340 Ok(rewards)
341 }
342
343 #[cfg(feature = "cosmwasm_1_4")]
344 pub fn query_delegation_total_rewards(
345 &self,
346 delegator: impl Into<String>,
347 ) -> StdResult<crate::DelegationTotalRewardsResponse> {
348 let request = DistributionQuery::DelegationTotalRewards {
349 delegator_address: delegator.into(),
350 }
351 .into();
352 self.query(&request)
353 }
354
355 #[cfg(feature = "cosmwasm_1_4")]
356 pub fn query_delegator_validators(
357 &self,
358 delegator: impl Into<String>,
359 ) -> StdResult<Vec<String>> {
360 use crate::DelegatorValidatorsResponse;
361
362 let request = DistributionQuery::DelegatorValidators {
363 delegator_address: delegator.into(),
364 }
365 .into();
366 let res: DelegatorValidatorsResponse = self.query(&request)?;
367 Ok(res.validators)
368 }
369
370 pub fn query_wasm_smart<T: DeserializeOwned>(
373 &self,
374 contract_addr: impl Into<String>,
375 msg: &impl Serialize,
376 ) -> StdResult<T> {
377 let request = WasmQuery::Smart {
378 contract_addr: contract_addr.into(),
379 msg: to_json_binary(msg)?,
380 }
381 .into();
382 self.query(&request)
383 }
384
385 pub fn query_wasm_raw(
394 &self,
395 contract_addr: impl Into<String>,
396 key: impl Into<Binary>,
397 ) -> StdResult<Option<Vec<u8>>> {
398 let request: QueryRequest<Empty> = WasmQuery::Raw {
399 contract_addr: contract_addr.into(),
400 key: key.into(),
401 }
402 .into();
403 let raw = to_json_vec(&request).map_err(|serialize_err| {
406 StdError::generic_err(format!("Serializing QueryRequest: {serialize_err}"))
407 })?;
408 match self.raw_query(&raw) {
409 SystemResult::Err(system_err) => Err(StdError::generic_err(format!(
410 "Querier system error: {system_err}"
411 ))),
412 SystemResult::Ok(ContractResult::Err(contract_err)) => Err(StdError::generic_err(
413 format!("Querier contract error: {contract_err}"),
414 )),
415 SystemResult::Ok(ContractResult::Ok(value)) => {
416 if value.is_empty() {
417 Ok(None)
418 } else {
419 Ok(Some(value.into()))
420 }
421 }
422 }
423 }
424
425 pub fn query_wasm_contract_info(
427 &self,
428 contract_addr: impl Into<String>,
429 ) -> StdResult<ContractInfoResponse> {
430 let request = WasmQuery::ContractInfo {
431 contract_addr: contract_addr.into(),
432 }
433 .into();
434 self.query(&request)
435 }
436
437 #[cfg(feature = "cosmwasm_1_2")]
439 pub fn query_wasm_code_info(&self, code_id: u64) -> StdResult<CodeInfoResponse> {
440 let request = WasmQuery::CodeInfo { code_id }.into();
441 self.query(&request)
442 }
443
444 #[cfg(feature = "staking")]
445 pub fn query_all_validators(&self) -> StdResult<Vec<Validator>> {
446 let request = StakingQuery::AllValidators {}.into();
447 let res: AllValidatorsResponse = self.query(&request)?;
448 Ok(res.validators)
449 }
450
451 #[cfg(feature = "staking")]
452 pub fn query_validator(&self, address: impl Into<String>) -> StdResult<Option<Validator>> {
453 let request = StakingQuery::Validator {
454 address: address.into(),
455 }
456 .into();
457 let res: ValidatorResponse = self.query(&request)?;
458 Ok(res.validator)
459 }
460
461 #[cfg(feature = "staking")]
462 pub fn query_bonded_denom(&self) -> StdResult<String> {
463 let request = StakingQuery::BondedDenom {}.into();
464 let res: BondedDenomResponse = self.query(&request)?;
465 Ok(res.denom)
466 }
467
468 #[cfg(feature = "staking")]
469 pub fn query_all_delegations(
470 &self,
471 delegator: impl Into<String>,
472 ) -> StdResult<Vec<Delegation>> {
473 let request = StakingQuery::AllDelegations {
474 delegator: delegator.into(),
475 }
476 .into();
477 let res: AllDelegationsResponse = self.query(&request)?;
478 Ok(res.delegations)
479 }
480
481 #[cfg(feature = "staking")]
482 pub fn query_delegation(
483 &self,
484 delegator: impl Into<String>,
485 validator: impl Into<String>,
486 ) -> StdResult<Option<FullDelegation>> {
487 let request = StakingQuery::Delegation {
488 delegator: delegator.into(),
489 validator: validator.into(),
490 }
491 .into();
492 let res: DelegationResponse = self.query(&request)?;
493 Ok(res.delegation)
494 }
495}
496
497#[cfg(test)]
498mod tests {
499 use serde::Deserialize;
500
501 use super::*;
502 use crate::testing::MockQuerier;
503 use crate::{coins, from_json, Uint128};
504
505 fn demo_helper(_querier: &dyn Querier) -> u64 {
507 2
508 }
509
510 #[test]
512 fn use_querier_wrapper_as_querier() {
513 let querier: MockQuerier<Empty> = MockQuerier::new(&[]);
514 let wrapper = QuerierWrapper::<Empty>::new(&querier);
515
516 let res = demo_helper(&*wrapper);
518 assert_eq!(2, res);
519
520 let res = demo_helper(wrapper.deref());
522 assert_eq!(2, res);
523 }
524
525 #[test]
526 fn auto_deref_raw_query() {
527 let acct = String::from("foobar");
528 let querier: MockQuerier<Empty> = MockQuerier::new(&[(&acct, &coins(5, "BTC"))]);
529 let wrapper = QuerierWrapper::<Empty>::new(&querier);
530 let query = QueryRequest::<Empty>::Bank(BankQuery::Balance {
531 address: acct,
532 denom: "BTC".to_string(),
533 });
534
535 let raw = wrapper
536 .raw_query(&to_json_vec(&query).unwrap())
537 .unwrap()
538 .unwrap();
539 let balance: BalanceResponse = from_json(raw).unwrap();
540 assert_eq!(balance.amount.amount, Uint128::new(5));
541 }
542
543 #[cfg(feature = "cosmwasm_1_1")]
544 #[test]
545 fn bank_query_helpers_work() {
546 use crate::coin;
547
548 let querier: MockQuerier<Empty> = MockQuerier::new(&[
549 ("foo", &[coin(123, "ELF"), coin(777, "FLY")]),
550 ("bar", &[coin(321, "ELF")]),
551 ]);
552 let wrapper = QuerierWrapper::<Empty>::new(&querier);
553
554 let supply = wrapper.query_supply("ELF").unwrap();
555 assert_eq!(supply, coin(444, "ELF"));
556
557 let balance = wrapper.query_balance("foo", "ELF").unwrap();
558 assert_eq!(balance, coin(123, "ELF"));
559
560 let all_balances = wrapper.query_all_balances("foo").unwrap();
561 assert_eq!(all_balances, vec![coin(123, "ELF"), coin(777, "FLY")]);
562 }
563
564 #[test]
565 fn contract_info() {
566 const ACCT: &str = "foobar";
567 fn mock_resp() -> ContractInfoResponse {
568 ContractInfoResponse {
569 code_id: 0,
570 creator: "creator".to_string(),
571 admin: None,
572 pinned: false,
573 ibc_port: None,
574 }
575 }
576
577 let mut querier: MockQuerier<Empty> = MockQuerier::new(&[(ACCT, &coins(5, "BTC"))]);
578 querier.update_wasm(|q| -> QuerierResult {
579 if q == &(WasmQuery::ContractInfo {
580 contract_addr: ACCT.to_string(),
581 }) {
582 SystemResult::Ok(ContractResult::Ok(to_json_binary(&mock_resp()).unwrap()))
583 } else {
584 SystemResult::Err(crate::SystemError::NoSuchContract {
585 addr: ACCT.to_string(),
586 })
587 }
588 });
589 let wrapper = QuerierWrapper::<Empty>::new(&querier);
590
591 let contract_info = wrapper.query_wasm_contract_info(ACCT).unwrap();
592 assert_eq!(contract_info, mock_resp());
593 }
594
595 #[test]
596 fn contract_info_err() {
597 const ACCT: &str = "foobar";
598 fn mock_resp() -> ContractInfoResponse {
599 ContractInfoResponse {
600 code_id: 0,
601 creator: "creator".to_string(),
602 admin: None,
603 pinned: false,
604 ibc_port: None,
605 }
606 }
607
608 let mut querier: MockQuerier<Empty> = MockQuerier::new(&[(ACCT, &coins(5, "BTC"))]);
609 querier.update_wasm(|q| -> QuerierResult {
610 if q == &(WasmQuery::ContractInfo {
611 contract_addr: ACCT.to_string(),
612 }) {
613 SystemResult::Ok(ContractResult::Ok(to_json_binary(&mock_resp()).unwrap()))
614 } else {
615 SystemResult::Err(crate::SystemError::NoSuchContract {
616 addr: ACCT.to_string(),
617 })
618 }
619 });
620 let wrapper = QuerierWrapper::<Empty>::new(&querier);
621
622 let err = wrapper.query_wasm_contract_info("unknown").unwrap_err();
623 assert!(matches!(
624 err,
625 StdError::GenericErr {
626 msg,
627 ..
628 } if msg == "Querier system error: No such contract: foobar"
629 ));
630 }
631
632 #[test]
633 fn querier_into_empty() {
634 #[derive(Clone, Serialize, Deserialize)]
635 struct MyQuery;
636 impl CustomQuery for MyQuery {}
637
638 let querier: MockQuerier<MyQuery> = MockQuerier::new(&[]);
639 let wrapper = QuerierWrapper::<MyQuery>::new(&querier);
640
641 let _: QuerierWrapper<Empty> = wrapper.into_empty();
642 }
643}