sui_json_rpc/
object_changes.rs

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