sui_types/
accumulator_metadata.rs

1// Copyright (c) Mysten Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::{
5    MoveTypeTagTrait, MoveTypeTagTraitGeneric, SUI_ACCUMULATOR_ROOT_OBJECT_ID,
6    SUI_FRAMEWORK_ADDRESS, SUI_FRAMEWORK_PACKAGE_ID,
7    base_types::{ObjectID, SequenceNumber, SuiAddress},
8    collection_types::Bag,
9    dynamic_field::{DynamicFieldKey, DynamicFieldObject},
10    error::SuiResult,
11    object::Object,
12    storage::ChildObjectResolver,
13};
14use move_core_types::{
15    ident_str,
16    identifier::IdentStr,
17    language_storage::{StructTag, TypeTag},
18};
19use serde::{Deserialize, Serialize};
20
21pub const ACCUMULATOR_METADATA_MODULE: &IdentStr = ident_str!("accumulator_metadata");
22pub const ACCUMULATOR_OWNER_KEY_TYPE: &IdentStr = ident_str!("OwnerKey");
23pub const ACCUMULATOR_OWNER_TYPE: &IdentStr = ident_str!("Owner");
24pub const ACCUMULATOR_METADATA_KEY_TYPE: &IdentStr = ident_str!("MetadataKey");
25pub const ACCUMULATOR_METADATA_TYPE: &IdentStr = ident_str!("Metadata");
26
27#[derive(Serialize, Deserialize)]
28pub struct AccumulatorOwner {
29    pub balances: Bag,
30    pub owner: SuiAddress,
31}
32
33impl MoveTypeTagTrait for AccumulatorOwner {
34    fn get_type_tag() -> TypeTag {
35        TypeTag::Struct(Box::new(StructTag {
36            address: SUI_FRAMEWORK_ADDRESS,
37            module: ACCUMULATOR_METADATA_MODULE.to_owned(),
38            name: ACCUMULATOR_OWNER_TYPE.to_owned(),
39            type_params: vec![],
40        }))
41    }
42}
43
44#[derive(Serialize, Deserialize, Debug, Default)]
45pub struct MetadataKey(u8);
46
47impl MoveTypeTagTraitGeneric for MetadataKey {
48    fn get_type_tag(type_params: &[TypeTag]) -> TypeTag {
49        TypeTag::Struct(Box::new(StructTag {
50            address: SUI_FRAMEWORK_PACKAGE_ID.into(),
51            module: ACCUMULATOR_METADATA_MODULE.to_owned(),
52            name: ACCUMULATOR_METADATA_KEY_TYPE.to_owned(),
53            type_params: type_params.to_vec(),
54        }))
55    }
56}
57
58#[derive(Serialize, Deserialize)]
59pub struct AccumulatorMetadata {
60    /// Any per-balance fields we wish to add in the future.
61    fields: Bag,
62}
63
64impl MoveTypeTagTraitGeneric for AccumulatorMetadata {
65    fn get_type_tag(type_params: &[TypeTag]) -> TypeTag {
66        TypeTag::Struct(Box::new(StructTag {
67            address: SUI_FRAMEWORK_ADDRESS,
68            module: ACCUMULATOR_METADATA_MODULE.to_owned(),
69            name: ACCUMULATOR_METADATA_TYPE.to_owned(),
70            type_params: type_params.to_vec(),
71        }))
72    }
73}
74
75#[derive(Serialize, Deserialize, Debug)]
76pub struct OwnerKey {
77    owner: SuiAddress,
78}
79
80impl MoveTypeTagTrait for OwnerKey {
81    fn get_type_tag() -> TypeTag {
82        TypeTag::Struct(Box::new(StructTag {
83            address: SUI_FRAMEWORK_ADDRESS,
84            module: ACCUMULATOR_METADATA_MODULE.to_owned(),
85            name: ACCUMULATOR_OWNER_KEY_TYPE.to_owned(),
86            type_params: vec![],
87        }))
88    }
89}
90
91impl AccumulatorOwner {
92    pub fn type_() -> StructTag {
93        StructTag {
94            address: SUI_FRAMEWORK_ADDRESS,
95            module: ACCUMULATOR_METADATA_MODULE.to_owned(),
96            name: ACCUMULATOR_OWNER_TYPE.to_owned(),
97            type_params: vec![],
98        }
99    }
100
101    pub fn get_object_id(owner: SuiAddress) -> SuiResult<ObjectID> {
102        let key = OwnerKey { owner };
103        DynamicFieldKey(
104            SUI_ACCUMULATOR_ROOT_OBJECT_ID,
105            key,
106            OwnerKey::get_type_tag(),
107        )
108        .object_id()
109    }
110
111    pub fn exists(
112        child_object_resolver: &dyn ChildObjectResolver,
113        version_bound: Option<SequenceNumber>,
114        owner: SuiAddress,
115    ) -> SuiResult<bool> {
116        let key = OwnerKey { owner };
117
118        DynamicFieldKey(
119            SUI_ACCUMULATOR_ROOT_OBJECT_ID,
120            key,
121            OwnerKey::get_type_tag(),
122        )
123        .into_id_with_bound(version_bound.unwrap_or(SequenceNumber::MAX))?
124        .exists(child_object_resolver)
125    }
126
127    pub fn load_object(
128        child_object_resolver: &dyn ChildObjectResolver,
129        root_version: Option<SequenceNumber>,
130        owner: SuiAddress,
131    ) -> SuiResult<Option<Object>> {
132        let key = OwnerKey { owner };
133        Ok(DynamicFieldKey(
134            SUI_ACCUMULATOR_ROOT_OBJECT_ID,
135            key,
136            OwnerKey::get_type_tag(),
137        )
138        .into_id_with_bound(root_version.unwrap_or(SequenceNumber::MAX))?
139        .load_object(child_object_resolver)?
140        .map(|o| o.into_object()))
141    }
142
143    pub fn from_object(object: Object) -> SuiResult<Self> {
144        DynamicFieldObject::<OwnerKey>::new(object).load_value::<Self>()
145    }
146
147    pub fn load(
148        child_object_resolver: &dyn ChildObjectResolver,
149        root_version: Option<SequenceNumber>,
150        owner: SuiAddress,
151    ) -> SuiResult<Option<Self>> {
152        let key = OwnerKey { owner };
153        DynamicFieldKey(
154            SUI_ACCUMULATOR_ROOT_OBJECT_ID,
155            key,
156            OwnerKey::get_type_tag(),
157        )
158        .into_id_with_bound(root_version.unwrap_or(SequenceNumber::MAX))?
159        .load_object(child_object_resolver)?
160        .map(|o| o.load_value::<Self>())
161        .transpose()
162    }
163
164    pub fn metadata_exists(
165        &self,
166        child_object_resolver: &dyn ChildObjectResolver,
167        version_bound: Option<SequenceNumber>,
168        type_: &TypeTag,
169    ) -> SuiResult<bool> {
170        let key = MetadataKey::default();
171        DynamicFieldKey(
172            *self.balances.id.object_id(),
173            key,
174            MetadataKey::get_type_tag(std::slice::from_ref(type_)),
175        )
176        .into_id_with_bound(version_bound.unwrap_or(SequenceNumber::MAX))?
177        .exists(child_object_resolver)
178    }
179
180    pub fn load_metadata(
181        &self,
182        child_object_resolver: &dyn ChildObjectResolver,
183        version_bound: Option<SequenceNumber>,
184        type_: &TypeTag,
185    ) -> SuiResult<Option<AccumulatorMetadata>> {
186        let key = MetadataKey::default();
187        DynamicFieldKey(
188            *self.balances.id.object_id(),
189            key,
190            MetadataKey::get_type_tag(std::slice::from_ref(type_)),
191        )
192        .into_id_with_bound(version_bound.unwrap_or(SequenceNumber::MAX))?
193        .load_object(child_object_resolver)?
194        .map(|o| o.load_value::<AccumulatorMetadata>())
195        .transpose()
196    }
197}