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