iota_json_rpc/
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::collections::BTreeMap;
6
7use iota_json_rpc_types::ObjectChange;
8use iota_types::{
9    base_types::{IotaAddress, ObjectID, ObjectRef, SequenceNumber},
10    effects::ObjectRemoveKind,
11    object::Owner,
12    storage::WriteKind,
13};
14
15use crate::ObjectProvider;
16
17pub async fn get_object_changes<P: ObjectProvider<Error = E>, E>(
18    object_provider: &P,
19    sender: IotaAddress,
20    modified_at_versions: Vec<(ObjectID, SequenceNumber)>,
21    all_changed_objects: Vec<(ObjectRef, Owner, WriteKind)>,
22    all_removed_objects: Vec<(ObjectRef, ObjectRemoveKind)>,
23) -> Result<Vec<ObjectChange>, E> {
24    let mut object_changes = vec![];
25
26    let modify_at_version = modified_at_versions.into_iter().collect::<BTreeMap<_, _>>();
27
28    for ((object_id, version, digest), owner, kind) in all_changed_objects {
29        let o = object_provider.get_object(&object_id, &version).await?;
30        if let Some(type_) = o.type_() {
31            let object_type = type_.clone().into();
32
33            match kind {
34                WriteKind::Mutate => object_changes.push(ObjectChange::Mutated {
35                    sender,
36                    owner,
37                    object_type,
38                    object_id,
39                    version,
40                    // modify_at_version should always be available for mutated object
41                    previous_version: modify_at_version
42                        .get(&object_id)
43                        .cloned()
44                        .unwrap_or_default(),
45                    digest,
46                }),
47                WriteKind::Create => object_changes.push(ObjectChange::Created {
48                    sender,
49                    owner,
50                    object_type,
51                    object_id,
52                    version,
53                    digest,
54                }),
55                _ => {}
56            }
57        } else if let Some(p) = o.data.try_as_package() {
58            if kind == WriteKind::Create {
59                object_changes.push(ObjectChange::Published {
60                    package_id: p.id(),
61                    version: p.version(),
62                    digest,
63                    modules: p.serialized_module_map().keys().cloned().collect(),
64                })
65            }
66        };
67    }
68
69    for ((id, version, _), kind) in all_removed_objects {
70        let o = object_provider
71            .find_object_lt_or_eq_version(&id, &version)
72            .await?;
73        if let Some(o) = o {
74            if let Some(type_) = o.type_() {
75                let object_type = type_.clone().into();
76                match kind {
77                    ObjectRemoveKind::Delete => object_changes.push(ObjectChange::Deleted {
78                        sender,
79                        object_type,
80                        object_id: id,
81                        version,
82                    }),
83                    ObjectRemoveKind::Wrap => object_changes.push(ObjectChange::Wrapped {
84                        sender,
85                        object_type,
86                        object_id: id,
87                        version,
88                    }),
89                }
90            }
91        };
92    }
93
94    Ok(object_changes)
95}