use serde::{de::DeserializeOwned, Serialize};
use crate::addresses::{CanonicalAddr, HumanAddr};
use crate::coins::Coin;
use crate::encoding::Binary;
use crate::errors::{StdError, StdResult, SystemResult};
#[cfg(feature = "iterator")]
use crate::iterator::{Order, KV};
use crate::query::{AllBalanceResponse, BalanceResponse, BankQuery, QueryRequest};
#[cfg(feature = "staking")]
use crate::query::{
AllDelegationsResponse, BondedDenomResponse, Delegation, DelegationResponse, FullDelegation,
StakingQuery, Validator, ValidatorsResponse,
};
use crate::serde::{from_binary, to_vec};
use crate::types::Empty;
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> {
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),
}
}
}
pub trait ReadonlyStorage {
fn get(&self, key: &[u8]) -> Option<Vec<u8>>;
#[cfg(feature = "iterator")]
fn range<'a>(
&'a self,
start: Option<&[u8]>,
end: Option<&[u8]>,
order: Order,
) -> Box<dyn Iterator<Item = KV> + 'a>;
}
pub trait Storage: ReadonlyStorage {
fn set(&mut self, key: &[u8], value: &[u8]);
fn remove(&mut self, key: &[u8]);
}
pub trait Api: Copy + Clone + Send {
fn canonical_address(&self, human: &HumanAddr) -> StdResult<CanonicalAddr>;
fn human_address(&self, canonical: &CanonicalAddr) -> StdResult<HumanAddr>;
}
pub type QuerierResult = SystemResult<StdResult<Binary>>;
pub trait Querier {
fn raw_query(&self, bin_request: &[u8]) -> QuerierResult;
fn query<T: DeserializeOwned>(&self, request: &QueryRequest<Empty>) -> StdResult<T> {
self.custom_query(request)
}
fn custom_query<T: Serialize, U: DeserializeOwned>(
&self,
request: &QueryRequest<T>,
) -> StdResult<U> {
let raw = match to_vec(request) {
Ok(raw) => raw,
Err(e) => {
return Err(StdError::generic_err(format!(
"Serializing QueryRequest: {}",
e
)))
}
};
match self.raw_query(&raw) {
Err(sys) => Err(StdError::generic_err(format!(
"Querier system error: {}",
sys
))),
Ok(Err(err)) => Err(err),
Ok(Ok(res)) => from_binary(&res),
}
}
fn query_balance<U: Into<HumanAddr>>(&self, address: U, denom: &str) -> StdResult<Coin> {
let request = BankQuery::Balance {
address: address.into(),
denom: denom.to_string(),
}
.into();
let res: BalanceResponse = self.query(&request)?;
Ok(res.amount)
}
fn query_all_balances<U: Into<HumanAddr>>(&self, address: U) -> StdResult<Vec<Coin>> {
let request = BankQuery::AllBalances {
address: address.into(),
}
.into();
let res: AllBalanceResponse = self.query(&request)?;
Ok(res.amount)
}
#[cfg(feature = "staking")]
fn query_validators(&self) -> StdResult<Vec<Validator>> {
let request = StakingQuery::Validators {}.into();
let res: ValidatorsResponse = self.query(&request)?;
Ok(res.validators)
}
#[cfg(feature = "staking")]
fn query_bonded_denom(&self) -> StdResult<String> {
let request = StakingQuery::BondedDenom {}.into();
let res: BondedDenomResponse = self.query(&request)?;
Ok(res.denom)
}
#[cfg(feature = "staking")]
fn query_all_delegations<U: Into<HumanAddr>>(
&self,
delegator: U,
) -> StdResult<Vec<Delegation>> {
let request = StakingQuery::AllDelegations {
delegator: delegator.into(),
}
.into();
let res: AllDelegationsResponse = self.query(&request)?;
Ok(res.delegations)
}
#[cfg(feature = "staking")]
fn query_delegation<U: Into<HumanAddr>>(
&self,
delegator: U,
validator: U,
) -> StdResult<Option<FullDelegation>> {
let request = StakingQuery::Delegation {
delegator: delegator.into(),
validator: validator.into(),
}
.into();
let res: DelegationResponse = self.query(&request)?;
Ok(res.delegation)
}
}