Skip to content

Commit 7db3578

Browse files
committed
Add node_bonded field to delegations
- clarifies whether the delegation is to a bonded or unbonded node - include delegations to unbonded nodes in the returned list
1 parent 5bdda91 commit 7db3578

File tree

3 files changed

+82
-59
lines changed

3 files changed

+82
-59
lines changed

nym-api/src/unstable_routes/account/cache.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,13 @@ impl AddressInfoCache {
108108
address: account_id.to_string(),
109109
balance: balance.into(),
110110
delegations: delegation_data
111-
.delegations()
112111
.into_iter()
113112
.map(|d| NyxAccountDelegationDetails {
114-
delegated: d.amount,
115-
height: d.height,
116-
node_id: d.node_id,
117-
proxy: d.proxy,
113+
delegated: d.details().amount.clone(),
114+
height: d.details().height,
115+
node_id: d.details().node_id,
116+
proxy: d.details().proxy.clone(),
117+
node_bonded: d.is_node_bonded(),
118118
})
119119
.collect(),
120120
accumulated_rewards,

nym-api/src/unstable_routes/account/data_collector.rs

Lines changed: 73 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,9 @@ use crate::{
88
};
99
use cosmwasm_std::{Coin, Decimal};
1010
use nym_mixnet_contract_common::NodeRewarding;
11-
use nym_topology::NodeId;
1211
use nym_validator_client::nyxd::AccountId;
1312
use std::collections::{HashMap, HashSet};
14-
use tracing::warn;
13+
use tracing::error;
1514

1615
pub(crate) struct AddressDataCollector {
1716
nyxd_client: crate::nyxd::Client,
@@ -56,18 +55,18 @@ impl AddressDataCollector {
5655
Ok(balance)
5756
}
5857

59-
pub(crate) async fn get_delegations(&mut self) -> AxumResult<AddressDelegationInfo> {
58+
pub(crate) async fn get_delegations(&mut self) -> AxumResult<Vec<AddressDelegationInfo>> {
6059
let og_delegations = self
6160
.nyxd_client
6261
.get_all_delegator_delegations(&self.account_id)
63-
.await?;
62+
.await?
63+
.into_iter()
64+
.map(|delegation| (delegation.node_id, delegation))
65+
.collect::<HashMap<_, _>>();
6466

65-
let delegated_to_nodes = og_delegations
66-
.iter()
67-
.map(|d| d.node_id)
68-
.collect::<HashSet<_>>();
67+
let mut node_delegation_info = Vec::new();
6968

70-
let nym_nodes = self
69+
let delegated_to_nodes_bonded = self
7170
.nym_contract_cache
7271
.all_cached_nym_nodes()
7372
.await
@@ -85,61 +84,72 @@ impl AddressDataCollector {
8584
// add to totals
8685
self.total_value += pending_operator_reward;
8786
}
88-
if delegated_to_nodes.contains(&node_details.node_id()) {
89-
Some((
90-
node_details.node_id(),
91-
// avoid cloning node data which we don't need
92-
(
93-
node_details.rewarding_details.clone(),
87+
if let Some(delegation) = og_delegations.get(&node_details.node_id()) {
88+
node_delegation_info.push(AddressDelegationInfo {
89+
details: delegation.clone(),
90+
node_reward_info: NodeBondStatus::Bonded(
91+
node_details.rewarding_details.to_owned(),
9492
node_details.is_unbonding(),
9593
),
96-
))
94+
});
95+
96+
Some(node_details.node_id())
9797
} else {
9898
None
9999
}
100100
})
101-
.collect::<HashMap<_, _>>();
101+
.collect::<HashSet<_>>();
102+
103+
for (node_id, delegation) in og_delegations {
104+
if !delegated_to_nodes_bonded.contains(&node_id) {
105+
node_delegation_info.push(AddressDelegationInfo {
106+
details: delegation.clone(),
107+
node_reward_info: NodeBondStatus::UnBonded,
108+
});
109+
}
110+
}
102111

103-
Ok(AddressDelegationInfo {
104-
delegations: og_delegations,
105-
delegated_to_nodes: nym_nodes,
106-
})
112+
Ok(node_delegation_info)
107113
}
108114

109115
pub(crate) async fn calculate_rewards(
110116
&mut self,
111-
delegation_data: &AddressDelegationInfo,
117+
delegation_data: &Vec<AddressDelegationInfo>,
112118
) -> AxumResult<Vec<NyxAccountDelegationRewardDetails>> {
113119
let mut accumulated_rewards = Vec::new();
114-
for delegation in delegation_data.delegations.iter() {
115-
let node_id = &delegation.node_id;
116-
117-
if let Some((rewarding_details, is_unbonding)) =
118-
delegation_data.delegated_to_nodes.get(node_id)
119-
{
120-
match rewarding_details.determine_delegation_reward(delegation) {
121-
Ok(delegation_reward) => {
122-
let reward = NyxAccountDelegationRewardDetails {
123-
node_id: delegation.node_id,
124-
rewards: decimal_to_coin(delegation_reward, &self.base_denom),
125-
amount_staked: delegation.amount.clone(),
126-
node_still_fully_bonded: !is_unbonding,
127-
};
128-
// 4. sum the rewards and delegations
129-
self.total_delegations += delegation.amount.amount.u128();
130-
self.total_value += delegation.amount.amount.u128();
131-
self.total_value += reward.rewards.amount.u128();
132-
self.claimable_rewards += reward.rewards.amount.u128();
133-
134-
accumulated_rewards.push(reward);
135-
}
136-
Err(err) => {
137-
warn!(
138-
"Couldn't determine delegations for {} on node {}: {}",
139-
&self.account_id, node_id, err
140-
)
120+
for delegation in delegation_data {
121+
let node_id = delegation.details.node_id;
122+
123+
match &delegation.node_reward_info {
124+
NodeBondStatus::Bonded(node_rewarding, is_unbonding) => {
125+
match node_rewarding.determine_delegation_reward(&delegation.details) {
126+
Ok(delegation_reward) => {
127+
let reward = NyxAccountDelegationRewardDetails {
128+
node_id,
129+
rewards: decimal_to_coin(delegation_reward, &self.base_denom),
130+
amount_staked: delegation.details.amount.clone(),
131+
node_still_fully_bonded: !is_unbonding,
132+
};
133+
// 4. sum the rewards and delegations
134+
self.total_delegations += delegation.details.amount.amount.u128();
135+
self.total_value += delegation.details.amount.amount.u128();
136+
self.total_value += reward.rewards.amount.u128();
137+
self.claimable_rewards += reward.rewards.amount.u128();
138+
139+
accumulated_rewards.push(reward);
140+
}
141+
Err(err) => {
142+
error!(
143+
"Couldn't determine delegations for {} on node {}: {}",
144+
&self.account_id, node_id, err
145+
)
146+
}
141147
}
142148
}
149+
NodeBondStatus::UnBonded => {
150+
// directory cache doesn't store node details required to
151+
// calculate rewarding for unbonded nodes
152+
}
143153
}
144154
}
145155

@@ -171,24 +181,33 @@ impl AddressDataCollector {
171181
}
172182

173183
pub(crate) struct AddressDelegationInfo {
174-
delegations: Vec<nym_mixnet_contract_common::Delegation>,
175-
delegated_to_nodes: HashMap<NodeId, RewardAndBondInfo>,
184+
details: nym_mixnet_contract_common::Delegation,
185+
node_reward_info: NodeBondStatus,
176186
}
177187

178188
impl AddressDelegationInfo {
179-
pub(crate) fn delegations(self) -> Vec<nym_mixnet_contract_common::Delegation> {
180-
self.delegations
189+
pub(crate) fn details(&self) -> &nym_mixnet_contract_common::Delegation {
190+
&self.details
191+
}
192+
193+
pub(crate) fn is_node_bonded(&self) -> bool {
194+
matches!(self.node_reward_info, NodeBondStatus::Bonded(_, _))
181195
}
182196
}
183197

184-
type RewardAndBondInfo = (NodeRewarding, bool);
198+
pub(crate) enum NodeBondStatus {
199+
/// bool: is node in the process of unbonding
200+
Bonded(NodeRewarding, bool),
201+
UnBonded,
202+
}
185203

186204
fn decimal_to_coin(decimal: Decimal, denom: impl Into<String>) -> Coin {
187205
Coin::new(decimal.to_uint_floor(), denom)
188206
}
189207

190208
#[cfg(test)]
191209
mod test {
210+
192211
use super::*;
193212

194213
#[tokio::test]

nym-api/src/unstable_routes/models.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub struct NyxAccountDelegationDetails {
2121
pub height: u64,
2222
#[schema(value_type = Option<String>)]
2323
pub proxy: Option<Addr>,
24+
pub node_bonded: bool,
2425
}
2526

2627
#[derive(Clone, Debug, Serialize, Deserialize, utoipa::ToSchema, utoipa::ToResponse)]
@@ -41,6 +42,9 @@ pub struct NyxAccountDetails {
4142
#[schema(value_type = CoinSchema)]
4243
pub total_value: Coin,
4344
pub delegations: Vec<NyxAccountDelegationDetails>,
45+
/// Shows rewards from delegations to **currently** bonded nodes.
46+
/// Rewards from nodes that user delegated to, but were later unbonded,
47+
/// are claimable, but not shown here.
4448
pub accumulated_rewards: Vec<NyxAccountDelegationRewardDetails>,
4549
#[schema(value_type = String)]
4650
pub total_delegations: Coin,

0 commit comments

Comments
 (0)