Skip to main content

iota_types/block/output/
metadata.rs

1// Copyright 2023 IOTA Stiftung
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::block::{output::OutputId, payload::transaction::TransactionId, BlockId};
5
6/// Metadata of an [`Output`](crate::block::output::Output).
7#[derive(Clone, Debug, Eq, PartialEq, Hash)]
8#[cfg_attr(
9    feature = "serde",
10    derive(serde::Serialize, serde::Deserialize),
11    serde(rename_all = "camelCase")
12)]
13pub struct OutputMetadata {
14    /// The identifier of the block in which the output was included.
15    block_id: BlockId,
16    /// The identifier of the output.
17    output_id: OutputId,
18    /// Whether the output is spent or not.
19    is_spent: bool,
20    /// If spent, the index of the milestone in which the output was spent.
21    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
22    milestone_index_spent: Option<u32>,
23    /// If spent, the timestamp of the milestone in which the output was spent.
24    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
25    milestone_timestamp_spent: Option<u32>,
26    /// If spent, the identifier of the transaction that spent the output.
27    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
28    transaction_id_spent: Option<TransactionId>,
29    /// The index of the milestone that booked the output.
30    milestone_index_booked: u32,
31    /// The timestamp of the milestone that booked the output.
32    milestone_timestamp_booked: u32,
33    /// The index of ledger when the output was fetched.
34    ledger_index: u32,
35}
36
37impl OutputMetadata {
38    /// Creates a new [`OutputMetadata`].
39    #[allow(clippy::too_many_arguments)]
40    pub fn new(
41        block_id: BlockId,
42        output_id: OutputId,
43        is_spent: bool,
44        milestone_index_spent: Option<u32>,
45        milestone_timestamp_spent: Option<u32>,
46        transaction_id_spent: Option<TransactionId>,
47        milestone_index_booked: u32,
48        milestone_timestamp_booked: u32,
49        ledger_index: u32,
50    ) -> Self {
51        Self {
52            block_id,
53            output_id,
54            is_spent,
55            milestone_index_spent,
56            milestone_timestamp_spent,
57            transaction_id_spent,
58            milestone_index_booked,
59            milestone_timestamp_booked,
60            ledger_index,
61        }
62    }
63
64    /// Returns the block id of the [`OutputMetadata`].
65    pub fn block_id(&self) -> &BlockId {
66        &self.block_id
67    }
68
69    /// Returns the output id of the [`OutputMetadata`].
70    pub fn output_id(&self) -> &OutputId {
71        &self.output_id
72    }
73
74    /// Returns the transaction id of the [`OutputMetadata`].
75    pub fn transaction_id(&self) -> &TransactionId {
76        self.output_id.transaction_id()
77    }
78
79    /// Returns the output index of the [`OutputMetadata`].
80    pub fn output_index(&self) -> u16 {
81        self.output_id.index()
82    }
83
84    /// Returns whether the output is spent ot not.
85    pub fn is_spent(&self) -> bool {
86        self.is_spent
87    }
88
89    /// Returns the milestone index spent of the [`OutputMetadata`].
90    pub fn milestone_index_spent(&self) -> Option<u32> {
91        self.milestone_index_spent
92    }
93
94    /// Returns the milestone timestamp spent of the [`OutputMetadata`].
95    pub fn milestone_timestamp_spent(&self) -> Option<u32> {
96        self.milestone_timestamp_spent
97    }
98
99    /// Returns the transaction id spent of the [`OutputMetadata`].
100    pub fn transaction_id_spent(&self) -> Option<&TransactionId> {
101        self.transaction_id_spent.as_ref()
102    }
103
104    /// Returns the milestone index booked of the [`OutputMetadata`].
105    pub fn milestone_index_booked(&self) -> u32 {
106        self.milestone_index_booked
107    }
108
109    /// Returns the milestone timestamp booked of the [`OutputMetadata`].
110    pub fn milestone_timestamp_booked(&self) -> u32 {
111        self.milestone_timestamp_booked
112    }
113
114    /// Returns the ledger index of the [`OutputMetadata`].
115    pub fn ledger_index(&self) -> u32 {
116        self.ledger_index
117    }
118}
119
120#[cfg(feature = "dto")]
121#[allow(missing_docs)]
122pub mod dto {
123    use std::str::FromStr;
124
125    use serde::{Deserialize, Serialize};
126
127    use super::*;
128    use crate::block::error::dto::DtoError;
129
130    /// DTO for an [`OutputMetadata`].
131    #[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
132    #[serde(rename_all = "camelCase")]
133    pub struct OutputMetadataDto {
134        pub block_id: String,
135        pub transaction_id: String,
136        pub output_index: u16,
137        pub is_spent: bool,
138        #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
139        pub milestone_index_spent: Option<u32>,
140        #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
141        pub milestone_timestamp_spent: Option<u32>,
142        #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
143        pub transaction_id_spent: Option<String>,
144        pub milestone_index_booked: u32,
145        pub milestone_timestamp_booked: u32,
146        pub ledger_index: u32,
147    }
148
149    impl OutputMetadataDto {
150        /// Returns the output id.
151        pub fn output_id(&self) -> Result<OutputId, crate::block::Error> {
152            OutputId::new(TransactionId::from_str(&self.transaction_id)?, self.output_index)
153        }
154    }
155
156    impl TryFrom<&OutputMetadataDto> for OutputMetadata {
157        type Error = DtoError;
158
159        fn try_from(response: &OutputMetadataDto) -> Result<Self, Self::Error> {
160            Ok(Self {
161                block_id: BlockId::from_str(&response.block_id)?,
162                output_id: OutputId::new(
163                    TransactionId::from_str(&response.transaction_id)?,
164                    response.output_index,
165                )?,
166                is_spent: response.is_spent,
167                milestone_index_spent: response.milestone_index_spent,
168                milestone_timestamp_spent: response.milestone_timestamp_spent,
169                transaction_id_spent: response
170                    .transaction_id_spent
171                    .as_ref()
172                    .map(|s| TransactionId::from_str(s))
173                    .transpose()?,
174                milestone_index_booked: response.milestone_index_booked,
175                milestone_timestamp_booked: response.milestone_timestamp_booked,
176                ledger_index: response.ledger_index,
177            })
178        }
179    }
180
181    impl From<&OutputMetadata> for OutputMetadataDto {
182        fn from(output_metadata: &OutputMetadata) -> Self {
183            Self {
184                block_id: output_metadata.block_id().to_string(),
185                transaction_id: output_metadata.transaction_id().to_string(),
186                output_index: output_metadata.output_index(),
187                is_spent: output_metadata.is_spent(),
188                milestone_index_spent: output_metadata.milestone_index_spent(),
189                milestone_timestamp_spent: output_metadata.milestone_timestamp_spent(),
190                transaction_id_spent: output_metadata.transaction_id_spent().map(|t| t.to_string()),
191                milestone_index_booked: output_metadata.milestone_index_booked(),
192                milestone_timestamp_booked: output_metadata.milestone_timestamp_booked(),
193                ledger_index: output_metadata.ledger_index(),
194            }
195        }
196    }
197}