iota_types/stardust/output/
basic.rs1use anyhow::Result;
8use iota_sdk_move_types::stardust::{
9 expiration_unlock_condition::ExpirationUnlockCondition,
10 storage_deposit_return_unlock_condition::StorageDepositReturnUnlockCondition,
11 timelock_unlock_condition::TimelockUnlockCondition,
12};
13use iota_sdk_types::{Address, Identifier, StructTag};
14use serde::{Deserialize, Serialize};
15use serde_with::serde_as;
16
17use crate::{balance::Balance, collection_types::Bag, error::IotaError, id::UID, object::Object};
18
19pub const BASIC_OUTPUT_MODULE_NAME: Identifier = Identifier::from_static("basic_output");
20pub const BASIC_OUTPUT_STRUCT_NAME: Identifier = Identifier::from_static("BasicOutput");
21
22#[serde_as]
24#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq)]
25pub struct BasicOutput {
26 pub id: UID,
28
29 pub balance: Balance,
31
32 pub native_tokens: Bag,
36
37 pub storage_deposit_return: Option<StorageDepositReturnUnlockCondition>,
39 pub timelock: Option<TimelockUnlockCondition>,
41 pub expiration: Option<ExpirationUnlockCondition>,
43
44 pub metadata: Option<Vec<u8>>,
48 pub tag: Option<Vec<u8>>,
50 pub sender: Option<Address>,
52}
53
54impl BasicOutput {
55 pub fn from_bcs_bytes(content: &[u8]) -> Result<Self, IotaError> {
57 bcs::from_bytes(content).map_err(|err| IotaError::ObjectDeserialization {
58 error: format!("Unable to deserialize BasicOutput object: {err:?}"),
59 })
60 }
61
62 pub fn is_basic_output(s: &StructTag) -> bool {
64 s.address() == Address::STARDUST
65 && s.module() == &BASIC_OUTPUT_MODULE_NAME
66 && s.name() == &BASIC_OUTPUT_STRUCT_NAME
67 }
68}
69
70impl TryFrom<&Object> for BasicOutput {
71 type Error = IotaError;
72 fn try_from(object: &Object) -> Result<Self, Self::Error> {
73 if let Some(o) = object.data.as_opt_struct() {
74 if BasicOutput::is_basic_output(o.struct_tag()) {
75 return BasicOutput::from_bcs_bytes(o.contents());
76 }
77 }
78
79 Err(IotaError::Type {
80 error: format!("Object type is not a BasicOutput: {object:?}"),
81 })
82 }
83}