iota_types/timelock/
timelocked_staked_iota.rs

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