1use iota_sdk_types::{Identifier, 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 if let Some(o) = object.data.as_opt_struct() {
56 if o.struct_tag().is_staked_iota() {
57 return bcs::from_bytes(o.contents()).map_err(|err| IotaError::Type {
58 error: format!("Unable to deserialize StakedIota object: {err:?}"),
59 });
60 }
61 }
62
63 Err(IotaError::Type {
64 error: format!("Object type is not a StakedIota: {object:?}"),
65 })
66 }
67}