1use iota_sdk_types::{Identifier, ObjectData, ObjectId};
6use serde::{Deserialize, Serialize};
7
8use crate::{
9 balance::Balance,
10 committee::EpochId,
11 error::IotaError,
12 id::{ID, UID},
13 object::Object,
14};
15
16pub const ADD_STAKE_MUL_COIN_FUN_NAME: Identifier =
17 Identifier::from_static("request_add_stake_mul_coin");
18pub const ADD_STAKE_FUN_NAME: Identifier = Identifier::from_static("request_add_stake");
19pub const WITHDRAW_STAKE_FUN_NAME: Identifier = Identifier::from_static("request_withdraw_stake");
20
21#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
22pub struct StakedIota {
23 id: UID,
24 pool_id: ID,
25 stake_activation_epoch: u64,
26 principal: Balance,
27}
28
29impl StakedIota {
30 pub fn id(&self) -> ObjectId {
31 self.id.id.bytes
32 }
33
34 pub fn pool_id(&self) -> ObjectId {
35 self.pool_id.bytes
36 }
37
38 pub fn activation_epoch(&self) -> EpochId {
39 self.stake_activation_epoch
40 }
41
42 pub fn request_epoch(&self) -> EpochId {
43 self.stake_activation_epoch.saturating_sub(1)
45 }
46
47 pub fn principal(&self) -> u64 {
48 self.principal.value()
49 }
50}
51
52impl TryFrom<&Object> for StakedIota {
53 type Error = IotaError;
54 fn try_from(object: &Object) -> Result<Self, Self::Error> {
55 match &object.data {
56 ObjectData::Struct(o) => {
57 if o.struct_tag().is_staked_iota() {
58 return bcs::from_bytes(o.contents()).map_err(|err| IotaError::Type {
59 error: format!("Unable to deserialize StakedIota object: {err:?}"),
60 });
61 }
62 }
63 ObjectData::Package(_) => {}
64 }
65
66 Err(IotaError::Type {
67 error: format!("Object type is not a StakedIota: {object:?}"),
68 })
69 }
70}