radix_native_sdk/component/
object.rs

1use crate::modules::metadata::Metadata;
2use crate::modules::role_assignment::RoleAssignment;
3use radix_common::data::scrypto::scrypto_encode;
4use radix_common::prelude::ScryptoEncode;
5use radix_common::types::GlobalAddress;
6use radix_engine_interface::api::*;
7use radix_engine_interface::object_modules::metadata::{
8    MetadataSetInput, MetadataVal, METADATA_SET_IDENT,
9};
10use radix_engine_interface::object_modules::ModuleConfig;
11use radix_engine_interface::prelude::*;
12use radix_engine_interface::types::NodeId;
13use radix_rust::indexmap;
14use sbor::rust::prelude::*;
15use sbor::rust::prelude::{Debug, ToOwned};
16
17#[derive(Debug)]
18pub struct BorrowedObject(pub NodeId);
19
20impl BorrowedObject {
21    pub fn new<T>(node_id: T) -> Self
22    where
23        T: Into<[u8; NodeId::LENGTH]>,
24    {
25        Self(NodeId(node_id.into()))
26    }
27
28    pub fn set_metadata<Y: SystemApi<E>, E: SystemApiError, S: AsRef<str>, V: MetadataVal>(
29        &mut self,
30        key: S,
31        value: V,
32        api: &mut Y,
33    ) -> Result<(), E> {
34        api.call_module_method(
35            &self.0,
36            AttachedModuleId::Metadata,
37            METADATA_SET_IDENT,
38            scrypto_encode(&MetadataSetInput {
39                key: key.as_ref().to_owned(),
40                value: value.to_metadata_value(),
41            })
42            .unwrap(),
43        )?;
44
45        Ok(())
46    }
47}
48
49pub fn globalize_object<Y: SystemApi<E>, E: SystemApiError>(
50    object_id: NodeId,
51    owner_role: OwnerRole,
52    address_reservation: GlobalAddressReservation,
53    main_roles: RoleAssignmentInit,
54    metadata: ModuleConfig<MetadataInit>,
55    api: &mut Y,
56) -> Result<GlobalAddress, E> {
57    let role_assignment = {
58        let roles = indexmap!(
59            ModuleId::Main => main_roles,
60            ModuleId::Metadata => metadata.roles,
61        );
62        RoleAssignment::create(owner_role, roles, api)?.0 .0
63    };
64
65    let metadata = Metadata::create_with_data(metadata.init, api)?.0;
66
67    let address = api.globalize(
68        object_id,
69        indexmap!(
70            AttachedModuleId::RoleAssignment => role_assignment,
71            AttachedModuleId::Metadata => metadata,
72        ),
73        Some(address_reservation),
74    )?;
75
76    Ok(address)
77}
78
79#[allow(clippy::too_many_arguments)]
80pub fn globalize_object_with_inner_object_and_event<
81    Y: SystemApi<E>,
82    E: SystemApiError,
83    V: ScryptoEncode,
84>(
85    object_id: NodeId,
86    owner_role: OwnerRole,
87    address_reservation: GlobalAddressReservation,
88    main_roles: RoleAssignmentInit,
89    metadata: ModuleConfig<MetadataInit>,
90    inner_object_bp: &str,
91    inner_object_fields: IndexMap<FieldIndex, FieldValue>,
92    event_name: &str,
93    event: V,
94    api: &mut Y,
95) -> Result<(GlobalAddress, NodeId), E> {
96    let role_assignment = {
97        let roles = indexmap!(
98            ModuleId::Main => main_roles,
99            ModuleId::Metadata => metadata.roles,
100        );
101        RoleAssignment::create(owner_role, roles, api)?.0 .0
102    };
103    let metadata = Metadata::create_with_data(metadata.init, api)?.0;
104
105    let (address, inner_object) = api
106        .globalize_with_address_and_create_inner_object_and_emit_event(
107            object_id,
108            indexmap!(
109                AttachedModuleId::RoleAssignment => role_assignment,
110                AttachedModuleId::Metadata => metadata,
111            ),
112            address_reservation,
113            inner_object_bp,
114            inner_object_fields,
115            event_name,
116            scrypto_encode(&event).unwrap(),
117        )?;
118
119    Ok((address, inner_object))
120}