iota_graphql_rpc/types/
object_change.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use async_graphql::*;
6use iota_types::effects::{IDOperation, ObjectChange as NativeObjectChange};
7
8use crate::types::{iota_address::IotaAddress, object::Object};
9
10/// Represents the source of an object change (derived from transaction kind)
11#[derive(Clone, Debug)]
12pub(crate) enum ObjectChangeSource {
13    /// Object change from a checkpointed transaction
14    Checkpointed,
15    /// Object change from an executed (not yet checkpointed) transaction
16    Executed,
17    /// Object change from a dry run transaction (dryRunTransactionBlock)
18    DryRun,
19}
20
21pub(crate) struct ObjectChange {
22    pub native: NativeObjectChange,
23    /// The checkpoint sequence number this was viewed at.
24    pub checkpoint_viewed_at: u64,
25    /// The source of this object change (derived from transaction kind)
26    pub source: ObjectChangeSource,
27}
28
29/// Effect on an individual Object (keyed by its ID).
30#[Object]
31impl ObjectChange {
32    /// The address of the object that has changed.
33    async fn address(&self) -> IotaAddress {
34        self.native.id.into()
35    }
36
37    /// The contents of the object immediately before the transaction.
38    async fn input_state(&self, ctx: &Context<'_>) -> Result<Option<Object>> {
39        let Some(version) = self.native.input_version else {
40            return Ok(None);
41        };
42
43        let object_lookup = match self.source {
44            ObjectChangeSource::Executed => Object::at_optimistic_version(version.value()),
45            ObjectChangeSource::Checkpointed | ObjectChangeSource::DryRun => {
46                Object::at_version(version.value(), self.checkpoint_viewed_at)
47            }
48        };
49        Object::query(ctx, self.native.id.into(), object_lookup)
50            .await
51            .extend()
52    }
53
54    /// The contents of the object immediately after the transaction.
55    async fn output_state(&self, ctx: &Context<'_>) -> Result<Option<Object>> {
56        let Some(version) = self.native.output_version else {
57            return Ok(None);
58        };
59
60        let object_lookup = match self.source {
61            ObjectChangeSource::Executed => Object::at_optimistic_version(version.value()),
62            ObjectChangeSource::Checkpointed | ObjectChangeSource::DryRun => {
63                Object::at_version(version.value(), self.checkpoint_viewed_at)
64            }
65        };
66        Object::query(ctx, self.native.id.into(), object_lookup)
67            .await
68            .extend()
69    }
70
71    /// Whether the ID was created in this transaction.
72    async fn id_created(&self) -> Option<bool> {
73        Some(self.native.id_operation == IDOperation::Created)
74    }
75
76    /// Whether the ID was deleted in this transaction.
77    async fn id_deleted(&self) -> Option<bool> {
78        Some(self.native.id_operation == IDOperation::Deleted)
79    }
80}