penumbra_sdk_stake/
delegate.rs1use penumbra_sdk_asset::{Balance, Value, STAKING_TOKEN_ASSET_ID};
2use penumbra_sdk_num::Amount;
3use penumbra_sdk_proto::{penumbra::core::component::stake::v1 as pb, DomainType};
4use penumbra_sdk_txhash::{EffectHash, EffectingData};
5use serde::{Deserialize, Serialize};
6
7use crate::{DelegationToken, IdentityKey};
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
11#[serde(try_from = "pb::Delegate", into = "pb::Delegate")]
12pub struct Delegate {
13 pub validator_identity: IdentityKey,
15 pub epoch_index: u64,
18 pub unbonded_amount: Amount,
21 pub delegation_amount: Amount,
27}
28
29impl EffectingData for Delegate {
30 fn effect_hash(&self) -> EffectHash {
31 EffectHash::from_proto_effecting_data(&self.to_proto())
33 }
34}
35
36impl Delegate {
37 pub fn balance(&self) -> Balance {
39 let stake: Balance = self.unbonded_value().into();
40 let delegation: Balance = self.delegation_value().into();
41
42 delegation - stake
44 }
45
46 pub fn delegation_value(&self) -> Value {
48 Value {
49 amount: self.delegation_amount,
50 asset_id: DelegationToken::new(self.validator_identity.clone()).id(),
51 }
52 }
53
54 pub fn unbonded_value(&self) -> Value {
56 Value {
57 amount: self.unbonded_amount,
58 asset_id: STAKING_TOKEN_ASSET_ID.clone(),
59 }
60 }
61}
62
63impl DomainType for Delegate {
64 type Proto = pb::Delegate;
65}
66
67impl From<Delegate> for pb::Delegate {
68 fn from(d: Delegate) -> Self {
69 pb::Delegate {
70 validator_identity: Some(d.validator_identity.into()),
71 epoch_index: d.epoch_index,
72 unbonded_amount: Some(d.unbonded_amount.into()),
73 delegation_amount: Some(d.delegation_amount.into()),
74 }
75 }
76}
77
78impl TryFrom<pb::Delegate> for Delegate {
79 type Error = anyhow::Error;
80 fn try_from(d: pb::Delegate) -> Result<Self, Self::Error> {
81 Ok(Self {
82 validator_identity: d
83 .validator_identity
84 .ok_or_else(|| anyhow::anyhow!("missing validator identity"))?
85 .try_into()?,
86 epoch_index: d.epoch_index,
87 unbonded_amount: d
88 .unbonded_amount
89 .ok_or_else(|| anyhow::anyhow!("missing unbonded amount"))?
90 .try_into()?,
91 delegation_amount: d
92 .delegation_amount
93 .ok_or_else(|| anyhow::anyhow!("missing delegation amount"))?
94 .try_into()?,
95 })
96 }
97}