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