iota_json_rpc_types/
object_changes.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use std::fmt::{Display, Formatter, Result};
6
7use iota_types::{
8    base_types::{IotaAddress, ObjectDigest, ObjectID, ObjectRef, SequenceNumber, StructTag},
9    iota_serde::IotaStructTag,
10    object::Owner,
11};
12use schemars::JsonSchema;
13use serde::{Deserialize, Serialize};
14use serde_with::serde_as;
15
16use crate::{
17    iota_owner::OwnerSchema,
18    iota_primitives::{
19        Base58 as Base58Schema, IotaAddress as IotaAddressSchema, ObjectID as ObjectIDSchema,
20        SequenceNumberString as SequenceNumberStringSchema, StructTag as StructTagSchema,
21    },
22};
23
24/// ObjectChange are derived from the object mutations in the TransactionEffect
25/// to provide richer object information.
26#[serde_as]
27#[derive(Debug, Clone, Deserialize, Serialize, JsonSchema, PartialEq, Eq)]
28#[serde(rename_all = "camelCase", tag = "type")]
29pub enum ObjectChange {
30    /// Module published
31    #[serde(rename_all = "camelCase")]
32    Published {
33        #[schemars(with = "ObjectIDSchema")]
34        package_id: ObjectID,
35        #[schemars(with = "SequenceNumberStringSchema")]
36        #[serde_as(as = "SequenceNumberStringSchema")]
37        version: SequenceNumber,
38        #[schemars(with = "Base58Schema")]
39        digest: ObjectDigest,
40        modules: Vec<String>,
41    },
42    /// Transfer objects to new address / wrap in another object
43    #[serde(rename_all = "camelCase")]
44    Transferred {
45        #[schemars(with = "IotaAddressSchema")]
46        sender: IotaAddress,
47        #[schemars(with = "OwnerSchema")]
48        #[serde_as(as = "OwnerSchema")]
49        recipient: Owner,
50        #[schemars(with = "StructTagSchema")]
51        #[serde_as(as = "StructTagSchema")]
52        object_type: StructTag,
53        #[schemars(with = "ObjectIDSchema")]
54        object_id: ObjectID,
55        #[schemars(with = "SequenceNumberStringSchema")]
56        #[serde_as(as = "SequenceNumberStringSchema")]
57        version: SequenceNumber,
58        #[schemars(with = "Base58Schema")]
59        digest: ObjectDigest,
60    },
61    /// Object mutated.
62    #[serde(rename_all = "camelCase")]
63    Mutated {
64        #[schemars(with = "IotaAddressSchema")]
65        sender: IotaAddress,
66        #[schemars(with = "OwnerSchema")]
67        #[serde_as(as = "OwnerSchema")]
68        owner: Owner,
69        #[schemars(with = "StructTagSchema")]
70        #[serde_as(as = "StructTagSchema")]
71        object_type: StructTag,
72        #[schemars(with = "ObjectIDSchema")]
73        object_id: ObjectID,
74        #[schemars(with = "SequenceNumberStringSchema")]
75        #[serde_as(as = "SequenceNumberStringSchema")]
76        version: SequenceNumber,
77        #[schemars(with = "SequenceNumberStringSchema")]
78        #[serde_as(as = "SequenceNumberStringSchema")]
79        previous_version: SequenceNumber,
80        #[schemars(with = "Base58Schema")]
81        digest: ObjectDigest,
82    },
83    /// Delete object
84    #[serde(rename_all = "camelCase")]
85    Deleted {
86        #[schemars(with = "IotaAddressSchema")]
87        sender: IotaAddress,
88        #[schemars(with = "StructTagSchema")]
89        #[serde_as(as = "StructTagSchema")]
90        object_type: StructTag,
91        #[schemars(with = "ObjectIDSchema")]
92        object_id: ObjectID,
93        #[schemars(with = "SequenceNumberStringSchema")]
94        #[serde_as(as = "SequenceNumberStringSchema")]
95        version: SequenceNumber,
96    },
97    /// Wrapped object
98    #[serde(rename_all = "camelCase")]
99    Wrapped {
100        #[schemars(with = "IotaAddressSchema")]
101        sender: IotaAddress,
102        #[schemars(with = "StructTagSchema")]
103        #[serde_as(as = "StructTagSchema")]
104        object_type: StructTag,
105        #[schemars(with = "ObjectIDSchema")]
106        object_id: ObjectID,
107        #[schemars(with = "SequenceNumberStringSchema")]
108        #[serde_as(as = "SequenceNumberStringSchema")]
109        version: SequenceNumber,
110    },
111    /// Unwrapped object
112    #[serde(rename_all = "camelCase")]
113    Unwrapped {
114        #[schemars(with = "IotaAddressSchema")]
115        sender: IotaAddress,
116        #[schemars(with = "OwnerSchema")]
117        #[serde_as(as = "OwnerSchema")]
118        owner: Owner,
119        #[schemars(with = "String")]
120        #[serde_as(as = "IotaStructTag")]
121        object_type: StructTag,
122        #[schemars(with = "ObjectIDSchema")]
123        object_id: ObjectID,
124        #[schemars(with = "SequenceNumberStringSchema")]
125        #[serde_as(as = "SequenceNumberStringSchema")]
126        version: SequenceNumber,
127        #[schemars(with = "Base58Schema")]
128        digest: ObjectDigest,
129    },
130    /// New object creation
131    #[serde(rename_all = "camelCase")]
132    Created {
133        #[schemars(with = "IotaAddressSchema")]
134        sender: IotaAddress,
135        #[schemars(with = "OwnerSchema")]
136        #[serde_as(as = "OwnerSchema")]
137        owner: Owner,
138        #[schemars(with = "StructTagSchema")]
139        #[serde_as(as = "StructTagSchema")]
140        object_type: StructTag,
141        #[schemars(with = "ObjectIDSchema")]
142        object_id: ObjectID,
143        #[schemars(with = "SequenceNumberStringSchema")]
144        #[serde_as(as = "SequenceNumberStringSchema")]
145        version: SequenceNumber,
146        #[schemars(with = "Base58Schema")]
147        digest: ObjectDigest,
148    },
149}
150
151impl ObjectChange {
152    pub fn object_id(&self) -> ObjectID {
153        match self {
154            ObjectChange::Published { package_id, .. } => *package_id,
155            ObjectChange::Transferred { object_id, .. }
156            | ObjectChange::Mutated { object_id, .. }
157            | ObjectChange::Deleted { object_id, .. }
158            | ObjectChange::Wrapped { object_id, .. }
159            | ObjectChange::Unwrapped { object_id, .. }
160            | ObjectChange::Created { object_id, .. } => *object_id,
161        }
162    }
163
164    pub fn object_ref(&self) -> ObjectRef {
165        match self {
166            ObjectChange::Published {
167                package_id,
168                version,
169                digest,
170                ..
171            } => ObjectRef::new(*package_id, *version, *digest),
172            ObjectChange::Transferred {
173                object_id,
174                version,
175                digest,
176                ..
177            }
178            | ObjectChange::Mutated {
179                object_id,
180                version,
181                digest,
182                ..
183            }
184            | ObjectChange::Unwrapped {
185                object_id,
186                version,
187                digest,
188                ..
189            }
190            | ObjectChange::Created {
191                object_id,
192                version,
193                digest,
194                ..
195            } => ObjectRef::new(*object_id, *version, *digest),
196            ObjectChange::Deleted {
197                object_id, version, ..
198            } => ObjectRef::new(*object_id, *version, ObjectDigest::OBJECT_DELETED),
199            ObjectChange::Wrapped {
200                object_id, version, ..
201            } => ObjectRef::new(*object_id, *version, ObjectDigest::OBJECT_WRAPPED),
202        }
203    }
204
205    pub fn mask_for_test(&mut self, new_version: SequenceNumber, new_digest: ObjectDigest) {
206        match self {
207            ObjectChange::Published {
208                version, digest, ..
209            }
210            | ObjectChange::Transferred {
211                version, digest, ..
212            }
213            | ObjectChange::Mutated {
214                version, digest, ..
215            }
216            | ObjectChange::Unwrapped {
217                version, digest, ..
218            }
219            | ObjectChange::Created {
220                version, digest, ..
221            } => {
222                *version = new_version;
223                *digest = new_digest
224            }
225            ObjectChange::Deleted { version, .. } | ObjectChange::Wrapped { version, .. } => {
226                *version = new_version
227            }
228        }
229    }
230}
231
232impl Display for ObjectChange {
233    fn fmt(&self, f: &mut Formatter) -> Result {
234        match self {
235            ObjectChange::Published {
236                package_id,
237                version,
238                digest,
239                modules,
240            } => {
241                write!(
242                    f,
243                    " ┌──\n │ PackageID: {} \n │ Version: {} \n │ Digest: {}\n │ Modules: {}\n └──",
244                    package_id,
245                    version,
246                    digest,
247                    modules.join(", ")
248                )
249            }
250            ObjectChange::Transferred {
251                sender,
252                recipient,
253                object_type,
254                object_id,
255                version,
256                digest,
257            } => {
258                write!(
259                    f,
260                    " ┌──\n │ ObjectID: {object_id}\n │ Sender: {sender} \n │ Recipient: {recipient}\n │ ObjectType: {object_type} \n │ Version: {version}\n │ Digest: {digest}\n └──"
261                )
262            }
263            ObjectChange::Mutated {
264                sender,
265                owner,
266                object_type,
267                object_id,
268                version,
269                previous_version: _,
270                digest,
271            } => {
272                write!(
273                    f,
274                    " ┌──\n │ ObjectID: {object_id}\n │ Sender: {sender} \n │ Owner: {owner}\n │ ObjectType: {object_type} \n │ Version: {version}\n │ Digest: {digest}\n └──"
275                )
276            }
277            ObjectChange::Deleted {
278                sender,
279                object_type,
280                object_id,
281                version,
282            } => {
283                write!(
284                    f,
285                    " ┌──\n │ ObjectID: {object_id}\n │ Sender: {sender} \n │ ObjectType: {object_type} \n │ Version: {version}\n └──"
286                )
287            }
288            ObjectChange::Wrapped {
289                sender,
290                object_type,
291                object_id,
292                version,
293            } => {
294                write!(
295                    f,
296                    " ┌──\n │ ObjectID: {object_id}\n │ Sender: {sender} \n │ ObjectType: {object_type} \n │ Version: {version}\n └──"
297                )
298            }
299            ObjectChange::Unwrapped {
300                sender,
301                owner,
302                object_type,
303                object_id,
304                version,
305                digest,
306            } => {
307                write!(
308                    f,
309                    " ┌──\n │ ObjectID: {}\n │ Sender: {} \n │ Owner: {}\n │ ObjectType: {} \n │ Version: {}\n │ Digest: {}\n └──",
310                    object_id,
311                    sender,
312                    owner,
313                    object_type,
314                    version.as_u64(),
315                    digest
316                )
317            }
318            ObjectChange::Created {
319                sender,
320                owner,
321                object_type,
322                object_id,
323                version,
324                digest,
325            } => {
326                write!(
327                    f,
328                    " ┌──\n │ ObjectID: {object_id}\n │ Sender: {sender} \n │ Owner: {owner}\n │ ObjectType: {object_type} \n │ Version: {version}\n │ Digest: {digest}\n └──"
329                )
330            }
331        }
332    }
333}