radix_engine_interface/api/
object_api.rs

1use crate::api::CollectionIndex;
2use crate::internal_prelude::*;
3use crate::object_modules::metadata::METADATA_BLUEPRINT;
4use crate::object_modules::role_assignment::ROLE_ASSIGNMENT_BLUEPRINT;
5use crate::types::*;
6
7use radix_common::constants::{
8    METADATA_MODULE_PACKAGE, ROLE_ASSIGNMENT_MODULE_PACKAGE, ROYALTY_MODULE_PACKAGE,
9};
10use radix_common::prelude::{scrypto_encode, ScryptoEncode, VersionedScryptoSchema};
11use radix_common::types::*;
12use radix_common::{ManifestSbor, ScryptoSbor};
13use radix_engine_interface::api::FieldIndex;
14use radix_engine_interface::object_modules::royalty::COMPONENT_ROYALTY_BLUEPRINT;
15use sbor::rust::collections::*;
16use sbor::rust::prelude::*;
17use sbor::rust::vec::Vec;
18
19#[repr(u8)]
20#[cfg_attr(
21    feature = "fuzzing",
22    derive(::arbitrary::Arbitrary, ::serde::Serialize, ::serde::Deserialize)
23)]
24#[derive(
25    Debug,
26    Clone,
27    Copy,
28    PartialEq,
29    Eq,
30    Hash,
31    PartialOrd,
32    Ord,
33    FromRepr,
34    EnumIter,
35    ManifestSbor,
36    ScryptoCategorize,
37    ScryptoEncode,
38    ScryptoDecode,
39)]
40pub enum ModuleId {
41    Main,
42    Metadata,
43    Royalty,
44    RoleAssignment,
45}
46
47/// Notes: This is to be deprecated, please use `ModuleId` instead
48pub type ObjectModuleId = ModuleId;
49
50impl Describe<ScryptoCustomTypeKind> for ModuleId {
51    const TYPE_ID: RustTypeId =
52        RustTypeId::WellKnown(well_known_scrypto_custom_types::MODULE_ID_TYPE);
53
54    fn type_data() -> ScryptoTypeData<RustTypeId> {
55        well_known_scrypto_custom_types::module_id_type_data()
56    }
57}
58
59impl From<Option<AttachedModuleId>> for ModuleId {
60    fn from(value: Option<AttachedModuleId>) -> Self {
61        match value {
62            None => ModuleId::Main,
63            Some(AttachedModuleId::Metadata) => ModuleId::Metadata,
64            Some(AttachedModuleId::Royalty) => ModuleId::Royalty,
65            Some(AttachedModuleId::RoleAssignment) => ModuleId::RoleAssignment,
66        }
67    }
68}
69
70impl From<ModuleId> for Option<AttachedModuleId> {
71    fn from(val: ModuleId) -> Self {
72        match val {
73            ModuleId::Main => None,
74            ModuleId::Metadata => Some(AttachedModuleId::Metadata),
75            ModuleId::Royalty => Some(AttachedModuleId::Royalty),
76            ModuleId::RoleAssignment => Some(AttachedModuleId::RoleAssignment),
77        }
78    }
79}
80
81impl ModuleId {
82    pub fn base_partition_num(&self) -> PartitionNumber {
83        match self {
84            ModuleId::Metadata => METADATA_BASE_PARTITION,
85            ModuleId::Royalty => ROYALTY_BASE_PARTITION,
86            ModuleId::RoleAssignment => ROLE_ASSIGNMENT_BASE_PARTITION,
87            ModuleId::Main => MAIN_BASE_PARTITION,
88        }
89    }
90
91    pub fn static_blueprint(&self) -> Option<BlueprintId> {
92        match self {
93            ModuleId::Metadata => Some(BlueprintId::new(
94                &METADATA_MODULE_PACKAGE,
95                METADATA_BLUEPRINT,
96            )),
97            ModuleId::Royalty => Some(BlueprintId::new(
98                &ROYALTY_MODULE_PACKAGE,
99                COMPONENT_ROYALTY_BLUEPRINT,
100            )),
101            ModuleId::RoleAssignment => Some(BlueprintId::new(
102                &ROLE_ASSIGNMENT_MODULE_PACKAGE,
103                ROLE_ASSIGNMENT_BLUEPRINT,
104            )),
105            ModuleId::Main => None,
106        }
107    }
108}
109
110#[repr(u8)]
111#[cfg_attr(
112    feature = "fuzzing",
113    derive(::arbitrary::Arbitrary, ::serde::Serialize, ::serde::Deserialize)
114)]
115#[derive(
116    Debug,
117    Clone,
118    Copy,
119    PartialEq,
120    Eq,
121    Hash,
122    PartialOrd,
123    Ord,
124    FromRepr,
125    EnumIter,
126    ManifestSbor,
127    ScryptoCategorize,
128    ScryptoEncode,
129    ScryptoDecode,
130)]
131#[sbor(use_repr_discriminators)]
132pub enum AttachedModuleId {
133    Metadata = 1,
134    Royalty = 2,
135    RoleAssignment = 3,
136}
137
138impl Describe<ScryptoCustomTypeKind> for AttachedModuleId {
139    const TYPE_ID: RustTypeId =
140        RustTypeId::WellKnown(well_known_scrypto_custom_types::ATTACHED_MODULE_ID_TYPE);
141
142    fn type_data() -> ScryptoTypeData<RustTypeId> {
143        well_known_scrypto_custom_types::attached_module_id_type_data()
144    }
145}
146
147impl AttachedModuleId {
148    pub fn static_blueprint(&self) -> BlueprintId {
149        match self {
150            AttachedModuleId::Metadata => {
151                BlueprintId::new(&METADATA_MODULE_PACKAGE, METADATA_BLUEPRINT)
152            }
153            AttachedModuleId::Royalty => {
154                BlueprintId::new(&ROYALTY_MODULE_PACKAGE, COMPONENT_ROYALTY_BLUEPRINT)
155            }
156            AttachedModuleId::RoleAssignment => {
157                BlueprintId::new(&ROLE_ASSIGNMENT_MODULE_PACKAGE, ROLE_ASSIGNMENT_BLUEPRINT)
158            }
159        }
160    }
161}
162
163impl From<AttachedModuleId> for ModuleId {
164    fn from(val: AttachedModuleId) -> Self {
165        match val {
166            AttachedModuleId::Metadata => ModuleId::Metadata,
167            AttachedModuleId::Royalty => ModuleId::Royalty,
168            AttachedModuleId::RoleAssignment => ModuleId::RoleAssignment,
169        }
170    }
171}
172
173#[cfg_attr(feature = "fuzzing", derive(::arbitrary::Arbitrary))]
174#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, ScryptoSbor)]
175pub struct FieldValue {
176    pub value: Vec<u8>,
177    pub locked: bool,
178}
179
180impl FieldValue {
181    pub fn new<E: ScryptoEncode>(value: E) -> Self {
182        Self {
183            value: scrypto_encode(&value).unwrap(),
184            locked: false,
185        }
186    }
187
188    pub fn immutable<E: ScryptoEncode>(value: E) -> Self {
189        Self {
190            value: scrypto_encode(&value).unwrap(),
191            locked: true,
192        }
193    }
194}
195
196#[derive(Default, Debug, Clone, PartialEq, Eq, ScryptoSbor)]
197pub struct GenericArgs {
198    pub additional_schema: Option<VersionedScryptoSchema>,
199    pub generic_substitutions: Vec<GenericSubstitution>,
200}
201
202pub struct KVEntry {
203    pub value: Option<Vec<u8>>,
204    pub locked: bool,
205}
206
207/// A high level interface to manipulate objects in the actor's call frame
208pub trait SystemObjectApi<E> {
209    /// Creates a new simple blueprint object of a given blueprint type
210    fn new_simple_object(
211        &mut self,
212        blueprint_ident: &str,
213        fields: IndexMap<FieldIndex, FieldValue>,
214    ) -> Result<NodeId, E> {
215        self.new_object(
216            blueprint_ident,
217            vec![],
218            GenericArgs::default(),
219            fields,
220            indexmap![],
221        )
222    }
223
224    /// Creates a new object of a given blueprint type
225    fn new_object(
226        &mut self,
227        blueprint_ident: &str,
228        features: Vec<&str>,
229        generic_args: GenericArgs,
230        fields: IndexMap<FieldIndex, FieldValue>,
231        kv_entries: IndexMap<CollectionIndex, IndexMap<Vec<u8>, KVEntry>>,
232    ) -> Result<NodeId, E>;
233
234    /// Drops an owned object, returns the fields of the object
235    fn drop_object(&mut self, node_id: &NodeId) -> Result<Vec<Vec<u8>>, E>;
236
237    /// Get the blueprint id of a visible object
238    fn get_blueprint_id(&mut self, node_id: &NodeId) -> Result<BlueprintId, E>;
239
240    /// Get the outer object of a visible object
241    fn get_outer_object(&mut self, node_id: &NodeId) -> Result<GlobalAddress, E>;
242
243    /// Allocates a global address, for a future globalization.
244    fn allocate_global_address(
245        &mut self,
246        blueprint_id: BlueprintId,
247    ) -> Result<(GlobalAddressReservation, GlobalAddress), E>;
248
249    /// Allocates a specific virtual global address
250    fn allocate_virtual_global_address(
251        &mut self,
252        blueprint_id: BlueprintId,
253        global_address: GlobalAddress,
254    ) -> Result<GlobalAddressReservation, E>;
255
256    /// Retrieve the global address of a given address reservation
257    fn get_reservation_address(&mut self, node_id: &NodeId) -> Result<GlobalAddress, E>;
258
259    /// Moves an object currently in the heap into the global space making
260    /// it accessible to all with the provided global address.
261    fn globalize(
262        &mut self,
263        node_id: NodeId,
264        modules: IndexMap<AttachedModuleId, NodeId>,
265        address_reservation: Option<GlobalAddressReservation>,
266    ) -> Result<GlobalAddress, E>;
267
268    /// Globalizes with a new inner object and emits an event
269    #[allow(clippy::too_many_arguments)]
270    fn globalize_with_address_and_create_inner_object_and_emit_event(
271        &mut self,
272        node_id: NodeId,
273        modules: IndexMap<AttachedModuleId, NodeId>,
274        address_reservation: GlobalAddressReservation,
275        inner_object_blueprint: &str,
276        inner_object_fields: IndexMap<u8, FieldValue>,
277        event_name: &str,
278        event_data: Vec<u8>,
279    ) -> Result<(GlobalAddress, NodeId), E>;
280
281    /// Calls a method on an object
282    fn call_method(
283        &mut self,
284        receiver: &NodeId,
285        method_name: &str,
286        args: Vec<u8>,
287    ) -> Result<Vec<u8>, E>;
288
289    /// Calls a direct access method on an object
290    fn call_direct_access_method(
291        &mut self,
292        receiver: &NodeId,
293        method_name: &str,
294        args: Vec<u8>,
295    ) -> Result<Vec<u8>, E>;
296
297    /// Calls a method on an object module
298    fn call_module_method(
299        &mut self,
300        receiver: &NodeId,
301        module_id: AttachedModuleId,
302        method_name: &str,
303        args: Vec<u8>,
304    ) -> Result<Vec<u8>, E>;
305}