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
12pub 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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
302pub enum StakingBondStatus {
304 Unspecified = 0,
306 Unbonded = 1,
308 Unbonding = 2,
310 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}