sui_sdk_types/effects/
mod.rs

1mod v1;
2mod v2;
3
4pub use v1::ModifiedAtVersion;
5pub use v1::ObjectReferenceWithOwner;
6pub use v1::TransactionEffectsV1;
7pub use v2::ChangedObject;
8pub use v2::IdOperation;
9pub use v2::ObjectIn;
10pub use v2::ObjectOut;
11pub use v2::TransactionEffectsV2;
12pub use v2::UnchangedSharedKind;
13pub use v2::UnchangedSharedObject;
14
15use crate::execution_status::ExecutionStatus;
16
17/// The output or effects of executing a transaction
18///
19/// # BCS
20///
21/// The BCS serialized form for this type is defined by the following ABNF:
22///
23/// ```text
24/// transaction-effects =  %x00 effects-v1
25///                     =/ %x01 effects-v2
26/// ```
27#[derive(Eq, PartialEq, Clone, Debug)]
28#[cfg_attr(feature = "proptest", derive(test_strategy::Arbitrary))]
29pub enum TransactionEffects {
30    V1(Box<TransactionEffectsV1>),
31    V2(Box<TransactionEffectsV2>),
32}
33
34impl TransactionEffects {
35    /// Return the status of the transaction.
36    pub fn status(&self) -> &ExecutionStatus {
37        match self {
38            TransactionEffects::V1(e) => e.status(),
39            TransactionEffects::V2(e) => e.status(),
40        }
41    }
42
43    /// Return the epoch in which this transaction was executed.
44    pub fn epoch(&self) -> u64 {
45        match self {
46            TransactionEffects::V1(e) => e.epoch(),
47            TransactionEffects::V2(e) => e.epoch(),
48        }
49    }
50
51    /// Return the gas cost summary of the transaction.
52    pub fn gas_summary(&self) -> &crate::gas::GasCostSummary {
53        match self {
54            TransactionEffects::V1(e) => e.gas_summary(),
55            TransactionEffects::V2(e) => e.gas_summary(),
56        }
57    }
58}
59
60#[cfg(feature = "serde")]
61#[cfg_attr(doc_cfg, doc(cfg(feature = "serde")))]
62mod serialization {
63    use super::TransactionEffects;
64    use super::TransactionEffectsV1;
65    use super::TransactionEffectsV2;
66
67    use serde::Deserialize;
68    use serde::Deserializer;
69    use serde::Serialize;
70    use serde::Serializer;
71
72    #[derive(serde_derive::Serialize)]
73    #[serde(tag = "version")]
74    enum ReadableEffectsRef<'a> {
75        #[serde(rename = "1")]
76        V1(&'a TransactionEffectsV1),
77        #[serde(rename = "2")]
78        V2(&'a TransactionEffectsV2),
79    }
80
81    #[derive(serde_derive::Deserialize)]
82    #[serde(tag = "version")]
83    pub enum ReadableEffects {
84        #[serde(rename = "1")]
85        V1(Box<TransactionEffectsV1>),
86        #[serde(rename = "2")]
87        V2(Box<TransactionEffectsV2>),
88    }
89
90    #[derive(serde_derive::Serialize)]
91    enum BinaryEffectsRef<'a> {
92        V1(&'a TransactionEffectsV1),
93        V2(&'a TransactionEffectsV2),
94    }
95
96    #[derive(serde_derive::Deserialize)]
97    pub enum BinaryEffects {
98        V1(Box<TransactionEffectsV1>),
99        V2(Box<TransactionEffectsV2>),
100    }
101
102    impl Serialize for TransactionEffects {
103        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
104        where
105            S: Serializer,
106        {
107            if serializer.is_human_readable() {
108                let readable = match self {
109                    TransactionEffects::V1(fx) => ReadableEffectsRef::V1(fx),
110                    TransactionEffects::V2(fx) => ReadableEffectsRef::V2(fx),
111                };
112                readable.serialize(serializer)
113            } else {
114                let binary = match self {
115                    TransactionEffects::V1(fx) => BinaryEffectsRef::V1(fx),
116                    TransactionEffects::V2(fx) => BinaryEffectsRef::V2(fx),
117                };
118                binary.serialize(serializer)
119            }
120        }
121    }
122
123    impl<'de> Deserialize<'de> for TransactionEffects {
124        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
125        where
126            D: Deserializer<'de>,
127        {
128            if deserializer.is_human_readable() {
129                ReadableEffects::deserialize(deserializer).map(|readable| match readable {
130                    ReadableEffects::V1(fx) => Self::V1(fx),
131                    ReadableEffects::V2(fx) => Self::V2(fx),
132                })
133            } else {
134                BinaryEffects::deserialize(deserializer).map(|binary| match binary {
135                    BinaryEffects::V1(fx) => Self::V1(fx),
136                    BinaryEffects::V2(fx) => Self::V2(fx),
137                })
138            }
139        }
140    }
141
142    #[cfg(test)]
143    mod tests {
144        use super::TransactionEffects;
145
146        use base64ct::Base64;
147        use base64ct::Encoding;
148
149        #[cfg(target_arch = "wasm32")]
150        use wasm_bindgen_test::wasm_bindgen_test as test;
151
152        #[test]
153        fn effects_fixtures() {
154            const GENESIS_EFFECTS: &str = include_str!("fixtures/genesis-transaction-effects");
155            const PYTH_WORMHOLE_V2: &str = include_str!("fixtures/pyth-wormhole-v2");
156
157            for fixture in [GENESIS_EFFECTS, PYTH_WORMHOLE_V2] {
158                let fixture = Base64::decode_vec(fixture.trim()).unwrap();
159                let fx: TransactionEffects = bcs::from_bytes(&fixture).unwrap();
160                assert_eq!(bcs::to_bytes(&fx).unwrap(), fixture);
161
162                let json = serde_json::to_string_pretty(&fx).unwrap();
163                println!("{json}");
164                assert_eq!(fx, serde_json::from_str(&json).unwrap());
165            }
166        }
167    }
168}