Skip to main content

iota_types/timelock/
timelocked_staked_iota.rs

1// Copyright (c) 2024 IOTA Stiftung
2// SPDX-License-Identifier: Apache-2.0
3
4use iota_sdk_move_types::iota_framework::object::UID;
5use iota_sdk_types::ObjectId;
6use serde::{Deserialize, Serialize};
7
8use crate::{committee::EpochId, error::IotaError, governance::StakedIota, object::Object};
9
10/// Rust version of the Move
11/// stardust::timelocked_staked_iota::TimelockedStakedIota type.
12#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
13pub struct TimelockedStakedIota {
14    id: UID,
15    /// A self-custodial object holding the staked IOTA tokens.
16    staked_iota: StakedIota,
17    /// This is the epoch time stamp of when the lock expires.
18    expiration_timestamp_ms: u64,
19    /// Timelock related label.
20    label: Option<String>,
21}
22
23impl TimelockedStakedIota {
24    /// Get the TimelockedStakedIota's `id`.
25    pub fn id(&self) -> ObjectId {
26        self.id.id.bytes
27    }
28
29    /// Get the wrapped StakedIota's `pool_id`.
30    pub fn pool_id(&self) -> ObjectId {
31        self.staked_iota.pool_id()
32    }
33
34    /// Get the wrapped StakedIota's `activation_epoch`.
35    pub fn activation_epoch(&self) -> EpochId {
36        self.staked_iota.activation_epoch()
37    }
38
39    /// Get the wrapped StakedIota's `request_epoch`.
40    pub fn request_epoch(&self) -> EpochId {
41        // TODO: this might change when we implement warm up period.
42        self.staked_iota.activation_epoch().saturating_sub(1)
43    }
44
45    /// Get the wrapped StakedIota's `principal`.
46    pub fn principal(&self) -> u64 {
47        self.staked_iota.principal()
48    }
49
50    /// Get the TimelockedStakedIota's `expiration_timestamp_ms`.
51    pub fn expiration_timestamp_ms(&self) -> u64 {
52        self.expiration_timestamp_ms
53    }
54
55    /// Get the TimelockedStakedIota's `label``.
56    pub fn label(&self) -> &Option<String> {
57        &self.label
58    }
59}
60
61impl TryFrom<&Object> for TimelockedStakedIota {
62    type Error = IotaError;
63    fn try_from(object: &Object) -> Result<Self, Self::Error> {
64        if let Some(o) = object.data.as_opt_struct() {
65            if o.struct_tag().is_timelocked_staked_iota() {
66                return bcs::from_bytes(o.contents()).map_err(|err| IotaError::Type {
67                    error: format!("Unable to deserialize TimelockedStakedIota object: {err:?}"),
68                });
69            }
70        }
71
72        Err(IotaError::Type {
73            error: format!("Object type is not a TimelockedStakedIota: {object:?}"),
74        })
75    }
76}