fadroma 0.8.8

Tools and frequently used functionality for developing CosmWasm smart contracts
Documentation
use super::ensemble::Context;
use crate::cosmwasm_std::{
    Querier, QueryRequest, WasmQuery, BankQuery, QuerierResult, SystemResult,
    SystemError, ContractResult, Empty, AllBalanceResponse, BalanceResponse,
    from_slice, to_binary, testing::MockQuerier
};
#[cfg(feature = "ensemble-staking")]
use crate::cosmwasm_std::{
    ValidatorResponse, AllValidatorsResponse, AllDelegationsResponse,
    BondedDenomResponse, StakingQuery
};

pub struct EnsembleQuerier {
    ctx: *const Context,
    base: MockQuerier
}

impl EnsembleQuerier {
    pub(crate) fn new(ctx: &Context) -> Self {
        Self {
            ctx,
            base: MockQuerier::new(&[])
        }
    }
}

macro_rules! querier_result {
    ($x:expr) => {
        {
            let result = match $x {
                Ok(bin) => ContractResult::Ok(bin),
                Err(err) => ContractResult::Err(err.to_string())
            };
        
            SystemResult::Ok(result)
        }
    };
}

impl Querier for EnsembleQuerier {
    fn raw_query(&self, bin_request: &[u8]) -> QuerierResult {
        let request: QueryRequest<Empty> = match from_slice(bin_request) {
            Ok(v) => v,
            Err(e) => {
                return SystemResult::Err(SystemError::InvalidRequest {
                    error: format!("Parsing query request: {}", e),
                    request: bin_request.into(),
                })
            }
        };

        let ctx = unsafe { &*(self.ctx) };

        match request {
            QueryRequest::Wasm(query) => match query {
                WasmQuery::Smart {
                    contract_addr, msg, ..
                } => {
                    if ctx.state.instance(&contract_addr).is_err() {
                        return SystemResult::Err(SystemError::NoSuchContract {
                            addr: contract_addr
                        });
                    }

                    querier_result!(ctx.query(&contract_addr, msg))
                }
                WasmQuery::Raw { contract_addr, .. } => {
                    if cfg!(feature = "scrt") {
                        panic!("Raw queries are unsupported in Secret Network - keys and values in raw storage are encrypted and must be queried through a smart query.");
                    } else {
                        if ctx.state.instance(&contract_addr).is_err() {
                            return SystemResult::Err(SystemError::NoSuchContract {
                                addr: contract_addr
                            });
                        }
    
                        todo!()
                    }
                }
                _ => unimplemented!(),
            },
            QueryRequest::Bank(query) => match query {
                BankQuery::AllBalances { address } => {
                    let amount = ctx.state.bank.query_balances(&address, None);

                    querier_result!(to_binary(&AllBalanceResponse { amount }))
                }
                BankQuery::Balance { address, denom } => {
                    let amount = ctx.state.bank.query_balances(&address, Some(denom));

                    querier_result!(to_binary(&BalanceResponse {
                        amount: amount.into_iter().next().unwrap()
                    }))
                }
                _ => unimplemented!(),
            },
            #[cfg(feature = "ensemble-staking")]
            QueryRequest::Staking(query) => match query {
                StakingQuery::AllDelegations { delegator } => {
                    let delegations = ctx.delegations.all_delegations(&delegator);

                    querier_result!(to_binary(&AllDelegationsResponse { delegations }))
                }
                StakingQuery::BondedDenom {} => {
                    let denom = ctx.delegations.bonded_denom();

                    querier_result!(to_binary(&BondedDenomResponse {
                        denom: denom.to_string(),
                    }))
                }
                StakingQuery::Delegation {
                    delegator,
                    validator
                } => {
                    let delegation = ctx.delegations.delegation(&delegator, &validator);

                    querier_result!(to_binary(&delegation))
                }
                StakingQuery::AllValidators {} => {
                    let validators = ctx.delegations.validators();

                    querier_result!(to_binary(&AllValidatorsResponse {
                        validators: validators.to_vec(),
                    }))
                }
                StakingQuery::Validator { address } => {
                    let validator = ctx
                        .delegations
                        .validators()
                        .iter()
                        .filter(|validator| validator.address == address)
                        .next()
                        .cloned();

                    querier_result!(to_binary(&ValidatorResponse { validator }))
                }
                _ => unimplemented!(),
            },
            _ => self.base.handle_query(&request)
        }
    }
}