Skip to main content

cw_orch_daemon/queriers/
staking.rs

1use std::fmt::Display;
2
3use crate::{cosmos_modules, error::DaemonError, Daemon};
4use cosmrs::proto::cosmos::base::query::v1beta1::PageRequest;
5use cosmwasm_std::{Addr, StdError};
6use cw_orch_core::environment::{Querier, QuerierGetter};
7use tokio::runtime::Handle;
8use tonic::transport::Channel;
9
10use super::bank::cosmrs_to_cosmwasm_coin;
11
12/// Querier for the Cosmos Staking module
13/// All the async function are prefixed with `_`
14pub struct Staking {
15    pub channel: Channel,
16    pub rt_handle: Option<Handle>,
17}
18
19impl Staking {
20    pub fn new(daemon: &Daemon) -> Self {
21        Self {
22            channel: daemon.channel(),
23            rt_handle: Some(daemon.rt_handle.clone()),
24        }
25    }
26
27    pub fn new_async(channel: Channel) -> Self {
28        Self {
29            channel,
30            rt_handle: None,
31        }
32    }
33}
34
35impl Querier for Staking {
36    type Error = DaemonError;
37}
38
39impl QuerierGetter<Staking> for Daemon {
40    fn querier(&self) -> Staking {
41        Staking::new(self)
42    }
43}
44impl Staking {
45    /// Queries validator info for given validator address
46    pub async fn _validator(
47        &self,
48        validator_addr: &Addr,
49    ) -> Result<cosmwasm_std::Validator, DaemonError> {
50        let validator_response: cosmos_modules::staking::QueryValidatorResponse = cosmos_query!(
51            self,
52            staking,
53            validator,
54            QueryValidatorRequest {
55                validator_addr: validator_addr.into()
56            }
57        );
58
59        Ok(cosmrs_to_cosmwasm_validator(
60            validator_response.validator.unwrap(),
61        )?)
62    }
63
64    /// Queries all validators that match the given status
65    ///
66    /// see [StakingBondStatus] for available statuses
67    pub async fn _validators(
68        &self,
69        status: StakingBondStatus,
70    ) -> Result<Vec<cosmwasm_std::Validator>, DaemonError> {
71        let validators: cosmos_modules::staking::QueryValidatorsResponse = cosmos_query!(
72            self,
73            staking,
74            validators,
75            QueryValidatorsRequest {
76                status: status.to_string(),
77                pagination: None,
78            }
79        );
80
81        Ok(validators
82            .validators
83            .into_iter()
84            .map(cosmrs_to_cosmwasm_validator)
85            .collect::<Result<_, _>>()?)
86    }
87
88    /// Query validator delegations info for given validator
89    ///
90    /// see [PageRequest] for pagination
91    pub async fn _delegations(
92        &self,
93        validator_addr: &Addr,
94        pagination: Option<PageRequest>,
95    ) -> Result<Vec<cosmwasm_std::Delegation>, DaemonError> {
96        let validator_delegations: cosmos_modules::staking::QueryValidatorDelegationsResponse = cosmos_query!(
97            self,
98            staking,
99            validator_delegations,
100            QueryValidatorDelegationsRequest {
101                validator_addr: validator_addr.into(),
102                pagination: pagination
103            }
104        );
105        Ok(validator_delegations
106            .delegation_responses
107            .into_iter()
108            .map(cosmrs_to_cosmwasm_delegation)
109            .collect::<Result<_, _>>()?)
110    }
111
112    /// Query validator unbonding delegations of a validator
113    pub async fn _unbonding_delegations(
114        &self,
115        validator_addr: &Addr,
116    ) -> Result<Vec<cosmos_modules::staking::UnbondingDelegation>, DaemonError> {
117        let validator_unbonding_delegations: cosmos_modules::staking::QueryValidatorUnbondingDelegationsResponse = cosmos_query!(
118            self,
119            staking,
120            validator_unbonding_delegations,
121            QueryValidatorUnbondingDelegationsRequest {
122                validator_addr: validator_addr.into(),
123                pagination: None
124            }
125        );
126        Ok(validator_unbonding_delegations.unbonding_responses)
127    }
128
129    /// Query delegation info for given validator for a delegator
130    pub async fn _delegation(
131        &self,
132        validator_addr: &Addr,
133        delegator_addr: &Addr,
134    ) -> Result<cosmwasm_std::Delegation, DaemonError> {
135        let delegation: cosmos_modules::staking::QueryDelegationResponse = cosmos_query!(
136            self,
137            staking,
138            delegation,
139            QueryDelegationRequest {
140                validator_addr: validator_addr.into(),
141                delegator_addr: delegator_addr.into()
142            }
143        );
144        Ok(cosmrs_to_cosmwasm_delegation(
145            delegation.delegation_response.unwrap(),
146        )?)
147    }
148
149    /// Query unbonding delegation info for given validator delegator
150    pub async fn _unbonding_delegation(
151        &self,
152        validator_addr: &Addr,
153        delegator_addr: &Addr,
154    ) -> Result<cosmos_modules::staking::UnbondingDelegation, DaemonError> {
155        let unbonding_delegation: cosmos_modules::staking::QueryUnbondingDelegationResponse = cosmos_query!(
156            self,
157            staking,
158            unbonding_delegation,
159            QueryUnbondingDelegationRequest {
160                validator_addr: validator_addr.into(),
161                delegator_addr: delegator_addr.into()
162            }
163        );
164        Ok(unbonding_delegation.unbond.unwrap())
165    }
166
167    /// Query all delegator delegations of a given delegator address
168    ///
169    /// see [PageRequest] for pagination
170    pub async fn _delegator_delegations(
171        &self,
172        delegator_addr: &Addr,
173        pagination: Option<PageRequest>,
174    ) -> Result<cosmos_modules::staking::QueryDelegatorDelegationsResponse, DaemonError> {
175        let delegator_delegations: cosmos_modules::staking::QueryDelegatorDelegationsResponse = cosmos_query!(
176            self,
177            staking,
178            delegator_delegations,
179            QueryDelegatorDelegationsRequest {
180                delegator_addr: delegator_addr.into(),
181                pagination: pagination
182            }
183        );
184        Ok(delegator_delegations)
185    }
186
187    /// Queries all unbonding delegations of a given delegator address.
188    ///
189    /// see [PageRequest] for pagination
190    pub async fn _delegator_unbonding_delegations(
191        &self,
192        delegator_addr: &Addr,
193        pagination: Option<PageRequest>,
194    ) -> Result<cosmos_modules::staking::QueryDelegatorUnbondingDelegationsResponse, DaemonError>
195    {
196        let delegator_unbonding_delegations: cosmos_modules::staking::QueryDelegatorUnbondingDelegationsResponse = cosmos_query!(
197            self,
198            staking,
199            delegator_unbonding_delegations,
200            QueryDelegatorUnbondingDelegationsRequest {
201                delegator_addr: delegator_addr.into(),
202                pagination: pagination
203            }
204        );
205        Ok(delegator_unbonding_delegations)
206    }
207
208    /// Query redelegations of a given address
209    ///
210    /// see [PageRequest] for pagination
211    pub async fn _redelegations(
212        &self,
213        delegator_addr: &Addr,
214        src_validator_addr: &Addr,
215        dst_validator_addr: &Addr,
216        pagination: Option<PageRequest>,
217    ) -> Result<cosmos_modules::staking::QueryRedelegationsResponse, DaemonError> {
218        let redelegations: cosmos_modules::staking::QueryRedelegationsResponse = cosmos_query!(
219            self,
220            staking,
221            redelegations,
222            QueryRedelegationsRequest {
223                delegator_addr: delegator_addr.into(),
224                src_validator_addr: src_validator_addr.into(),
225                dst_validator_addr: dst_validator_addr.into(),
226                pagination: pagination
227            }
228        );
229        Ok(redelegations)
230    }
231
232    /// Query delegator validators info for given delegator address.
233    pub async fn _delegator_validator(
234        &self,
235        validator_addr: &Addr,
236        delegator_addr: &Addr,
237    ) -> Result<cosmos_modules::staking::QueryDelegatorValidatorResponse, DaemonError> {
238        let delegator_validator: cosmos_modules::staking::QueryDelegatorValidatorResponse = cosmos_query!(
239            self,
240            staking,
241            delegator_validator,
242            QueryDelegatorValidatorRequest {
243                validator_addr: validator_addr.into(),
244                delegator_addr: delegator_addr.into(),
245            }
246        );
247        Ok(delegator_validator)
248    }
249
250    /// Query delegator validators info for given delegator address
251    ///
252    /// see [PageRequest] for pagination
253    pub async fn _delegator_validators(
254        &self,
255        delegator_addr: &Addr,
256        pagination: Option<PageRequest>,
257    ) -> Result<cosmos_modules::staking::QueryDelegatorValidatorsResponse, DaemonError> {
258        let delegator_validators: cosmos_modules::staking::QueryDelegatorValidatorsResponse = cosmos_query!(
259            self,
260            staking,
261            delegator_validators,
262            QueryDelegatorValidatorsRequest {
263                delegator_addr: delegator_addr.into(),
264                pagination: pagination
265            }
266        );
267
268        Ok(delegator_validators)
269    }
270
271    /// Query historical info info for given height
272    pub async fn _historical_info(
273        &self,
274        height: i64,
275    ) -> Result<cosmos_modules::staking::QueryHistoricalInfoResponse, DaemonError> {
276        let historical_info: cosmos_modules::staking::QueryHistoricalInfoResponse = cosmos_query!(
277            self,
278            staking,
279            historical_info,
280            QueryHistoricalInfoRequest { height: height }
281        );
282        Ok(historical_info)
283    }
284
285    /// Query the pool info
286    pub async fn _pool(&self) -> Result<cosmos_modules::staking::QueryPoolResponse, DaemonError> {
287        let pool: cosmos_modules::staking::QueryPoolResponse =
288            cosmos_query!(self, staking, pool, QueryPoolRequest {});
289        Ok(pool)
290    }
291
292    /// Query staking parameters
293    pub async fn _params(
294        &self,
295    ) -> Result<cosmos_modules::staking::QueryParamsResponse, DaemonError> {
296        let params: cosmos_modules::staking::QueryParamsResponse =
297            cosmos_query!(self, staking, params, QueryParamsRequest {});
298        Ok(params)
299    }
300}
301
302/// Staking bond statuses
303pub enum StakingBondStatus {
304    /// UNSPECIFIED defines an invalid validator status.
305    Unspecified = 0,
306    /// UNBONDED defines a validator that is not bonded.
307    Unbonded = 1,
308    /// UNBONDING defines a validator that is unbonding.
309    Unbonding = 2,
310    /// BONDED defines a validator that is bonded.
311    Bonded = 3,
312}
313
314impl Display for StakingBondStatus {
315    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
316        let str = match self {
317            StakingBondStatus::Unspecified => "BOND_STATUS_UNSPECIFIED",
318            StakingBondStatus::Unbonded => "BOND_STATUS_UNBONDED",
319            StakingBondStatus::Unbonding => "BOND_STATUS_UNBONDING",
320            StakingBondStatus::Bonded => "BOND_STATUS_BONDED",
321        };
322        write!(f, "{}", str)
323    }
324}
325
326pub fn cosmrs_to_cosmwasm_validator(
327    validator: cosmrs::proto::cosmos::staking::v1beta1::Validator,
328) -> Result<cosmwasm_std::Validator, StdError> {
329    let comission = validator.commission.unwrap().commission_rates.unwrap();
330    Ok(cosmwasm_std::Validator::new(
331        validator.operator_address,
332        comission.rate.parse()?,
333        comission.max_rate.parse()?,
334        comission.max_change_rate.parse()?,
335    ))
336}
337
338pub fn cosmrs_to_cosmwasm_delegation(
339    delegation_response: cosmrs::proto::cosmos::staking::v1beta1::DelegationResponse,
340) -> Result<cosmwasm_std::Delegation, StdError> {
341    let delegation = delegation_response.delegation.unwrap();
342    Ok(cosmwasm_std::Delegation::new(
343        Addr::unchecked(delegation.delegator_address),
344        delegation.validator_address,
345        cosmrs_to_cosmwasm_coin(delegation_response.balance.unwrap())?,
346    ))
347}