iota_types/
derived_object.rs1use move_core_types::{
6 ident_str,
7 identifier::IdentStr,
8 language_storage::{StructTag, TypeTag},
9};
10
11use crate::{
12 IOTA_FRAMEWORK_ADDRESS,
13 base_types::{IotaAddress, ObjectID},
14 dynamic_field,
15};
16
17pub const DERIVED_OBJECT_MODULE_NAME: &IdentStr = ident_str!("derived_object");
18pub const DERIVED_OBJECT_STRUCT_NAME: &IdentStr = ident_str!("DerivedObjectKey");
19
20pub fn derive_object_id<T>(
25 parent: T,
26 key_type_tag: &TypeTag,
27 key_bytes: &[u8],
28) -> Result<ObjectID, bcs::Error>
29where
30 T: Into<IotaAddress>,
31{
32 let parent_address = parent.into();
33
34 let wrapper_type_tag = TypeTag::Struct(Box::new(StructTag {
36 address: IOTA_FRAMEWORK_ADDRESS,
37 module: DERIVED_OBJECT_MODULE_NAME.into(),
38 name: DERIVED_OBJECT_STRUCT_NAME.into(),
39 type_params: vec![key_type_tag.clone()],
40 }));
41
42 dynamic_field::derive_dynamic_field_id(parent_address, &wrapper_type_tag, key_bytes)
43}
44
45#[cfg(test)]
46mod tests {
47 use std::str::FromStr;
48
49 use move_core_types::identifier::Identifier;
50 use serde::Serialize;
51
52 use super::*;
53
54 #[derive(Serialize)]
55 struct DemoStruct {
56 value: u64,
57 }
58
59 #[derive(Serialize)]
60 struct GenericStruct<T> {
61 value: T,
62 }
63
64 #[test]
67 fn test_derive_object_snapshot() {
68 let key_bytes = bcs::to_bytes("foo".as_bytes()).unwrap();
70 let key_type_tag = TypeTag::Vector(Box::new(TypeTag::U8));
71
72 let id = derive_object_id(
73 ObjectID::from_str("0x2").unwrap(),
74 &key_type_tag,
75 &key_bytes,
76 )
77 .unwrap();
78
79 assert_eq!(
80 id,
81 ObjectID::from_str(
82 "0xa2b411aa9588c398d8e3bc97dddbdd430b5ded7f81545d05e33916c3ca0f30c3"
83 )
84 .unwrap()
85 );
86 }
87
88 #[test]
89 fn test_derive_object_with_struct_key_snapshot() {
90 let key = DemoStruct { value: 1 };
91 let key_value = bcs::to_bytes(&key).unwrap();
92
93 let id = derive_object_id(
94 ObjectID::from_str("0x2").unwrap(),
95 &TypeTag::Struct(Box::new(StructTag {
96 address: IOTA_FRAMEWORK_ADDRESS,
97 module: Identifier::new("derived_object_tests").unwrap(),
98 name: Identifier::new("DemoStruct").unwrap(),
99 type_params: vec![],
100 })),
101 &key_value,
102 )
103 .unwrap();
104
105 assert_eq!(
106 id,
107 ObjectID::from_str(
108 "0x20c58d8790a5d2214c159c23f18a5fdc347211e511186353e785ad543abcea6b"
109 )
110 .unwrap()
111 );
112 }
113
114 #[test]
115 fn test_derive_object_with_generic_struct_key_snapshot() {
116 let key = GenericStruct::<u64> { value: 1 };
117 let key_value = bcs::to_bytes(&key).unwrap();
118
119 let id = derive_object_id(
120 ObjectID::from_str("0x2").unwrap(),
121 &TypeTag::Struct(Box::new(StructTag {
122 address: IOTA_FRAMEWORK_ADDRESS,
123 module: Identifier::new("derived_object_tests").unwrap(),
124 name: Identifier::new("GenericStruct").unwrap(),
125 type_params: vec![TypeTag::U64],
126 })),
127 &key_value,
128 )
129 .unwrap();
130
131 assert_eq!(
132 id,
133 ObjectID::from_str(
134 "0xb497b8dcf1e297ae5fa69c040e4a08ef8240d5373bbc9d6b686ffbd7dfe04cbe"
135 )
136 .unwrap()
137 );
138 }
139}