1use alloc::collections::BTreeMap;
2use bech32::{encode, ToBase32, Variant};
3use core::marker::PhantomData;
4#[cfg(feature = "cosmwasm_1_3")]
5use core::ops::Bound;
6use serde::de::DeserializeOwned;
7#[cfg(feature = "stargate")]
8use serde::Serialize;
9use sha2::{Digest, Sha256};
10#[cfg(feature = "cosmwasm_1_3")]
11use std::collections::BTreeSet;
12use std::collections::HashMap;
13
14use crate::addresses::{Addr, CanonicalAddr};
15use crate::binary::Binary;
16use crate::coin::Coin;
17use crate::deps::OwnedDeps;
18use crate::errors::{RecoverPubkeyError, StdError, StdResult, SystemError, VerificationError};
19#[cfg(feature = "stargate")]
20use crate::ibc::{
21 IbcAcknowledgement, IbcChannel, IbcChannelCloseMsg, IbcChannelConnectMsg, IbcChannelOpenMsg,
22 IbcEndpoint, IbcOrder, IbcPacket, IbcPacketAckMsg, IbcPacketReceiveMsg, IbcPacketTimeoutMsg,
23 IbcTimeoutBlock,
24};
25use crate::math::Uint128;
26#[cfg(feature = "cosmwasm_1_1")]
27use crate::query::SupplyResponse;
28use crate::query::{
29 AllBalanceResponse, BalanceResponse, BankQuery, CustomQuery, QueryRequest, WasmQuery,
30};
31#[cfg(feature = "staking")]
32use crate::query::{
33 AllDelegationsResponse, AllValidatorsResponse, BondedDenomResponse, DelegationResponse,
34 FullDelegation, StakingQuery, Validator, ValidatorResponse,
35};
36#[cfg(feature = "cosmwasm_1_3")]
37use crate::query::{DelegatorWithdrawAddressResponse, DistributionQuery};
38use crate::results::{ContractResult, Empty, SystemResult};
39use crate::serde::{from_json, to_json_binary};
40use crate::storage::MemoryStorage;
41use crate::timestamp::Timestamp;
42use crate::traits::{Api, Querier, QuerierResult};
43use crate::types::{BlockInfo, ContractInfo, Env, MessageInfo, TransactionInfo};
44#[cfg(feature = "cosmwasm_1_3")]
45use crate::{
46 query::{AllDenomMetadataResponse, DecCoin, DenomMetadataResponse},
47 PageRequest,
48};
49use crate::{Attribute, DenomMetadata};
50#[cfg(feature = "stargate")]
51use crate::{ChannelResponse, IbcQuery, ListChannelsResponse, PortIdResponse};
52#[cfg(feature = "cosmwasm_1_4")]
53use crate::{Decimal256, DelegationRewardsResponse, DelegatorValidatorsResponse};
54
55use super::riffle_shuffle;
56
57pub const MOCK_CONTRACT_ADDR: &str = "cosmos2contract";
58
59pub fn mock_dependencies() -> OwnedDeps<MockStorage, MockApi, MockQuerier, Empty> {
64 OwnedDeps {
65 storage: MockStorage::default(),
66 api: MockApi::default(),
67 querier: MockQuerier::default(),
68 custom_query_type: PhantomData,
69 }
70}
71
72pub fn mock_dependencies_with_balance(
76 contract_balance: &[Coin],
77) -> OwnedDeps<MockStorage, MockApi, MockQuerier, Empty> {
78 mock_dependencies_with_balances(&[(MOCK_CONTRACT_ADDR, contract_balance)])
79}
80
81pub fn mock_dependencies_with_balances(
84 balances: &[(&str, &[Coin])],
85) -> OwnedDeps<MockStorage, MockApi, MockQuerier> {
86 OwnedDeps {
87 storage: MockStorage::default(),
88 api: MockApi::default(),
89 querier: MockQuerier::new(balances),
90 custom_query_type: PhantomData,
91 }
92}
93
94pub type MockStorage = MemoryStorage;
97
98const CANONICAL_LENGTH: usize = 90; const SHUFFLES_ENCODE: usize = 10;
109const SHUFFLES_DECODE: usize = 2;
110
111const BECH32_PREFIX: &str = "cosmwasm";
113
114#[derive(Copy, Clone)]
118pub struct MockApi {
119 canonical_length: usize,
122 bech32_prefix: &'static str,
124}
125
126impl Default for MockApi {
127 fn default() -> Self {
128 MockApi {
129 canonical_length: CANONICAL_LENGTH,
130 bech32_prefix: BECH32_PREFIX,
131 }
132 }
133}
134
135impl Api for MockApi {
136 fn addr_validate(&self, input: &str) -> StdResult<Addr> {
137 let canonical = self.addr_canonicalize(input)?;
138 let normalized = self.addr_humanize(&canonical)?;
139 if input != normalized {
140 return Err(StdError::generic_err(
141 "Invalid input: address not normalized",
142 ));
143 }
144
145 Ok(Addr::unchecked(input))
146 }
147
148 fn addr_canonicalize(&self, input: &str) -> StdResult<CanonicalAddr> {
149 let min_length = 3;
151 let max_length = self.canonical_length;
152 if input.len() < min_length {
153 return Err(StdError::generic_err(
154 format!("Invalid input: human address too short for this mock implementation (must be >= {min_length})."),
155 ));
156 }
157 if input.len() > max_length {
158 return Err(StdError::generic_err(
159 format!("Invalid input: human address too long for this mock implementation (must be <= {max_length})."),
160 ));
161 }
162
163 let normalized = input.to_lowercase();
165
166 let mut out = Vec::from(normalized);
167
168 out.resize(self.canonical_length, 0x00);
170 let rotate_by = digit_sum(&out) % self.canonical_length;
173 out.rotate_left(rotate_by);
174 for _ in 0..SHUFFLES_ENCODE {
175 out = riffle_shuffle(&out);
176 }
177 Ok(out.into())
178 }
179
180 fn addr_humanize(&self, canonical: &CanonicalAddr) -> StdResult<Addr> {
181 if canonical.len() != self.canonical_length {
182 return Err(StdError::generic_err(
183 "Invalid input: canonical address length not correct",
184 ));
185 }
186
187 let mut tmp: Vec<u8> = canonical.clone().into();
188 for _ in 0..SHUFFLES_DECODE {
190 tmp = riffle_shuffle(&tmp);
191 }
192 let rotate_by = digit_sum(&tmp) % self.canonical_length;
194 tmp.rotate_right(rotate_by);
195 let trimmed = tmp.into_iter().filter(|&x| x != 0x00).collect();
197 let human = String::from_utf8(trimmed)?;
199 Ok(Addr::unchecked(human))
200 }
201
202 fn secp256k1_verify(
203 &self,
204 message_hash: &[u8],
205 signature: &[u8],
206 public_key: &[u8],
207 ) -> Result<bool, VerificationError> {
208 Ok(cosmwasm_crypto::secp256k1_verify(
209 message_hash,
210 signature,
211 public_key,
212 )?)
213 }
214
215 fn secp256k1_recover_pubkey(
216 &self,
217 message_hash: &[u8],
218 signature: &[u8],
219 recovery_param: u8,
220 ) -> Result<Vec<u8>, RecoverPubkeyError> {
221 let pubkey =
222 cosmwasm_crypto::secp256k1_recover_pubkey(message_hash, signature, recovery_param)?;
223 Ok(pubkey.to_vec())
224 }
225
226 fn ed25519_verify(
227 &self,
228 message: &[u8],
229 signature: &[u8],
230 public_key: &[u8],
231 ) -> Result<bool, VerificationError> {
232 Ok(cosmwasm_crypto::ed25519_verify(
233 message, signature, public_key,
234 )?)
235 }
236
237 fn ed25519_batch_verify(
238 &self,
239 messages: &[&[u8]],
240 signatures: &[&[u8]],
241 public_keys: &[&[u8]],
242 ) -> Result<bool, VerificationError> {
243 Ok(cosmwasm_crypto::ed25519_batch_verify(
244 messages,
245 signatures,
246 public_keys,
247 )?)
248 }
249
250 fn debug(&self, message: &str) {
251 println!("{message}");
252 }
253}
254
255impl MockApi {
256 pub fn with_prefix(mut self, prefix: &'static str) -> Self {
272 self.bech32_prefix = prefix;
273 self
274 }
275
276 pub fn addr_make(&self, input: &str) -> Addr {
296 let digest = Sha256::digest(input).to_vec();
297 match encode(self.bech32_prefix, digest.to_base32(), Variant::Bech32) {
298 Ok(address) => Addr::unchecked(address),
299 Err(reason) => panic!("Generating address failed with reason: {reason}"),
300 }
301 }
302}
303
304pub fn mock_env() -> Env {
310 Env {
311 block: BlockInfo {
312 height: 12_345,
313 time: Timestamp::from_nanos(1_571_797_419_879_305_533),
314 chain_id: "cosmos-testnet-14002".to_string(),
315 },
316 transaction: Some(TransactionInfo { index: 3 }),
317 contract: ContractInfo {
318 address: Addr::unchecked(MOCK_CONTRACT_ADDR),
319 },
320 }
321}
322
323pub fn mock_info(sender: &str, funds: &[Coin]) -> MessageInfo {
326 MessageInfo {
327 sender: Addr::unchecked(sender),
328 funds: funds.to_vec(),
329 }
330}
331
332#[cfg(feature = "stargate")]
335pub fn mock_ibc_channel(my_channel_id: &str, order: IbcOrder, version: &str) -> IbcChannel {
336 IbcChannel {
337 endpoint: IbcEndpoint {
338 port_id: "my_port".to_string(),
339 channel_id: my_channel_id.to_string(),
340 },
341 counterparty_endpoint: IbcEndpoint {
342 port_id: "their_port".to_string(),
343 channel_id: "channel-7".to_string(),
344 },
345 order,
346 version: version.to_string(),
347 connection_id: "connection-2".to_string(),
348 }
349}
350
351#[cfg(feature = "stargate")]
353pub fn mock_ibc_channel_open_init(
354 my_channel_id: &str,
355 order: IbcOrder,
356 version: &str,
357) -> IbcChannelOpenMsg {
358 IbcChannelOpenMsg::new_init(mock_ibc_channel(my_channel_id, order, version))
359}
360
361#[cfg(feature = "stargate")]
363pub fn mock_ibc_channel_open_try(
364 my_channel_id: &str,
365 order: IbcOrder,
366 version: &str,
367) -> IbcChannelOpenMsg {
368 IbcChannelOpenMsg::new_try(mock_ibc_channel(my_channel_id, order, version), version)
369}
370
371#[cfg(feature = "stargate")]
373pub fn mock_ibc_channel_connect_ack(
374 my_channel_id: &str,
375 order: IbcOrder,
376 version: &str,
377) -> IbcChannelConnectMsg {
378 IbcChannelConnectMsg::new_ack(mock_ibc_channel(my_channel_id, order, version), version)
379}
380
381#[cfg(feature = "stargate")]
383pub fn mock_ibc_channel_connect_confirm(
384 my_channel_id: &str,
385 order: IbcOrder,
386 version: &str,
387) -> IbcChannelConnectMsg {
388 IbcChannelConnectMsg::new_confirm(mock_ibc_channel(my_channel_id, order, version))
389}
390
391#[cfg(feature = "stargate")]
393pub fn mock_ibc_channel_close_init(
394 my_channel_id: &str,
395 order: IbcOrder,
396 version: &str,
397) -> IbcChannelCloseMsg {
398 IbcChannelCloseMsg::new_init(mock_ibc_channel(my_channel_id, order, version))
399}
400
401#[cfg(feature = "stargate")]
403pub fn mock_ibc_channel_close_confirm(
404 my_channel_id: &str,
405 order: IbcOrder,
406 version: &str,
407) -> IbcChannelCloseMsg {
408 IbcChannelCloseMsg::new_confirm(mock_ibc_channel(my_channel_id, order, version))
409}
410
411#[cfg(feature = "stargate")]
414pub fn mock_ibc_packet_recv(
415 my_channel_id: &str,
416 data: &impl Serialize,
417) -> StdResult<IbcPacketReceiveMsg> {
418 Ok(IbcPacketReceiveMsg::new(
419 IbcPacket {
420 data: to_json_binary(data)?,
421 src: IbcEndpoint {
422 port_id: "their-port".to_string(),
423 channel_id: "channel-1234".to_string(),
424 },
425 dest: IbcEndpoint {
426 port_id: "our-port".to_string(),
427 channel_id: my_channel_id.into(),
428 },
429 sequence: 27,
430 timeout: IbcTimeoutBlock {
431 revision: 1,
432 height: 12345678,
433 }
434 .into(),
435 },
436 #[cfg(feature = "ibc3")]
437 Addr::unchecked("relayer"),
438 ))
439}
440
441#[cfg(feature = "stargate")]
445fn mock_ibc_packet(my_channel_id: &str, data: &impl Serialize) -> StdResult<IbcPacket> {
446 Ok(IbcPacket {
447 data: to_json_binary(data)?,
448 src: IbcEndpoint {
449 port_id: "their-port".to_string(),
450 channel_id: my_channel_id.into(),
451 },
452 dest: IbcEndpoint {
453 port_id: "our-port".to_string(),
454 channel_id: "channel-1234".to_string(),
455 },
456 sequence: 29,
457 timeout: IbcTimeoutBlock {
458 revision: 1,
459 height: 432332552,
460 }
461 .into(),
462 })
463}
464
465#[cfg(feature = "stargate")]
469pub fn mock_ibc_packet_ack(
470 my_channel_id: &str,
471 data: &impl Serialize,
472 ack: IbcAcknowledgement,
473) -> StdResult<IbcPacketAckMsg> {
474 let packet = mock_ibc_packet(my_channel_id, data)?;
475
476 Ok(IbcPacketAckMsg::new(
477 ack,
478 packet,
479 #[cfg(feature = "ibc3")]
480 Addr::unchecked("relayer"),
481 ))
482}
483
484#[cfg(feature = "stargate")]
488pub fn mock_ibc_packet_timeout(
489 my_channel_id: &str,
490 data: &impl Serialize,
491) -> StdResult<IbcPacketTimeoutMsg> {
492 let packet = mock_ibc_packet(my_channel_id, data)?;
493 Ok(IbcPacketTimeoutMsg::new(
494 packet,
495 #[cfg(feature = "ibc3")]
496 Addr::unchecked("relayer"),
497 ))
498}
499
500pub type MockQuerierCustomHandlerResult = SystemResult<ContractResult<Binary>>;
503
504pub struct MockQuerier<C: DeserializeOwned = Empty> {
507 bank: BankQuerier,
508 #[cfg(feature = "staking")]
509 staking: StakingQuerier,
510 #[cfg(feature = "cosmwasm_1_3")]
511 distribution: DistributionQuerier,
512 wasm: WasmQuerier,
513 #[cfg(feature = "stargate")]
514 ibc: IbcQuerier,
515 custom_handler: Box<dyn for<'a> Fn(&'a C) -> MockQuerierCustomHandlerResult>,
520}
521
522impl<C: DeserializeOwned> MockQuerier<C> {
523 pub fn new(balances: &[(&str, &[Coin])]) -> Self {
524 MockQuerier {
525 bank: BankQuerier::new(balances),
526 #[cfg(feature = "cosmwasm_1_3")]
527 distribution: DistributionQuerier::default(),
528 #[cfg(feature = "staking")]
529 staking: StakingQuerier::default(),
530 wasm: WasmQuerier::default(),
531 #[cfg(feature = "stargate")]
532 ibc: IbcQuerier::default(),
533 custom_handler: Box::from(|_: &_| -> MockQuerierCustomHandlerResult {
535 SystemResult::Err(SystemError::UnsupportedRequest {
536 kind: "custom".to_string(),
537 })
538 }),
539 }
540 }
541
542 pub fn update_balance(
544 &mut self,
545 addr: impl Into<String>,
546 balance: Vec<Coin>,
547 ) -> Option<Vec<Coin>> {
548 self.bank.update_balance(addr, balance)
549 }
550
551 pub fn set_denom_metadata(&mut self, denom_metadata: &[DenomMetadata]) {
552 self.bank.set_denom_metadata(denom_metadata);
553 }
554
555 #[cfg(feature = "cosmwasm_1_3")]
556 pub fn set_withdraw_address(
557 &mut self,
558 delegator_address: impl Into<String>,
559 withdraw_address: impl Into<String>,
560 ) {
561 self.distribution
562 .set_withdraw_address(delegator_address, withdraw_address);
563 }
564
565 #[cfg(feature = "cosmwasm_1_3")]
570 pub fn set_withdraw_addresses(
571 &mut self,
572 withdraw_addresses: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>,
573 ) {
574 self.distribution.set_withdraw_addresses(withdraw_addresses);
575 }
576
577 #[cfg(feature = "cosmwasm_1_3")]
578 pub fn clear_withdraw_addresses(&mut self) {
579 self.distribution.clear_withdraw_addresses();
580 }
581
582 #[cfg(feature = "staking")]
583 pub fn update_staking(
584 &mut self,
585 denom: &str,
586 validators: &[crate::query::Validator],
587 delegations: &[crate::query::FullDelegation],
588 ) {
589 self.staking = StakingQuerier::new(denom, validators, delegations);
590 }
591
592 #[cfg(feature = "stargate")]
593 pub fn update_ibc(&mut self, port_id: &str, channels: &[IbcChannel]) {
594 self.ibc = IbcQuerier::new(port_id, channels);
595 }
596
597 pub fn update_wasm<WH: 'static>(&mut self, handler: WH)
598 where
599 WH: Fn(&WasmQuery) -> QuerierResult,
600 {
601 self.wasm.update_handler(handler)
602 }
603
604 pub fn with_custom_handler<CH: 'static>(mut self, handler: CH) -> Self
605 where
606 CH: Fn(&C) -> MockQuerierCustomHandlerResult,
607 {
608 self.custom_handler = Box::from(handler);
609 self
610 }
611}
612
613impl Default for MockQuerier {
614 fn default() -> Self {
615 MockQuerier::new(&[])
616 }
617}
618
619impl<C: CustomQuery + DeserializeOwned> Querier for MockQuerier<C> {
620 fn raw_query(&self, bin_request: &[u8]) -> QuerierResult {
621 let request: QueryRequest<C> = match from_json(bin_request) {
622 Ok(v) => v,
623 Err(e) => {
624 return SystemResult::Err(SystemError::InvalidRequest {
625 error: format!("Parsing query request: {e}"),
626 request: bin_request.into(),
627 })
628 }
629 };
630 self.handle_query(&request)
631 }
632}
633
634impl<C: CustomQuery + DeserializeOwned> MockQuerier<C> {
635 pub fn handle_query(&self, request: &QueryRequest<C>) -> QuerierResult {
636 match &request {
637 QueryRequest::Bank(bank_query) => self.bank.query(bank_query),
638 QueryRequest::Custom(custom_query) => (*self.custom_handler)(custom_query),
639 #[cfg(feature = "staking")]
640 QueryRequest::Staking(staking_query) => self.staking.query(staking_query),
641 #[cfg(feature = "cosmwasm_1_3")]
642 QueryRequest::Distribution(distribution_query) => {
643 self.distribution.query(distribution_query)
644 }
645 QueryRequest::Wasm(msg) => self.wasm.query(msg),
646 #[cfg(feature = "stargate")]
647 QueryRequest::Stargate { .. } => SystemResult::Err(SystemError::UnsupportedRequest {
648 kind: "Stargate".to_string(),
649 }),
650 #[cfg(feature = "stargate")]
651 QueryRequest::Ibc(msg) => self.ibc.query(msg),
652 }
653 }
654}
655
656struct WasmQuerier {
657 handler: Box<dyn for<'a> Fn(&'a WasmQuery) -> QuerierResult>,
662}
663
664impl WasmQuerier {
665 fn new(handler: Box<dyn for<'a> Fn(&'a WasmQuery) -> QuerierResult>) -> Self {
666 Self { handler }
667 }
668
669 fn update_handler<WH: 'static>(&mut self, handler: WH)
670 where
671 WH: Fn(&WasmQuery) -> QuerierResult,
672 {
673 self.handler = Box::from(handler)
674 }
675
676 fn query(&self, request: &WasmQuery) -> QuerierResult {
677 (*self.handler)(request)
678 }
679}
680
681impl Default for WasmQuerier {
682 fn default() -> Self {
683 let handler = Box::from(|request: &WasmQuery| -> QuerierResult {
684 let err = match request {
685 WasmQuery::Smart { contract_addr, .. } => SystemError::NoSuchContract {
686 addr: contract_addr.clone(),
687 },
688 WasmQuery::Raw { contract_addr, .. } => SystemError::NoSuchContract {
689 addr: contract_addr.clone(),
690 },
691 WasmQuery::ContractInfo { contract_addr, .. } => SystemError::NoSuchContract {
692 addr: contract_addr.clone(),
693 },
694 #[cfg(feature = "cosmwasm_1_2")]
695 WasmQuery::CodeInfo { code_id, .. } => {
696 SystemError::NoSuchCode { code_id: *code_id }
697 }
698 };
699 SystemResult::Err(err)
700 });
701 Self::new(handler)
702 }
703}
704
705#[derive(Clone, Default)]
706pub struct BankQuerier {
707 #[allow(dead_code)]
708 supplies: HashMap<String, Uint128>,
710 balances: HashMap<String, Vec<Coin>>,
712 denom_metadata: BTreeMap<Vec<u8>, DenomMetadata>,
714}
715
716impl BankQuerier {
717 pub fn new(balances: &[(&str, &[Coin])]) -> Self {
718 let balances: HashMap<_, _> = balances
719 .iter()
720 .map(|(s, c)| (s.to_string(), c.to_vec()))
721 .collect();
722
723 BankQuerier {
724 supplies: Self::calculate_supplies(&balances),
725 balances,
726 denom_metadata: BTreeMap::new(),
727 }
728 }
729
730 pub fn update_balance(
731 &mut self,
732 addr: impl Into<String>,
733 balance: Vec<Coin>,
734 ) -> Option<Vec<Coin>> {
735 let result = self.balances.insert(addr.into(), balance);
736 self.supplies = Self::calculate_supplies(&self.balances);
737
738 result
739 }
740
741 pub fn set_denom_metadata(&mut self, denom_metadata: &[DenomMetadata]) {
742 self.denom_metadata = denom_metadata
743 .iter()
744 .map(|d| (d.base.as_bytes().to_vec(), d.clone()))
745 .collect();
746 }
747
748 fn calculate_supplies(balances: &HashMap<String, Vec<Coin>>) -> HashMap<String, Uint128> {
749 let mut supplies = HashMap::new();
750
751 let all_coins = balances.iter().flat_map(|(_, coins)| coins);
752
753 for coin in all_coins {
754 *supplies
755 .entry(coin.denom.clone())
756 .or_insert_with(Uint128::zero) += coin.amount;
757 }
758
759 supplies
760 }
761
762 pub fn query(&self, request: &BankQuery) -> QuerierResult {
763 let contract_result: ContractResult<Binary> = match request {
764 #[cfg(feature = "cosmwasm_1_1")]
765 BankQuery::Supply { denom } => {
766 let amount = self
767 .supplies
768 .get(denom)
769 .cloned()
770 .unwrap_or_else(Uint128::zero);
771 let bank_res = SupplyResponse {
772 amount: Coin {
773 amount,
774 denom: denom.to_string(),
775 },
776 };
777 to_json_binary(&bank_res).into()
778 }
779 BankQuery::Balance { address, denom } => {
780 let amount = self
782 .balances
783 .get(address)
784 .and_then(|v| v.iter().find(|c| &c.denom == denom).map(|c| c.amount))
785 .unwrap_or_default();
786 let bank_res = BalanceResponse {
787 amount: Coin {
788 amount,
789 denom: denom.to_string(),
790 },
791 };
792 to_json_binary(&bank_res).into()
793 }
794 BankQuery::AllBalances { address } => {
795 let bank_res = AllBalanceResponse {
797 amount: self.balances.get(address).cloned().unwrap_or_default(),
798 };
799 to_json_binary(&bank_res).into()
800 }
801 #[cfg(feature = "cosmwasm_1_3")]
802 BankQuery::DenomMetadata { denom } => {
803 let denom_metadata = self.denom_metadata.get(denom.as_bytes());
804 match denom_metadata {
805 Some(m) => {
806 let metadata_res = DenomMetadataResponse {
807 metadata: m.clone(),
808 };
809 to_json_binary(&metadata_res).into()
810 }
811 None => return SystemResult::Err(SystemError::Unknown {}),
812 }
813 }
814 #[cfg(feature = "cosmwasm_1_3")]
815 BankQuery::AllDenomMetadata { pagination } => {
816 let default_pagination = PageRequest {
817 key: None,
818 limit: 100,
819 reverse: false,
820 };
821 let pagination = pagination.as_ref().unwrap_or(&default_pagination);
822
823 let range = match (pagination.reverse, &pagination.key) {
825 (_, None) => (Bound::Unbounded, Bound::Unbounded),
826 (true, Some(key)) => (Bound::Unbounded, Bound::Included(key.as_slice())),
827 (false, Some(key)) => (Bound::Included(key.as_slice()), Bound::Unbounded),
828 };
829 let iter = self.denom_metadata.range::<[u8], _>(range);
830 let iter: Box<dyn Iterator<Item = _>> = if pagination.reverse {
832 Box::new(iter.rev())
833 } else {
834 Box::new(iter)
835 };
836
837 let mut metadata: Vec<_> = iter
838 .take((pagination.limit.saturating_add(1)) as usize)
840 .map(|(_, m)| m.clone())
841 .collect();
842
843 let next_key = if metadata.len() > pagination.limit as usize {
846 metadata.pop().map(|m| Binary::from(m.base.as_bytes()))
847 } else {
848 None
849 };
850
851 let metadata_res = AllDenomMetadataResponse { metadata, next_key };
852 to_json_binary(&metadata_res).into()
853 }
854 };
855 SystemResult::Ok(contract_result)
857 }
858}
859
860#[cfg(feature = "stargate")]
861#[derive(Clone, Default)]
862pub struct IbcQuerier {
863 port_id: String,
864 channels: Vec<IbcChannel>,
865}
866
867#[cfg(feature = "stargate")]
868impl IbcQuerier {
869 pub fn new(port_id: &str, channels: &[IbcChannel]) -> Self {
873 IbcQuerier {
874 port_id: port_id.to_string(),
875 channels: channels.to_vec(),
876 }
877 }
878
879 pub fn query(&self, request: &IbcQuery) -> QuerierResult {
880 let contract_result: ContractResult<Binary> = match request {
881 IbcQuery::Channel {
882 channel_id,
883 port_id,
884 } => {
885 let channel = self
886 .channels
887 .iter()
888 .find(|c| match port_id {
889 Some(p) => c.endpoint.channel_id.eq(channel_id) && c.endpoint.port_id.eq(p),
890 None => {
891 c.endpoint.channel_id.eq(channel_id)
892 && c.endpoint.port_id == self.port_id
893 }
894 })
895 .cloned();
896 let res = ChannelResponse { channel };
897 to_json_binary(&res).into()
898 }
899 IbcQuery::ListChannels { port_id } => {
900 let channels = self
901 .channels
902 .iter()
903 .filter(|c| match port_id {
904 Some(p) => c.endpoint.port_id.eq(p),
905 None => c.endpoint.port_id == self.port_id,
906 })
907 .cloned()
908 .collect();
909 let res = ListChannelsResponse { channels };
910 to_json_binary(&res).into()
911 }
912 IbcQuery::PortId {} => {
913 let res = PortIdResponse {
914 port_id: self.port_id.clone(),
915 };
916 to_json_binary(&res).into()
917 }
918 };
919 SystemResult::Ok(contract_result)
921 }
922}
923
924#[cfg(feature = "staking")]
925#[derive(Clone, Default)]
926pub struct StakingQuerier {
927 denom: String,
928 validators: Vec<Validator>,
929 delegations: Vec<FullDelegation>,
930}
931
932#[cfg(feature = "staking")]
933impl StakingQuerier {
934 pub fn new(denom: &str, validators: &[Validator], delegations: &[FullDelegation]) -> Self {
935 StakingQuerier {
936 denom: denom.to_string(),
937 validators: validators.to_vec(),
938 delegations: delegations.to_vec(),
939 }
940 }
941
942 pub fn query(&self, request: &StakingQuery) -> QuerierResult {
943 let contract_result: ContractResult<Binary> = match request {
944 StakingQuery::BondedDenom {} => {
945 let res = BondedDenomResponse {
946 denom: self.denom.clone(),
947 };
948 to_json_binary(&res).into()
949 }
950 StakingQuery::AllValidators {} => {
951 let res = AllValidatorsResponse {
952 validators: self.validators.clone(),
953 };
954 to_json_binary(&res).into()
955 }
956 StakingQuery::Validator { address } => {
957 let validator: Option<Validator> = self
958 .validators
959 .iter()
960 .find(|validator| validator.address == *address)
961 .cloned();
962 let res = ValidatorResponse { validator };
963 to_json_binary(&res).into()
964 }
965 StakingQuery::AllDelegations { delegator } => {
966 let delegations: Vec<_> = self
967 .delegations
968 .iter()
969 .filter(|d| d.delegator.as_str() == delegator)
970 .cloned()
971 .map(|d| d.into())
972 .collect();
973 let res = AllDelegationsResponse { delegations };
974 to_json_binary(&res).into()
975 }
976 StakingQuery::Delegation {
977 delegator,
978 validator,
979 } => {
980 let delegation = self
981 .delegations
982 .iter()
983 .find(|d| d.delegator.as_str() == delegator && d.validator == *validator);
984 let res = DelegationResponse {
985 delegation: delegation.cloned(),
986 };
987 to_json_binary(&res).into()
988 }
989 };
990 SystemResult::Ok(contract_result)
992 }
993}
994
995#[cfg(feature = "cosmwasm_1_3")]
996#[derive(Clone, Default)]
997pub struct DistributionQuerier {
998 withdraw_addresses: HashMap<String, String>,
999 rewards: BTreeMap<String, BTreeMap<String, Vec<DecCoin>>>,
1001 validators: BTreeMap<String, BTreeSet<String>>,
1003}
1004
1005#[cfg(feature = "cosmwasm_1_3")]
1006impl DistributionQuerier {
1007 pub fn new(withdraw_addresses: HashMap<String, String>) -> Self {
1008 DistributionQuerier {
1009 withdraw_addresses,
1010 ..Default::default()
1011 }
1012 }
1013
1014 pub fn set_withdraw_address(
1015 &mut self,
1016 delegator_address: impl Into<String>,
1017 withdraw_address: impl Into<String>,
1018 ) {
1019 self.withdraw_addresses
1020 .insert(delegator_address.into(), withdraw_address.into());
1021 }
1022
1023 pub fn set_withdraw_addresses(
1028 &mut self,
1029 withdraw_addresses: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>,
1030 ) {
1031 for (d, w) in withdraw_addresses {
1032 self.set_withdraw_address(d, w);
1033 }
1034 }
1035
1036 pub fn clear_withdraw_addresses(&mut self) {
1037 self.withdraw_addresses.clear();
1038 }
1039
1040 pub fn set_rewards(
1042 &mut self,
1043 validator: impl Into<String>,
1044 delegator: impl Into<String>,
1045 rewards: Vec<DecCoin>,
1046 ) {
1047 self.rewards
1048 .entry(delegator.into())
1049 .or_default()
1050 .insert(validator.into(), rewards);
1051 }
1052
1053 pub fn set_validators(
1055 &mut self,
1056 delegator: impl Into<String>,
1057 validators: impl IntoIterator<Item = impl Into<String>>,
1058 ) {
1059 self.validators.insert(
1060 delegator.into(),
1061 validators.into_iter().map(Into::into).collect(),
1062 );
1063 }
1064
1065 pub fn query(&self, request: &DistributionQuery) -> QuerierResult {
1066 let contract_result: ContractResult<Binary> = match request {
1067 DistributionQuery::DelegatorWithdrawAddress { delegator_address } => {
1068 let res = DelegatorWithdrawAddressResponse {
1069 withdraw_address: Addr::unchecked(
1070 self.withdraw_addresses
1071 .get(delegator_address)
1072 .unwrap_or(delegator_address),
1073 ),
1074 };
1075 to_json_binary(&res).into()
1076 }
1077 #[cfg(feature = "cosmwasm_1_4")]
1078 DistributionQuery::DelegationRewards {
1079 delegator_address,
1080 validator_address,
1081 } => {
1082 let res = DelegationRewardsResponse {
1083 rewards: self
1084 .rewards
1085 .get(delegator_address)
1086 .and_then(|v| v.get(validator_address))
1087 .cloned()
1088 .unwrap_or_default(),
1089 };
1090 to_json_binary(&res).into()
1091 }
1092 #[cfg(feature = "cosmwasm_1_4")]
1093 DistributionQuery::DelegationTotalRewards { delegator_address } => {
1094 let validator_rewards = self
1095 .validator_rewards(delegator_address)
1096 .unwrap_or_default();
1097 let res = crate::DelegationTotalRewardsResponse {
1098 total: validator_rewards
1099 .iter()
1100 .fold(BTreeMap::<&str, DecCoin>::new(), |mut acc, rewards| {
1101 for coin in &rewards.reward {
1102 acc.entry(&coin.denom)
1103 .or_insert_with(|| DecCoin {
1104 denom: coin.denom.clone(),
1105 amount: Decimal256::zero(),
1106 })
1107 .amount += coin.amount;
1108 }
1109
1110 acc
1111 })
1112 .into_values()
1113 .collect(),
1114 rewards: validator_rewards,
1115 };
1116 to_json_binary(&res).into()
1117 }
1118 #[cfg(feature = "cosmwasm_1_4")]
1119 DistributionQuery::DelegatorValidators { delegator_address } => {
1120 let res = DelegatorValidatorsResponse {
1121 validators: self
1122 .validators
1123 .get(delegator_address)
1124 .map(|set| set.iter().cloned().collect())
1125 .unwrap_or_default(),
1126 };
1127 to_json_binary(&res).into()
1128 }
1129 };
1130 SystemResult::Ok(contract_result)
1132 }
1133
1134 #[cfg(feature = "cosmwasm_1_4")]
1136 fn validator_rewards(&self, delegator_address: &str) -> Option<Vec<crate::DelegatorReward>> {
1137 let validator_rewards = self.rewards.get(delegator_address)?;
1138
1139 Some(
1140 validator_rewards
1141 .iter()
1142 .map(|(validator, rewards)| crate::DelegatorReward {
1143 validator_address: validator.clone(),
1144 reward: rewards.clone(),
1145 })
1146 .collect(),
1147 )
1148 }
1149}
1150
1151pub fn digit_sum(input: &[u8]) -> usize {
1152 input.iter().fold(0, |sum, val| sum + (*val as usize))
1153}
1154
1155pub fn mock_wasmd_attr(key: impl Into<String>, value: impl Into<String>) -> Attribute {
1158 Attribute {
1159 key: key.into(),
1160 value: value.into(),
1161 }
1162}
1163
1164#[cfg(test)]
1165mod tests {
1166 use super::*;
1167 #[cfg(feature = "cosmwasm_1_3")]
1168 use crate::DenomUnit;
1169 use crate::{coin, coins, from_json, to_json_binary, ContractInfoResponse, Response};
1170 #[cfg(feature = "staking")]
1171 use crate::{Decimal, Delegation};
1172 use hex_literal::hex;
1173 use serde::Deserialize;
1174
1175 const SECP256K1_MSG_HASH_HEX: &str =
1176 "5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0";
1177 const SECP256K1_SIG_HEX: &str = "207082eb2c3dfa0b454e0906051270ba4074ac93760ba9e7110cd9471475111151eb0dbbc9920e72146fb564f99d039802bf6ef2561446eb126ef364d21ee9c4";
1178 const SECP256K1_PUBKEY_HEX: &str = "04051c1ee2190ecfb174bfe4f90763f2b4ff7517b70a2aec1876ebcfd644c4633fb03f3cfbd94b1f376e34592d9d41ccaf640bb751b00a1fadeb0c01157769eb73";
1179
1180 const ED25519_MSG_HEX: &str = "72";
1181 const ED25519_SIG_HEX: &str = "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00";
1182 const ED25519_PUBKEY_HEX: &str =
1183 "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c";
1184
1185 #[test]
1186 fn mock_info_works() {
1187 let info = mock_info("my name", &coins(100, "atom"));
1188 assert_eq!(
1189 info,
1190 MessageInfo {
1191 sender: Addr::unchecked("my name"),
1192 funds: vec![Coin {
1193 amount: 100u128.into(),
1194 denom: "atom".into(),
1195 }]
1196 }
1197 );
1198 }
1199
1200 #[test]
1201 fn addr_validate_works() {
1202 let api = MockApi::default();
1203
1204 let addr = api.addr_validate("foobar123").unwrap();
1206 assert_eq!(addr, "foobar123");
1207
1208 api.addr_validate("").unwrap_err();
1210 api.addr_validate("Foobar123").unwrap_err();
1212 api.addr_validate("FOOBAR123").unwrap_err();
1213 }
1214
1215 #[test]
1216 fn addr_canonicalize_works() {
1217 let api = MockApi::default();
1218
1219 api.addr_canonicalize("foobar123").unwrap();
1220
1221 let data1 = api.addr_canonicalize("foo123").unwrap();
1223 let data2 = api.addr_canonicalize("FOO123").unwrap();
1224 assert_eq!(data1, data2);
1225 }
1226
1227 #[test]
1228 fn canonicalize_and_humanize_restores_original() {
1229 let api = MockApi::default();
1230
1231 let original = String::from("shorty");
1233 let canonical = api.addr_canonicalize(&original).unwrap();
1234 let recovered = api.addr_humanize(&canonical).unwrap();
1235 assert_eq!(recovered, original);
1236
1237 let original = String::from("CosmWasmChef");
1239 let canonical = api.addr_canonicalize(&original).unwrap();
1240 let recovered = api.addr_humanize(&canonical).unwrap();
1241 assert_eq!(recovered, "cosmwasmchef");
1242
1243 let original =
1245 String::from("juno1v82su97skv6ucfqvuvswe0t5fph7pfsrtraxf0x33d8ylj5qnrysdvkc95");
1246 let canonical = api.addr_canonicalize(&original).unwrap();
1247 let recovered = api.addr_humanize(&canonical).unwrap();
1248 assert_eq!(recovered, original);
1249 }
1250
1251 #[test]
1252 fn addr_canonicalize_min_input_length() {
1253 let api = MockApi::default();
1254 let human = String::from("1");
1255 let err = api.addr_canonicalize(&human).unwrap_err();
1256 assert!(err
1257 .to_string()
1258 .contains("human address too short for this mock implementation (must be >= 3)"));
1259 }
1260
1261 #[test]
1262 fn addr_canonicalize_max_input_length() {
1263 let api = MockApi::default();
1264 let human =
1265 String::from("some-extremely-long-address-not-supported-by-this-api-longer-than-supported------------------------");
1266 let err = api.addr_canonicalize(&human).unwrap_err();
1267 assert!(err
1268 .to_string()
1269 .contains("human address too long for this mock implementation (must be <= 90)"));
1270 }
1271
1272 #[test]
1273 #[should_panic(expected = "length not correct")]
1274 fn addr_humanize_input_length() {
1275 let api = MockApi::default();
1276 let input = CanonicalAddr::from(vec![61; 11]);
1277 api.addr_humanize(&input).unwrap();
1278 }
1279
1280 #[test]
1282 fn secp256k1_verify_works() {
1283 let api = MockApi::default();
1284
1285 let hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
1286 let signature = hex::decode(SECP256K1_SIG_HEX).unwrap();
1287 let public_key = hex::decode(SECP256K1_PUBKEY_HEX).unwrap();
1288
1289 assert!(api
1290 .secp256k1_verify(&hash, &signature, &public_key)
1291 .unwrap());
1292 }
1293
1294 #[test]
1296 fn secp256k1_verify_fails() {
1297 let api = MockApi::default();
1298
1299 let mut hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
1300 hash[0] ^= 0x01;
1302 let signature = hex::decode(SECP256K1_SIG_HEX).unwrap();
1303 let public_key = hex::decode(SECP256K1_PUBKEY_HEX).unwrap();
1304
1305 assert!(!api
1306 .secp256k1_verify(&hash, &signature, &public_key)
1307 .unwrap());
1308 }
1309
1310 #[test]
1312 fn secp256k1_verify_errs() {
1313 let api = MockApi::default();
1314
1315 let hash = hex::decode(SECP256K1_MSG_HASH_HEX).unwrap();
1316 let signature = hex::decode(SECP256K1_SIG_HEX).unwrap();
1317 let public_key = vec![];
1318
1319 let res = api.secp256k1_verify(&hash, &signature, &public_key);
1320 assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
1321 }
1322
1323 #[test]
1324 fn secp256k1_recover_pubkey_works() {
1325 let api = MockApi::default();
1326
1327 let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
1329 let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
1330 let recovery_param = 1;
1331 let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
1332
1333 let pubkey = api
1334 .secp256k1_recover_pubkey(&hash, &signature, recovery_param)
1335 .unwrap();
1336 assert_eq!(pubkey, expected);
1337 }
1338
1339 #[test]
1340 fn secp256k1_recover_pubkey_fails_for_wrong_recovery_param() {
1341 let api = MockApi::default();
1342
1343 let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
1345 let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
1346 let _recovery_param = 1;
1347 let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
1348
1349 let pubkey = api.secp256k1_recover_pubkey(&hash, &signature, 0).unwrap();
1351 assert_eq!(pubkey.len(), 65);
1352 assert_ne!(pubkey, expected);
1353
1354 let result = api.secp256k1_recover_pubkey(&hash, &signature, 42);
1356 match result.unwrap_err() {
1357 RecoverPubkeyError::InvalidRecoveryParam => {}
1358 err => panic!("Unexpected error: {err:?}"),
1359 }
1360 }
1361
1362 #[test]
1363 fn secp256k1_recover_pubkey_fails_for_wrong_hash() {
1364 let api = MockApi::default();
1365
1366 let hash = hex!("5ae8317d34d1e595e3fa7247db80c0af4320cce1116de187f8f7e2e099c0d8d0");
1368 let signature = hex!("45c0b7f8c09a9e1f1cea0c25785594427b6bf8f9f878a8af0b1abbb48e16d0920d8becd0c220f67c51217eecfd7184ef0732481c843857e6bc7fc095c4f6b788");
1369 let recovery_param = 1;
1370 let expected = hex!("044a071e8a6e10aada2b8cf39fa3b5fb3400b04e99ea8ae64ceea1a977dbeaf5d5f8c8fbd10b71ab14cd561f7df8eb6da50f8a8d81ba564342244d26d1d4211595");
1371
1372 let mut corrupted_hash = hash;
1374 corrupted_hash[0] ^= 0x01;
1375 let pubkey = api
1376 .secp256k1_recover_pubkey(&corrupted_hash, &signature, recovery_param)
1377 .unwrap();
1378 assert_eq!(pubkey.len(), 65);
1379 assert_ne!(pubkey, expected);
1380
1381 let mut malformed_hash = hash.to_vec();
1383 malformed_hash.push(0x8a);
1384 let result = api.secp256k1_recover_pubkey(&malformed_hash, &signature, recovery_param);
1385 match result.unwrap_err() {
1386 RecoverPubkeyError::InvalidHashFormat => {}
1387 err => panic!("Unexpected error: {err:?}"),
1388 }
1389 }
1390
1391 #[test]
1393 fn ed25519_verify_works() {
1394 let api = MockApi::default();
1395
1396 let msg = hex::decode(ED25519_MSG_HEX).unwrap();
1397 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
1398 let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
1399
1400 assert!(api.ed25519_verify(&msg, &signature, &public_key).unwrap());
1401 }
1402
1403 #[test]
1405 fn ed25519_verify_fails() {
1406 let api = MockApi::default();
1407
1408 let mut msg = hex::decode(ED25519_MSG_HEX).unwrap();
1409 msg[0] ^= 0x01;
1411 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
1412 let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
1413
1414 assert!(!api.ed25519_verify(&msg, &signature, &public_key).unwrap());
1415 }
1416
1417 #[test]
1419 fn ed25519_verify_errs() {
1420 let api = MockApi::default();
1421
1422 let msg = hex::decode(ED25519_MSG_HEX).unwrap();
1423 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
1424 let public_key = vec![];
1425
1426 let res = api.ed25519_verify(&msg, &signature, &public_key);
1427 assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
1428 }
1429
1430 #[test]
1432 fn ed25519_batch_verify_works() {
1433 let api = MockApi::default();
1434
1435 let msg = hex::decode(ED25519_MSG_HEX).unwrap();
1436 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
1437 let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
1438
1439 let msgs: Vec<&[u8]> = vec![&msg];
1440 let signatures: Vec<&[u8]> = vec![&signature];
1441 let public_keys: Vec<&[u8]> = vec![&public_key];
1442
1443 assert!(api
1444 .ed25519_batch_verify(&msgs, &signatures, &public_keys)
1445 .unwrap());
1446 }
1447
1448 #[test]
1450 fn ed25519_batch_verify_fails() {
1451 let api = MockApi::default();
1452
1453 let mut msg = hex::decode(ED25519_MSG_HEX).unwrap();
1454 msg[0] ^= 0x01;
1456 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
1457 let public_key = hex::decode(ED25519_PUBKEY_HEX).unwrap();
1458
1459 let msgs: Vec<&[u8]> = vec![&msg];
1460 let signatures: Vec<&[u8]> = vec![&signature];
1461 let public_keys: Vec<&[u8]> = vec![&public_key];
1462
1463 assert!(!api
1464 .ed25519_batch_verify(&msgs, &signatures, &public_keys)
1465 .unwrap());
1466 }
1467
1468 #[test]
1470 fn ed25519_batch_verify_errs() {
1471 let api = MockApi::default();
1472
1473 let msg = hex::decode(ED25519_MSG_HEX).unwrap();
1474 let signature = hex::decode(ED25519_SIG_HEX).unwrap();
1475 let public_key: Vec<u8> = vec![0u8; 0];
1476
1477 let msgs: Vec<&[u8]> = vec![msg.as_slice()];
1478 let signatures: Vec<&[u8]> = vec![signature.as_slice()];
1479 let public_keys: Vec<&[u8]> = vec![&public_key];
1480
1481 let res = api.ed25519_batch_verify(&msgs, &signatures, &public_keys);
1482 assert_eq!(res.unwrap_err(), VerificationError::InvalidPubkeyFormat);
1483 }
1484
1485 #[cfg(feature = "cosmwasm_1_1")]
1486 #[test]
1487 fn bank_querier_supply() {
1488 let addr1 = String::from("foo");
1489 let balance1 = vec![coin(123, "ELF"), coin(777, "FLY")];
1490
1491 let addr2 = String::from("bar");
1492 let balance2 = coins(321, "ELF");
1493
1494 let bank = BankQuerier::new(&[(&addr1, &balance1), (&addr2, &balance2)]);
1495
1496 let elf = bank
1497 .query(&BankQuery::Supply {
1498 denom: "ELF".to_string(),
1499 })
1500 .unwrap()
1501 .unwrap();
1502 let res: SupplyResponse = from_json(elf).unwrap();
1503 assert_eq!(res.amount, coin(444, "ELF"));
1504
1505 let fly = bank
1506 .query(&BankQuery::Supply {
1507 denom: "FLY".to_string(),
1508 })
1509 .unwrap()
1510 .unwrap();
1511 let res: SupplyResponse = from_json(fly).unwrap();
1512 assert_eq!(res.amount, coin(777, "FLY"));
1513
1514 let atom = bank
1516 .query(&BankQuery::Supply {
1517 denom: "ATOM".to_string(),
1518 })
1519 .unwrap()
1520 .unwrap();
1521 let res: SupplyResponse = from_json(atom).unwrap();
1522 assert_eq!(res.amount, coin(0, "ATOM"));
1523 }
1524
1525 #[test]
1526 fn bank_querier_all_balances() {
1527 let addr = String::from("foobar");
1528 let balance = vec![coin(123, "ELF"), coin(777, "FLY")];
1529 let bank = BankQuerier::new(&[(&addr, &balance)]);
1530
1531 let all = bank
1532 .query(&BankQuery::AllBalances { address: addr })
1533 .unwrap()
1534 .unwrap();
1535 let res: AllBalanceResponse = from_json(all).unwrap();
1536 assert_eq!(&res.amount, &balance);
1537 }
1538
1539 #[test]
1540 fn bank_querier_one_balance() {
1541 let addr = String::from("foobar");
1542 let balance = vec![coin(123, "ELF"), coin(777, "FLY")];
1543 let bank = BankQuerier::new(&[(&addr, &balance)]);
1544
1545 let fly = bank
1547 .query(&BankQuery::Balance {
1548 address: addr.clone(),
1549 denom: "FLY".to_string(),
1550 })
1551 .unwrap()
1552 .unwrap();
1553 let res: BalanceResponse = from_json(fly).unwrap();
1554 assert_eq!(res.amount, coin(777, "FLY"));
1555
1556 let miss = bank
1558 .query(&BankQuery::Balance {
1559 address: addr,
1560 denom: "MISS".to_string(),
1561 })
1562 .unwrap()
1563 .unwrap();
1564 let res: BalanceResponse = from_json(miss).unwrap();
1565 assert_eq!(res.amount, coin(0, "MISS"));
1566 }
1567
1568 #[test]
1569 fn bank_querier_missing_account() {
1570 let addr = String::from("foobar");
1571 let balance = vec![coin(123, "ELF"), coin(777, "FLY")];
1572 let bank = BankQuerier::new(&[(&addr, &balance)]);
1573
1574 let all = bank
1576 .query(&BankQuery::AllBalances {
1577 address: String::from("elsewhere"),
1578 })
1579 .unwrap()
1580 .unwrap();
1581 let res: AllBalanceResponse = from_json(all).unwrap();
1582 assert_eq!(res.amount, vec![]);
1583
1584 let miss = bank
1586 .query(&BankQuery::Balance {
1587 address: String::from("elsewhere"),
1588 denom: "ELF".to_string(),
1589 })
1590 .unwrap()
1591 .unwrap();
1592 let res: BalanceResponse = from_json(miss).unwrap();
1593 assert_eq!(res.amount, coin(0, "ELF"));
1594 }
1595
1596 #[cfg(feature = "cosmwasm_1_3")]
1597 #[test]
1598 fn bank_querier_metadata_works() {
1599 let mut bank = BankQuerier::new(&[]);
1600 bank.set_denom_metadata(
1601 &(0..100)
1602 .map(|i| DenomMetadata {
1603 symbol: format!("FOO{i}"),
1604 name: "Foo".to_string(),
1605 description: "Foo coin".to_string(),
1606 denom_units: vec![DenomUnit {
1607 denom: "ufoo".to_string(),
1608 exponent: 8,
1609 aliases: vec!["microfoo".to_string(), "foobar".to_string()],
1610 }],
1611 display: "FOO".to_string(),
1612 base: format!("ufoo{i}"),
1613 uri: "https://foo.bar".to_string(),
1614 uri_hash: "foo".to_string(),
1615 })
1616 .collect::<Vec<_>>(),
1617 );
1618
1619 let res = bank
1621 .query(&BankQuery::AllDenomMetadata {
1622 pagination: Some(PageRequest {
1623 key: None,
1624 limit: 10,
1625 reverse: false,
1626 }),
1627 })
1628 .unwrap()
1629 .unwrap();
1630 let res: AllDenomMetadataResponse = from_json(res).unwrap();
1631 assert_eq!(res.metadata.len(), 10);
1632 assert!(res.next_key.is_some());
1633
1634 let res2 = bank
1636 .query(&BankQuery::AllDenomMetadata {
1637 pagination: Some(PageRequest {
1638 key: res.next_key,
1639 limit: 10,
1640 reverse: false,
1641 }),
1642 })
1643 .unwrap()
1644 .unwrap();
1645 let res2: AllDenomMetadataResponse = from_json(res2).unwrap();
1646 assert_eq!(res2.metadata.len(), 10);
1647 assert_ne!(res.metadata.last(), res2.metadata.first());
1648 for m in res.metadata {
1650 assert!(!res2.metadata.contains(&m));
1651 }
1652
1653 let res = bank
1655 .query(&BankQuery::AllDenomMetadata {
1656 pagination: Some(PageRequest {
1657 key: None,
1658 limit: 100,
1659 reverse: true,
1660 }),
1661 })
1662 .unwrap()
1663 .unwrap();
1664 let res: AllDenomMetadataResponse = from_json(res).unwrap();
1665 assert_eq!(res.metadata.len(), 100);
1666 assert!(res.next_key.is_none(), "no more data should be available");
1667 assert_eq!(res.metadata[0].symbol, "FOO99", "should have been reversed");
1668
1669 let more_res = bank
1670 .query(&BankQuery::AllDenomMetadata {
1671 pagination: Some(PageRequest {
1672 key: res.next_key,
1673 limit: u32::MAX,
1674 reverse: true,
1675 }),
1676 })
1677 .unwrap()
1678 .unwrap();
1679 let more_res: AllDenomMetadataResponse = from_json(more_res).unwrap();
1680 assert_eq!(
1681 more_res.metadata, res.metadata,
1682 "should be same as previous query"
1683 );
1684 }
1685
1686 #[cfg(feature = "cosmwasm_1_3")]
1687 #[test]
1688 fn distribution_querier_delegator_withdraw_address() {
1689 let mut distribution = DistributionQuerier::default();
1690 distribution.set_withdraw_address("addr0", "withdraw0");
1691
1692 let query = DistributionQuery::DelegatorWithdrawAddress {
1693 delegator_address: "addr0".to_string(),
1694 };
1695
1696 let res = distribution.query(&query).unwrap().unwrap();
1697 let res: DelegatorWithdrawAddressResponse = from_json(res).unwrap();
1698 assert_eq!(res.withdraw_address, "withdraw0");
1699
1700 let query = DistributionQuery::DelegatorWithdrawAddress {
1701 delegator_address: "addr1".to_string(),
1702 };
1703
1704 let res = distribution.query(&query).unwrap().unwrap();
1705 let res: DelegatorWithdrawAddressResponse = from_json(res).unwrap();
1706 assert_eq!(res.withdraw_address, "addr1");
1707 }
1708
1709 #[cfg(feature = "cosmwasm_1_4")]
1710 #[test]
1711 fn distribution_querier_delegator_validators() {
1712 let mut distribution = DistributionQuerier::default();
1713 distribution.set_validators("addr0", ["valoper1", "valoper2"]);
1714
1715 let query = DistributionQuery::DelegatorValidators {
1716 delegator_address: "addr0".to_string(),
1717 };
1718
1719 let res = distribution.query(&query).unwrap().unwrap();
1720 let res: DelegatorValidatorsResponse = from_json(res).unwrap();
1721 assert_eq!(res.validators, ["valoper1", "valoper2"]);
1722
1723 let query = DistributionQuery::DelegatorValidators {
1724 delegator_address: "addr1".to_string(),
1725 };
1726
1727 let res = distribution.query(&query).unwrap().unwrap();
1728 let res: DelegatorValidatorsResponse = from_json(res).unwrap();
1729 assert_eq!(res.validators, ([] as [String; 0]));
1730 }
1731
1732 #[cfg(feature = "cosmwasm_1_4")]
1733 #[test]
1734 fn distribution_querier_delegation_rewards() {
1735 use crate::{Decimal256, DelegationTotalRewardsResponse, DelegatorReward};
1736
1737 let mut distribution = DistributionQuerier::default();
1738 let valoper0_rewards = vec![
1739 DecCoin::new(Decimal256::from_atomics(1234u128, 0).unwrap(), "uatom"),
1740 DecCoin::new(Decimal256::from_atomics(56781234u128, 4).unwrap(), "utest"),
1741 ];
1742 distribution.set_rewards("valoper0", "addr0", valoper0_rewards.clone());
1743
1744 let query = DistributionQuery::DelegationRewards {
1746 delegator_address: "addr0".to_string(),
1747 validator_address: "valoper0".to_string(),
1748 };
1749 let res = distribution.query(&query).unwrap().unwrap();
1750 let res: DelegationRewardsResponse = from_json(res).unwrap();
1751 assert_eq!(res.rewards, valoper0_rewards);
1752
1753 let query = DistributionQuery::DelegationRewards {
1755 delegator_address: "nonexistent".to_string(),
1756 validator_address: "valoper0".to_string(),
1757 };
1758 let res = distribution.query(&query).unwrap().unwrap();
1759 let res: DelegationRewardsResponse = from_json(res).unwrap();
1760 assert_eq!(res.rewards.len(), 0);
1761
1762 let query = DistributionQuery::DelegationRewards {
1764 delegator_address: "addr0".to_string(),
1765 validator_address: "valopernonexistent".to_string(),
1766 };
1767 let res = distribution.query(&query).unwrap().unwrap();
1768 let res: DelegationRewardsResponse = from_json(res).unwrap();
1769 assert_eq!(res.rewards.len(), 0);
1770
1771 let valoper1_rewards = vec![DecCoin::new(Decimal256::one(), "uatom")];
1773 distribution.set_rewards("valoper1", "addr0", valoper1_rewards.clone());
1774
1775 let query = DistributionQuery::DelegationTotalRewards {
1777 delegator_address: "addr0".to_string(),
1778 };
1779 let res = distribution.query(&query).unwrap().unwrap();
1780 let res: DelegationTotalRewardsResponse = from_json(res).unwrap();
1781 assert_eq!(
1782 res.rewards,
1783 vec![
1784 DelegatorReward {
1785 validator_address: "valoper0".into(),
1786 reward: valoper0_rewards
1787 },
1788 DelegatorReward {
1789 validator_address: "valoper1".into(),
1790 reward: valoper1_rewards
1791 },
1792 ]
1793 );
1794 assert_eq!(
1795 res.total,
1796 [
1797 DecCoin::new(
1798 Decimal256::from_atomics(1234u128, 0).unwrap() + Decimal256::one(),
1799 "uatom"
1800 ),
1801 DecCoin::new(Decimal256::from_atomics(56781234u128, 4).unwrap(), "utest")
1803 ]
1804 );
1805 }
1806
1807 #[cfg(feature = "stargate")]
1808 #[test]
1809 fn ibc_querier_channel_existing() {
1810 let chan1 = mock_ibc_channel("channel-0", IbcOrder::Ordered, "ibc");
1811 let chan2 = mock_ibc_channel("channel-1", IbcOrder::Ordered, "ibc");
1812
1813 let ibc = IbcQuerier::new("myport", &[chan1.clone(), chan2]);
1814
1815 let query = &IbcQuery::Channel {
1817 channel_id: "channel-0".to_string(),
1818 port_id: Some("my_port".to_string()),
1819 };
1820 let raw = ibc.query(query).unwrap().unwrap();
1821 let chan: ChannelResponse = from_json(raw).unwrap();
1822 assert_eq!(chan.channel, Some(chan1));
1823 }
1824
1825 #[cfg(feature = "stargate")]
1826 #[test]
1827 fn ibc_querier_channel_existing_no_port() {
1828 let chan1 = IbcChannel {
1829 endpoint: IbcEndpoint {
1830 port_id: "myport".to_string(),
1831 channel_id: "channel-0".to_string(),
1832 },
1833 counterparty_endpoint: IbcEndpoint {
1834 port_id: "their_port".to_string(),
1835 channel_id: "channel-7".to_string(),
1836 },
1837 order: IbcOrder::Ordered,
1838 version: "ibc".to_string(),
1839 connection_id: "connection-2".to_string(),
1840 };
1841 let chan2 = mock_ibc_channel("channel-1", IbcOrder::Ordered, "ibc");
1842
1843 let ibc = IbcQuerier::new("myport", &[chan1.clone(), chan2]);
1844
1845 let query = &IbcQuery::Channel {
1847 channel_id: "channel-0".to_string(),
1848 port_id: Some("myport".to_string()),
1849 };
1850 let raw = ibc.query(query).unwrap().unwrap();
1851 let chan: ChannelResponse = from_json(raw).unwrap();
1852 assert_eq!(chan.channel, Some(chan1));
1853 }
1854
1855 #[cfg(feature = "stargate")]
1856 #[test]
1857 fn ibc_querier_channel_none() {
1858 let chan1 = mock_ibc_channel("channel-0", IbcOrder::Ordered, "ibc");
1859 let chan2 = mock_ibc_channel("channel-1", IbcOrder::Ordered, "ibc");
1860
1861 let ibc = IbcQuerier::new("myport", &[chan1, chan2]);
1862
1863 let query = &IbcQuery::Channel {
1865 channel_id: "channel-0".to_string(),
1866 port_id: None,
1867 };
1868 let raw = ibc.query(query).unwrap().unwrap();
1869 let chan: ChannelResponse = from_json(raw).unwrap();
1870 assert_eq!(chan.channel, None);
1871 }
1872
1873 #[cfg(feature = "stargate")]
1874 #[test]
1875 fn ibc_querier_channels_matching() {
1876 let chan1 = mock_ibc_channel("channel-0", IbcOrder::Ordered, "ibc");
1877 let chan2 = mock_ibc_channel("channel-1", IbcOrder::Ordered, "ibc");
1878
1879 let ibc = IbcQuerier::new("myport", &[chan1.clone(), chan2.clone()]);
1880
1881 let query = &IbcQuery::ListChannels {
1883 port_id: Some("my_port".to_string()),
1884 };
1885 let raw = ibc.query(query).unwrap().unwrap();
1886 let res: ListChannelsResponse = from_json(raw).unwrap();
1887 assert_eq!(res.channels, vec![chan1, chan2]);
1888 }
1889
1890 #[cfg(feature = "stargate")]
1891 #[test]
1892 fn ibc_querier_channels_no_matching() {
1893 let chan1 = mock_ibc_channel("channel-0", IbcOrder::Ordered, "ibc");
1894 let chan2 = mock_ibc_channel("channel-1", IbcOrder::Ordered, "ibc");
1895
1896 let ibc = IbcQuerier::new("myport", &[chan1, chan2]);
1897
1898 let query = &IbcQuery::ListChannels { port_id: None };
1900 let raw = ibc.query(query).unwrap().unwrap();
1901 let res: ListChannelsResponse = from_json(raw).unwrap();
1902 assert_eq!(res.channels, vec![]);
1903 }
1904
1905 #[cfg(feature = "stargate")]
1906 #[test]
1907 fn ibc_querier_port() {
1908 let chan1 = mock_ibc_channel("channel-0", IbcOrder::Ordered, "ibc");
1909
1910 let ibc = IbcQuerier::new("myport", &[chan1]);
1911
1912 let query = &IbcQuery::PortId {};
1914 let raw = ibc.query(query).unwrap().unwrap();
1915 let res: PortIdResponse = from_json(raw).unwrap();
1916 assert_eq!(res.port_id, "myport");
1917 }
1918
1919 #[cfg(feature = "staking")]
1920 #[test]
1921 fn staking_querier_all_validators() {
1922 let val1 = Validator {
1923 address: String::from("validator-one"),
1924 commission: Decimal::percent(1),
1925 max_commission: Decimal::percent(3),
1926 max_change_rate: Decimal::percent(1),
1927 };
1928 let val2 = Validator {
1929 address: String::from("validator-two"),
1930 commission: Decimal::permille(15),
1931 max_commission: Decimal::permille(40),
1932 max_change_rate: Decimal::permille(5),
1933 };
1934
1935 let staking = StakingQuerier::new("ustake", &[val1.clone(), val2.clone()], &[]);
1936
1937 let raw = staking
1939 .query(&StakingQuery::AllValidators {})
1940 .unwrap()
1941 .unwrap();
1942 let vals: AllValidatorsResponse = from_json(raw).unwrap();
1943 assert_eq!(vals.validators, vec![val1, val2]);
1944 }
1945
1946 #[cfg(feature = "staking")]
1947 #[test]
1948 fn staking_querier_validator() {
1949 let address1 = String::from("validator-one");
1950 let address2 = String::from("validator-two");
1951 let address_non_existent = String::from("wannabe-validator");
1952
1953 let val1 = Validator {
1954 address: address1.clone(),
1955 commission: Decimal::percent(1),
1956 max_commission: Decimal::percent(3),
1957 max_change_rate: Decimal::percent(1),
1958 };
1959 let val2 = Validator {
1960 address: address2.clone(),
1961 commission: Decimal::permille(15),
1962 max_commission: Decimal::permille(40),
1963 max_change_rate: Decimal::permille(5),
1964 };
1965
1966 let staking = StakingQuerier::new("ustake", &[val1.clone(), val2.clone()], &[]);
1967
1968 let raw = staking
1970 .query(&StakingQuery::Validator { address: address1 })
1971 .unwrap()
1972 .unwrap();
1973 let res: ValidatorResponse = from_json(raw).unwrap();
1974 assert_eq!(res.validator, Some(val1));
1975
1976 let raw = staking
1978 .query(&StakingQuery::Validator { address: address2 })
1979 .unwrap()
1980 .unwrap();
1981 let res: ValidatorResponse = from_json(raw).unwrap();
1982 assert_eq!(res.validator, Some(val2));
1983
1984 let raw = staking
1986 .query(&StakingQuery::Validator {
1987 address: address_non_existent,
1988 })
1989 .unwrap()
1990 .unwrap();
1991 let res: ValidatorResponse = from_json(raw).unwrap();
1992 assert_eq!(res.validator, None);
1993 }
1994
1995 #[cfg(feature = "staking")]
1996 fn get_all_delegators(
1998 staking: &StakingQuerier,
1999 delegator: impl Into<String>,
2000 ) -> Vec<Delegation> {
2001 let raw = staking
2002 .query(&StakingQuery::AllDelegations {
2003 delegator: delegator.into(),
2004 })
2005 .unwrap()
2006 .unwrap();
2007 let dels: AllDelegationsResponse = from_json(raw).unwrap();
2008 dels.delegations
2009 }
2010
2011 #[cfg(feature = "staking")]
2012 fn get_delegator(
2014 staking: &StakingQuerier,
2015 delegator: impl Into<String>,
2016 validator: impl Into<String>,
2017 ) -> Option<FullDelegation> {
2018 let raw = staking
2019 .query(&StakingQuery::Delegation {
2020 delegator: delegator.into(),
2021 validator: validator.into(),
2022 })
2023 .unwrap()
2024 .unwrap();
2025 let dels: DelegationResponse = from_json(raw).unwrap();
2026 dels.delegation
2027 }
2028
2029 #[cfg(feature = "staking")]
2030 #[test]
2031 fn staking_querier_delegations() {
2032 let val1 = String::from("validator-one");
2033 let val2 = String::from("validator-two");
2034
2035 let user_a = Addr::unchecked("investor");
2036 let user_b = Addr::unchecked("speculator");
2037 let user_c = Addr::unchecked("hodler");
2038
2039 let del1a = FullDelegation {
2041 delegator: user_a.clone(),
2042 validator: val1.clone(),
2043 amount: coin(100, "ustake"),
2044 can_redelegate: coin(100, "ustake"),
2045 accumulated_rewards: coins(5, "ustake"),
2046 };
2047 let del2a = FullDelegation {
2048 delegator: user_a.clone(),
2049 validator: val2.clone(),
2050 amount: coin(500, "ustake"),
2051 can_redelegate: coin(500, "ustake"),
2052 accumulated_rewards: coins(20, "ustake"),
2053 };
2054
2055 let del1b = FullDelegation {
2057 delegator: user_b.clone(),
2058 validator: val1.clone(),
2059 amount: coin(500, "ustake"),
2060 can_redelegate: coin(0, "ustake"),
2061 accumulated_rewards: coins(0, "ustake"),
2062 };
2063
2064 let del2c = FullDelegation {
2066 delegator: user_c.clone(),
2067 validator: val2.clone(),
2068 amount: coin(8888, "ustake"),
2069 can_redelegate: coin(4567, "ustake"),
2070 accumulated_rewards: coins(900, "ustake"),
2071 };
2072
2073 let staking = StakingQuerier::new(
2074 "ustake",
2075 &[],
2076 &[del1a.clone(), del1b.clone(), del2a.clone(), del2c.clone()],
2077 );
2078
2079 let dels = get_all_delegators(&staking, user_a.clone());
2081 assert_eq!(dels, vec![del1a.clone().into(), del2a.clone().into()]);
2082
2083 let dels = get_all_delegators(&staking, user_b.clone());
2085 assert_eq!(dels, vec![del1b.clone().into()]);
2086
2087 let dels = get_all_delegators(&staking, user_c.clone());
2089 assert_eq!(dels, vec![del2c.clone().into()]);
2090
2091 let dels = get_all_delegators(&staking, String::from("no one"));
2093 assert_eq!(dels, vec![]);
2094
2095 let dels = get_delegator(&staking, user_a.clone(), val1.clone());
2097 assert_eq!(dels, Some(del1a));
2098 let dels = get_delegator(&staking, user_a, val2.clone());
2099 assert_eq!(dels, Some(del2a));
2100
2101 let dels = get_delegator(&staking, user_b.clone(), val1.clone());
2103 assert_eq!(dels, Some(del1b));
2104 let dels = get_delegator(&staking, user_b, val2.clone());
2105 assert_eq!(dels, None);
2106
2107 let dels = get_delegator(&staking, user_c.clone(), val1);
2109 assert_eq!(dels, None);
2110 let dels = get_delegator(&staking, user_c, val2);
2111 assert_eq!(dels, Some(del2c));
2112 }
2113
2114 #[test]
2115 fn wasm_querier_works() {
2116 let mut querier = WasmQuerier::default();
2117
2118 let any_addr = "foo".to_string();
2119
2120 let system_err = querier
2122 .query(&WasmQuery::Raw {
2123 contract_addr: any_addr.clone(),
2124 key: b"the key".into(),
2125 })
2126 .unwrap_err();
2127 match system_err {
2128 SystemError::NoSuchContract { addr } => assert_eq!(addr, any_addr),
2129 err => panic!("Unexpected error: {err:?}"),
2130 }
2131
2132 let system_err = querier
2134 .query(&WasmQuery::Smart {
2135 contract_addr: any_addr.clone(),
2136 msg: b"{}".into(),
2137 })
2138 .unwrap_err();
2139 match system_err {
2140 SystemError::NoSuchContract { addr } => assert_eq!(addr, any_addr),
2141 err => panic!("Unexpected error: {err:?}"),
2142 }
2143
2144 let system_err = querier
2146 .query(&WasmQuery::ContractInfo {
2147 contract_addr: any_addr.clone(),
2148 })
2149 .unwrap_err();
2150 match system_err {
2151 SystemError::NoSuchContract { addr } => assert_eq!(addr, any_addr),
2152 err => panic!("Unexpected error: {err:?}"),
2153 }
2154
2155 #[cfg(feature = "cosmwasm_1_2")]
2156 {
2157 let system_err = querier
2159 .query(&WasmQuery::CodeInfo { code_id: 4 })
2160 .unwrap_err();
2161 match system_err {
2162 SystemError::NoSuchCode { code_id } => assert_eq!(code_id, 4),
2163 err => panic!("Unexpected error: {err:?}"),
2164 }
2165 }
2166
2167 querier.update_handler(|request| {
2168 let constract1 = Addr::unchecked("contract1");
2169 let mut storage1 = HashMap::<Binary, Binary>::default();
2170 storage1.insert(b"the key".into(), b"the value".into());
2171
2172 match request {
2173 WasmQuery::Raw { contract_addr, key } => {
2174 if *contract_addr == constract1 {
2175 if let Some(value) = storage1.get(key) {
2176 SystemResult::Ok(ContractResult::Ok(value.clone()))
2177 } else {
2178 SystemResult::Ok(ContractResult::Ok(Binary::default()))
2179 }
2180 } else {
2181 SystemResult::Err(SystemError::NoSuchContract {
2182 addr: contract_addr.clone(),
2183 })
2184 }
2185 }
2186 WasmQuery::Smart { contract_addr, msg } => {
2187 if *contract_addr == constract1 {
2188 #[derive(Deserialize)]
2189 struct MyMsg {}
2190 let _msg: MyMsg = match from_json(msg) {
2191 Ok(msg) => msg,
2192 Err(err) => {
2193 return SystemResult::Ok(ContractResult::Err(err.to_string()))
2194 }
2195 };
2196 let response: Response = Response::new().set_data(b"good");
2197 SystemResult::Ok(ContractResult::Ok(to_json_binary(&response).unwrap()))
2198 } else {
2199 SystemResult::Err(SystemError::NoSuchContract {
2200 addr: contract_addr.clone(),
2201 })
2202 }
2203 }
2204 WasmQuery::ContractInfo { contract_addr } => {
2205 if *contract_addr == constract1 {
2206 let response = ContractInfoResponse {
2207 code_id: 4,
2208 creator: "lalala".into(),
2209 admin: None,
2210 pinned: false,
2211 ibc_port: None,
2212 };
2213 SystemResult::Ok(ContractResult::Ok(to_json_binary(&response).unwrap()))
2214 } else {
2215 SystemResult::Err(SystemError::NoSuchContract {
2216 addr: contract_addr.clone(),
2217 })
2218 }
2219 }
2220 #[cfg(feature = "cosmwasm_1_2")]
2221 WasmQuery::CodeInfo { code_id } => {
2222 use crate::{CodeInfoResponse, HexBinary};
2223 let code_id = *code_id;
2224 if code_id == 4 {
2225 let response = CodeInfoResponse {
2226 code_id,
2227 creator: "lalala".into(),
2228 checksum: HexBinary::from_hex(
2229 "84cf20810fd429caf58898c3210fcb71759a27becddae08dbde8668ea2f4725d",
2230 )
2231 .unwrap(),
2232 };
2233 SystemResult::Ok(ContractResult::Ok(to_json_binary(&response).unwrap()))
2234 } else {
2235 SystemResult::Err(SystemError::NoSuchCode { code_id })
2236 }
2237 }
2238 }
2239 });
2240
2241 let result = querier.query(&WasmQuery::Raw {
2243 contract_addr: "contract1".into(),
2244 key: b"the key".into(),
2245 });
2246 match result {
2247 SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(value, b"the value" as &[u8]),
2248 res => panic!("Unexpected result: {res:?}"),
2249 }
2250 let result = querier.query(&WasmQuery::Raw {
2251 contract_addr: "contract1".into(),
2252 key: b"other key".into(),
2253 });
2254 match result {
2255 SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(value, b"" as &[u8]),
2256 res => panic!("Unexpected result: {res:?}"),
2257 }
2258
2259 let result = querier.query(&WasmQuery::Smart {
2261 contract_addr: "contract1".into(),
2262 msg: b"{}".into(),
2263 });
2264 match result {
2265 SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(
2266 value,
2267 br#"{"messages":[],"attributes":[],"events":[],"data":"Z29vZA=="}"# as &[u8]
2268 ),
2269 res => panic!("Unexpected result: {res:?}"),
2270 }
2271 let result = querier.query(&WasmQuery::Smart {
2272 contract_addr: "contract1".into(),
2273 msg: b"a broken request".into(),
2274 });
2275 match result {
2276 SystemResult::Ok(ContractResult::Err(err)) => {
2277 assert_eq!(err, "Error parsing into type cosmwasm_std::testing::mock::tests::wasm_querier_works::{{closure}}::MyMsg: Invalid type")
2278 }
2279 res => panic!("Unexpected result: {res:?}"),
2280 }
2281
2282 let result = querier.query(&WasmQuery::ContractInfo {
2284 contract_addr: "contract1".into(),
2285 });
2286 match result {
2287 SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(
2288 value,
2289 br#"{"code_id":4,"creator":"lalala","admin":null,"pinned":false,"ibc_port":null}"#
2290 as &[u8]
2291 ),
2292 res => panic!("Unexpected result: {res:?}"),
2293 }
2294
2295 #[cfg(feature = "cosmwasm_1_2")]
2297 {
2298 let result = querier.query(&WasmQuery::CodeInfo { code_id: 4 });
2299 match result {
2300 SystemResult::Ok(ContractResult::Ok(value)) => assert_eq!(
2301 value,
2302 br#"{"code_id":4,"creator":"lalala","checksum":"84cf20810fd429caf58898c3210fcb71759a27becddae08dbde8668ea2f4725d"}"#
2303 ),
2304 res => panic!("Unexpected result: {res:?}"),
2305 }
2306 }
2307 }
2308
2309 #[test]
2310 fn digit_sum_works() {
2311 assert_eq!(digit_sum(&[]), 0);
2312 assert_eq!(digit_sum(&[0]), 0);
2313 assert_eq!(digit_sum(&[0, 0]), 0);
2314 assert_eq!(digit_sum(&[0, 0, 0]), 0);
2315
2316 assert_eq!(digit_sum(&[1, 0, 0]), 1);
2317 assert_eq!(digit_sum(&[0, 1, 0]), 1);
2318 assert_eq!(digit_sum(&[0, 0, 1]), 1);
2319
2320 assert_eq!(digit_sum(&[1, 2, 3]), 6);
2321
2322 assert_eq!(digit_sum(&[255, 1]), 256);
2323 }
2324
2325 #[test]
2326 fn making_an_address_works() {
2327 let mock_api = MockApi::default();
2328
2329 assert_eq!(
2330 mock_api.addr_make("creator").to_string(),
2331 "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp",
2332 );
2333
2334 assert_eq!(
2335 mock_api.addr_make("").to_string(),
2336 "cosmwasm1uwcvgs5clswpfxhm7nyfjmaeysn6us0yvjdexn9yjkv3k7zjhp2sly4xh9",
2337 );
2338
2339 let mock_api = MockApi::default().with_prefix("juno");
2340 assert_eq!(
2341 mock_api.addr_make("creator").to_string(),
2342 "juno1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqsksmtyp",
2343 );
2344 }
2345
2346 #[test]
2347 #[should_panic(expected = "Generating address failed with reason: invalid length")]
2348 fn making_an_address_with_empty_prefix_should_panic() {
2349 MockApi::default().with_prefix("").addr_make("creator");
2350 }
2351}