use std::fmt::Display;
use crate::{cosmos_modules, error::DaemonError, Daemon};
use cosmrs::proto::cosmos::base::query::v1beta1::PageRequest;
use cosmwasm_std::{Addr, StdError};
use cw_orch_core::environment::{Querier, QuerierGetter};
use tokio::runtime::Handle;
use tonic::transport::Channel;
use super::bank::cosmrs_to_cosmwasm_coin;
pub struct Staking {
pub channel: Channel,
pub rt_handle: Option<Handle>,
}
impl Staking {
pub fn new(daemon: &Daemon) -> Self {
Self {
channel: daemon.channel(),
rt_handle: Some(daemon.rt_handle.clone()),
}
}
pub fn new_async(channel: Channel) -> Self {
Self {
channel,
rt_handle: None,
}
}
}
impl Querier for Staking {
type Error = DaemonError;
}
impl QuerierGetter<Staking> for Daemon {
fn querier(&self) -> Staking {
Staking::new(self)
}
}
impl Staking {
pub async fn _validator(
&self,
validator_addr: impl Into<String>,
) -> Result<cosmwasm_std::Validator, DaemonError> {
let validator_response: cosmos_modules::staking::QueryValidatorResponse = cosmos_query!(
self,
staking,
validator,
QueryValidatorRequest {
validator_addr: validator_addr.into()
}
);
Ok(cosmrs_to_cosmwasm_validator(
validator_response.validator.unwrap(),
)?)
}
pub async fn _validators(
&self,
status: StakingBondStatus,
) -> Result<Vec<cosmwasm_std::Validator>, DaemonError> {
let validators: cosmos_modules::staking::QueryValidatorsResponse = cosmos_query!(
self,
staking,
validators,
QueryValidatorsRequest {
status: status.to_string(),
pagination: None,
}
);
Ok(validators
.validators
.into_iter()
.map(cosmrs_to_cosmwasm_validator)
.collect::<Result<_, _>>()?)
}
pub async fn _delegations(
&self,
validator_addr: impl Into<String>,
pagination: Option<PageRequest>,
) -> Result<Vec<cosmwasm_std::Delegation>, DaemonError> {
let validator_delegations: cosmos_modules::staking::QueryValidatorDelegationsResponse = cosmos_query!(
self,
staking,
validator_delegations,
QueryValidatorDelegationsRequest {
validator_addr: validator_addr.into(),
pagination: pagination
}
);
Ok(validator_delegations
.delegation_responses
.into_iter()
.map(cosmrs_to_cosmwasm_delegation)
.collect::<Result<_, _>>()?)
}
pub async fn _unbonding_delegations(
&self,
validator_addr: impl Into<String>,
) -> Result<Vec<cosmos_modules::staking::UnbondingDelegation>, DaemonError> {
let validator_unbonding_delegations: cosmos_modules::staking::QueryValidatorUnbondingDelegationsResponse = cosmos_query!(
self,
staking,
validator_unbonding_delegations,
QueryValidatorUnbondingDelegationsRequest {
validator_addr: validator_addr.into(),
pagination: None
}
);
Ok(validator_unbonding_delegations.unbonding_responses)
}
pub async fn _delegation(
&self,
validator_addr: impl Into<String>,
delegator_addr: impl Into<String>,
) -> Result<cosmwasm_std::Delegation, DaemonError> {
let delegation: cosmos_modules::staking::QueryDelegationResponse = cosmos_query!(
self,
staking,
delegation,
QueryDelegationRequest {
validator_addr: validator_addr.into(),
delegator_addr: delegator_addr.into()
}
);
Ok(cosmrs_to_cosmwasm_delegation(
delegation.delegation_response.unwrap(),
)?)
}
pub async fn _unbonding_delegation(
&self,
validator_addr: impl Into<String>,
delegator_addr: impl Into<String>,
) -> Result<cosmos_modules::staking::UnbondingDelegation, DaemonError> {
let unbonding_delegation: cosmos_modules::staking::QueryUnbondingDelegationResponse = cosmos_query!(
self,
staking,
unbonding_delegation,
QueryUnbondingDelegationRequest {
validator_addr: validator_addr.into(),
delegator_addr: delegator_addr.into()
}
);
Ok(unbonding_delegation.unbond.unwrap())
}
pub async fn _delegator_delegations(
&self,
delegator_addr: impl Into<String>,
pagination: Option<PageRequest>,
) -> Result<cosmos_modules::staking::QueryDelegatorDelegationsResponse, DaemonError> {
let delegator_delegations: cosmos_modules::staking::QueryDelegatorDelegationsResponse = cosmos_query!(
self,
staking,
delegator_delegations,
QueryDelegatorDelegationsRequest {
delegator_addr: delegator_addr.into(),
pagination: pagination
}
);
Ok(delegator_delegations)
}
pub async fn _delegator_unbonding_delegations(
&self,
delegator_addr: impl Into<String>,
pagination: Option<PageRequest>,
) -> Result<cosmos_modules::staking::QueryDelegatorUnbondingDelegationsResponse, DaemonError>
{
let delegator_unbonding_delegations: cosmos_modules::staking::QueryDelegatorUnbondingDelegationsResponse = cosmos_query!(
self,
staking,
delegator_unbonding_delegations,
QueryDelegatorUnbondingDelegationsRequest {
delegator_addr: delegator_addr.into(),
pagination: pagination
}
);
Ok(delegator_unbonding_delegations)
}
pub async fn _redelegations(
&self,
delegator_addr: impl Into<String>,
src_validator_addr: impl Into<String>,
dst_validator_addr: impl Into<String>,
pagination: Option<PageRequest>,
) -> Result<cosmos_modules::staking::QueryRedelegationsResponse, DaemonError> {
let redelegations: cosmos_modules::staking::QueryRedelegationsResponse = cosmos_query!(
self,
staking,
redelegations,
QueryRedelegationsRequest {
delegator_addr: delegator_addr.into(),
src_validator_addr: src_validator_addr.into(),
dst_validator_addr: dst_validator_addr.into(),
pagination: pagination
}
);
Ok(redelegations)
}
pub async fn _delegator_validator(
&self,
validator_addr: impl Into<String>,
delegator_addr: impl Into<String>,
) -> Result<cosmos_modules::staking::QueryDelegatorValidatorResponse, DaemonError> {
let delegator_validator: cosmos_modules::staking::QueryDelegatorValidatorResponse = cosmos_query!(
self,
staking,
delegator_validator,
QueryDelegatorValidatorRequest {
validator_addr: validator_addr.into(),
delegator_addr: delegator_addr.into(),
}
);
Ok(delegator_validator)
}
pub async fn _delegator_validators(
&self,
delegator_addr: impl Into<String>,
pagination: Option<PageRequest>,
) -> Result<cosmos_modules::staking::QueryDelegatorValidatorsResponse, DaemonError> {
let delegator_validators: cosmos_modules::staking::QueryDelegatorValidatorsResponse = cosmos_query!(
self,
staking,
delegator_validators,
QueryDelegatorValidatorsRequest {
delegator_addr: delegator_addr.into(),
pagination: pagination
}
);
Ok(delegator_validators)
}
pub async fn _historical_info(
&self,
height: i64,
) -> Result<cosmos_modules::staking::QueryHistoricalInfoResponse, DaemonError> {
let historical_info: cosmos_modules::staking::QueryHistoricalInfoResponse = cosmos_query!(
self,
staking,
historical_info,
QueryHistoricalInfoRequest { height: height }
);
Ok(historical_info)
}
pub async fn _pool(&self) -> Result<cosmos_modules::staking::QueryPoolResponse, DaemonError> {
let pool: cosmos_modules::staking::QueryPoolResponse =
cosmos_query!(self, staking, pool, QueryPoolRequest {});
Ok(pool)
}
pub async fn _params(
&self,
) -> Result<cosmos_modules::staking::QueryParamsResponse, DaemonError> {
let params: cosmos_modules::staking::QueryParamsResponse =
cosmos_query!(self, staking, params, QueryParamsRequest {});
Ok(params)
}
}
pub enum StakingBondStatus {
Unspecified = 0,
Unbonded = 1,
Unbonding = 2,
Bonded = 3,
}
impl Display for StakingBondStatus {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let str = match self {
StakingBondStatus::Unspecified => "BOND_STATUS_UNSPECIFIED",
StakingBondStatus::Unbonded => "BOND_STATUS_UNBONDED",
StakingBondStatus::Unbonding => "BOND_STATUS_UNBONDING",
StakingBondStatus::Bonded => "BOND_STATUS_BONDED",
};
write!(f, "{}", str)
}
}
pub fn cosmrs_to_cosmwasm_validator(
validator: cosmrs::proto::cosmos::staking::v1beta1::Validator,
) -> Result<cosmwasm_std::Validator, StdError> {
let comission = validator.commission.unwrap().commission_rates.unwrap();
Ok(cosmwasm_std::Validator {
address: validator.operator_address,
commission: comission.rate.parse()?,
max_commission: comission.max_rate.parse()?,
max_change_rate: comission.max_change_rate.parse()?,
})
}
pub fn cosmrs_to_cosmwasm_delegation(
delegation_response: cosmrs::proto::cosmos::staking::v1beta1::DelegationResponse,
) -> Result<cosmwasm_std::Delegation, StdError> {
let delegation = delegation_response.delegation.unwrap();
Ok(cosmwasm_std::Delegation {
delegator: Addr::unchecked(delegation.delegator_address),
validator: delegation.validator_address,
amount: cosmrs_to_cosmwasm_coin(delegation_response.balance.unwrap())?,
})
}