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
use crate::wasm_emulation::query::gas::{
    GAS_COST_ALL_DELEGATIONS, GAS_COST_ALL_VALIDATORS, GAS_COST_BONDED_DENOM, GAS_COST_DELEGATIONS,
    GAS_COST_VALIDATOR,
};
use crate::wasm_emulation::query::mock_querier::QueryResultWithGas;
use cosmwasm_std::Binary;
use cosmwasm_vm::GasInfo;

use cosmwasm_std::to_json_binary;
use cosmwasm_std::{
    AllDelegationsResponse, AllValidatorsResponse, BondedDenomResponse, DelegationResponse,
    FullDelegation, StakingQuery, Validator, ValidatorResponse,
};
use cosmwasm_std::{ContractResult, SystemResult};

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct StakingQuerier {
    denom: String,
    validators: Vec<Validator>,
    delegations: Vec<FullDelegation>,
}

impl StakingQuerier {
    pub fn new(denom: &str, validators: &[Validator], delegations: &[FullDelegation]) -> Self {
        StakingQuerier {
            denom: denom.to_string(),
            validators: validators.to_vec(),
            delegations: delegations.to_vec(),
        }
    }

    pub fn query(&self, request: &StakingQuery) -> QueryResultWithGas {
        let contract_result: ContractResult<Binary> = match request {
            StakingQuery::BondedDenom {} => {
                let res = BondedDenomResponse::new(self.denom.clone());
                to_json_binary(&res).into()
            }
            StakingQuery::AllValidators {} => {
                let res = AllValidatorsResponse::new(self.validators.clone());
                to_json_binary(&res).into()
            }
            StakingQuery::Validator { address } => {
                let validator: Option<Validator> = self
                    .validators
                    .iter()
                    .find(|validator| validator.address == *address)
                    .cloned();
                let res = ValidatorResponse::new(validator);
                to_json_binary(&res).into()
            }
            StakingQuery::AllDelegations { delegator } => {
                let delegations: Vec<_> = self
                    .delegations
                    .iter()
                    .filter(|d| d.delegator.as_str() == delegator)
                    .cloned()
                    .map(|d| d.into())
                    .collect();
                let res = AllDelegationsResponse::new(delegations);
                to_json_binary(&res).into()
            }
            StakingQuery::Delegation {
                delegator,
                validator,
            } => {
                let delegation = self
                    .delegations
                    .iter()
                    .find(|d| d.delegator.as_str() == delegator && d.validator == *validator);
                let res = DelegationResponse::new(delegation.cloned());
                to_json_binary(&res).into()
            }
            &_ => panic!("Not implemented {:?}", request),
        };

        // We handle the gas_info
        let gas_info = match request {
            StakingQuery::BondedDenom { .. } => GAS_COST_BONDED_DENOM,
            StakingQuery::AllValidators { .. } => GAS_COST_ALL_VALIDATORS,
            StakingQuery::Validator { .. } => GAS_COST_VALIDATOR,
            StakingQuery::AllDelegations { .. } => GAS_COST_ALL_DELEGATIONS,
            StakingQuery::Delegation { .. } => GAS_COST_DELEGATIONS,
            &_ => panic!("Not implemented {:?}", request),
        };

        // system result is always ok in the mock implementation
        (
            SystemResult::Ok(contract_result),
            GasInfo::with_externally_used(gas_info),
        )
    }
}