radix_native_sdk/resource/
resource_manager.rs

1use radix_common::constants::RESOURCE_PACKAGE;
2use radix_common::data::scrypto::model::*;
3use radix_common::data::scrypto::{
4    scrypto_decode, scrypto_encode, ScryptoDecode, ScryptoEncode, ScryptoValue,
5};
6use radix_common::math::Decimal;
7use radix_common::traits::NonFungibleData;
8use radix_common::ScryptoSbor;
9use radix_engine_interface::api::*;
10use radix_engine_interface::blueprints::resource::*;
11use radix_engine_interface::object_modules::metadata::MetadataInit;
12use radix_engine_interface::object_modules::ModuleConfig;
13use radix_engine_interface::types::*;
14use sbor::rust::prelude::*;
15
16/// Represents a resource manager.
17#[derive(Debug, PartialEq, Eq, ScryptoSbor, Clone)]
18pub struct ResourceManager(pub ResourceAddress);
19
20impl ResourceManager {
21    pub fn new_fungible<Y: SystemBlueprintApi<E>, E: SystemApiError, M: Into<MetadataInit>>(
22        owner_role: OwnerRole,
23        track_total_supply: bool,
24        divisibility: u8,
25        resource_roles: FungibleResourceRoles,
26        metadata: M,
27        address_reservation: Option<GlobalAddressReservation>,
28        api: &mut Y,
29    ) -> Result<Self, E> {
30        let metadata = ModuleConfig {
31            init: metadata.into(),
32            roles: RoleAssignmentInit::default(),
33        };
34
35        let result = api.call_function(
36            RESOURCE_PACKAGE,
37            FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT,
38            FUNGIBLE_RESOURCE_MANAGER_CREATE_IDENT,
39            scrypto_encode(&FungibleResourceManagerCreateInput {
40                owner_role,
41                track_total_supply,
42                metadata,
43                resource_roles,
44                divisibility,
45                address_reservation,
46            })
47            .unwrap(),
48        )?;
49
50        let resource_address = scrypto_decode(result.as_slice()).unwrap();
51        Ok(ResourceManager(resource_address))
52    }
53
54    #[allow(clippy::too_many_arguments)]
55    pub fn new_fungible_with_initial_supply<
56        Y: SystemBlueprintApi<E>,
57        E: SystemApiError,
58        M: Into<MetadataInit>,
59    >(
60        owner_role: OwnerRole,
61        track_total_supply: bool,
62        divisibility: u8,
63        initial_supply: Decimal,
64        resource_roles: FungibleResourceRoles,
65        metadata: M,
66        address_reservation: Option<GlobalAddressReservation>,
67        api: &mut Y,
68    ) -> Result<(Self, FungibleBucket), E> {
69        let metadata = ModuleConfig {
70            init: metadata.into(),
71            roles: RoleAssignmentInit::default(),
72        };
73
74        let result = api.call_function(
75            RESOURCE_PACKAGE,
76            FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT,
77            FUNGIBLE_RESOURCE_MANAGER_CREATE_WITH_INITIAL_SUPPLY_IDENT,
78            scrypto_encode(&FungibleResourceManagerCreateWithInitialSupplyInput {
79                owner_role,
80                track_total_supply,
81                metadata,
82                resource_roles,
83                divisibility,
84                initial_supply,
85                address_reservation,
86            })
87            .unwrap(),
88        )?;
89        let (resource_address, bucket): (ResourceAddress, FungibleBucket) =
90            scrypto_decode(result.as_slice()).unwrap();
91        Ok((ResourceManager(resource_address), bucket))
92    }
93
94    pub fn new_non_fungible<
95        // NOTE: These are in a non-standard order, but the N is a required explicit parameter,
96        // so we keep them in this order for backwards compatibility for people using TestEnvironment
97        N: NonFungibleData,
98        Y: SystemBlueprintApi<E>,
99        E: SystemApiError,
100        M: Into<MetadataInit>,
101    >(
102        owner_role: OwnerRole,
103        id_type: NonFungibleIdType,
104        track_total_supply: bool,
105        resource_roles: NonFungibleResourceRoles,
106        metadata: M,
107        address_reservation: Option<GlobalAddressReservation>,
108        api: &mut Y,
109    ) -> Result<Self, E> {
110        let metadata = ModuleConfig {
111            init: metadata.into(),
112            roles: RoleAssignmentInit::default(),
113        };
114
115        let non_fungible_schema =
116            NonFungibleDataSchema::new_local_without_self_package_replacement::<N>();
117        let result = api.call_function(
118            RESOURCE_PACKAGE,
119            NON_FUNGIBLE_RESOURCE_MANAGER_BLUEPRINT,
120            NON_FUNGIBLE_RESOURCE_MANAGER_CREATE_IDENT,
121            scrypto_encode(&NonFungibleResourceManagerCreateInput {
122                owner_role,
123                id_type,
124                track_total_supply,
125                non_fungible_schema,
126                resource_roles,
127                metadata,
128                address_reservation,
129            })
130            .unwrap(),
131        )?;
132        let resource_address = scrypto_decode(result.as_slice()).unwrap();
133        Ok(ResourceManager(resource_address))
134    }
135
136    /// Mints non-fungible resources
137    pub fn mint_non_fungible_single_ruid<
138        Y: SystemObjectApi<E>,
139        E: SystemApiError,
140        T: ScryptoEncode,
141    >(
142        &self,
143        data: T,
144        api: &mut Y,
145    ) -> Result<(NonFungibleBucket, NonFungibleLocalId), E> {
146        let value: ScryptoValue = scrypto_decode(&scrypto_encode(&data).unwrap()).unwrap();
147
148        let rtn = api.call_method(
149            self.0.as_node_id(),
150            NON_FUNGIBLE_RESOURCE_MANAGER_MINT_SINGLE_RUID_IDENT,
151            scrypto_encode(&NonFungibleResourceManagerMintSingleRuidInput { entry: value })
152                .unwrap(),
153        )?;
154
155        Ok(scrypto_decode(&rtn).unwrap())
156    }
157
158    /// Mints non-fungible resources
159    pub fn mint_non_fungible<Y: SystemObjectApi<E>, E: SystemApiError, T: ScryptoEncode>(
160        &self,
161        data: IndexMap<NonFungibleLocalId, T>,
162        api: &mut Y,
163    ) -> Result<NonFungibleBucket, E> {
164        let rtn = api.call_method(
165            self.0.as_node_id(),
166            NON_FUNGIBLE_RESOURCE_MANAGER_MINT_IDENT,
167            scrypto_encode(&NonFungibleResourceManagerMintInput {
168                entries: data
169                    .into_iter()
170                    .map(|(key, value)| {
171                        (
172                            key,
173                            (scrypto_decode(&scrypto_encode(&value).unwrap()).unwrap(),),
174                        )
175                    })
176                    .collect(),
177            })
178            .unwrap(),
179        )?;
180
181        Ok(scrypto_decode(&rtn).unwrap())
182    }
183
184    /// Mints fungible resources
185    pub fn mint_fungible<Y: SystemObjectApi<E>, E: SystemApiError>(
186        &mut self,
187        amount: Decimal,
188        api: &mut Y,
189    ) -> Result<FungibleBucket, E> {
190        let rtn = api.call_method(
191            self.0.as_node_id(),
192            FUNGIBLE_RESOURCE_MANAGER_MINT_IDENT,
193            scrypto_encode(&FungibleResourceManagerMintInput { amount }).unwrap(),
194        )?;
195
196        Ok(scrypto_decode(&rtn).unwrap())
197    }
198
199    pub fn get_non_fungible_data<Y: SystemObjectApi<E>, E: SystemApiError, T: ScryptoDecode>(
200        &self,
201        id: NonFungibleLocalId,
202        api: &mut Y,
203    ) -> Result<T, E> {
204        let rtn = api.call_method(
205            self.0.as_node_id(),
206            NON_FUNGIBLE_RESOURCE_MANAGER_GET_NON_FUNGIBLE_IDENT,
207            scrypto_encode(&NonFungibleResourceManagerGetNonFungibleInput { id }).unwrap(),
208        )?;
209
210        let data = scrypto_decode(&rtn).unwrap();
211        Ok(data)
212    }
213
214    pub fn resource_type<Y: SystemObjectApi<E>, E: SystemApiError>(
215        &self,
216        api: &mut Y,
217    ) -> Result<ResourceType, E> {
218        let rtn = api.call_method(
219            self.0.as_node_id(),
220            RESOURCE_MANAGER_GET_RESOURCE_TYPE_IDENT,
221            scrypto_encode(&ResourceManagerGetResourceTypeInput {}).unwrap(),
222        )?;
223
224        Ok(scrypto_decode(&rtn).unwrap())
225    }
226
227    pub fn burn<Y: SystemObjectApi<E>, E: SystemApiError>(
228        &mut self,
229        bucket: impl Into<Bucket>,
230        api: &mut Y,
231    ) -> Result<(), E> {
232        let bucket = bucket.into();
233        let rtn = api.call_method(
234            self.0.as_node_id(),
235            RESOURCE_MANAGER_BURN_IDENT,
236            scrypto_encode(&ResourceManagerBurnInput { bucket }).unwrap(),
237        )?;
238        let _: () = scrypto_decode(&rtn).unwrap();
239        Ok(())
240    }
241
242    pub fn package_burn<Y: SystemObjectApi<E>, E: SystemApiError>(
243        &mut self,
244        bucket: impl Into<Bucket>,
245        api: &mut Y,
246    ) -> Result<(), E> {
247        let bucket = bucket.into();
248        let rtn = api.call_method(
249            self.0.as_node_id(),
250            RESOURCE_MANAGER_PACKAGE_BURN_IDENT,
251            scrypto_encode(&ResourceManagerPackageBurnInput { bucket }).unwrap(),
252        )?;
253        let _: () = scrypto_decode(&rtn).unwrap();
254        Ok(())
255    }
256
257    pub fn total_supply<Y: SystemObjectApi<E>, E: SystemApiError>(
258        &self,
259        api: &mut Y,
260    ) -> Result<Option<Decimal>, E> {
261        let rtn = api.call_method(
262            self.0.as_node_id(),
263            RESOURCE_MANAGER_GET_TOTAL_SUPPLY_IDENT,
264            scrypto_encode(&ResourceManagerGetTotalSupplyInput {}).unwrap(),
265        )?;
266        Ok(scrypto_decode(&rtn).unwrap())
267    }
268
269    pub fn new_empty_fungible_bucket<Y: SystemObjectApi<E>, E: SystemApiError>(
270        &self,
271        api: &mut Y,
272    ) -> Result<FungibleBucket, E> {
273        Ok(FungibleBucket(self.new_empty_bucket(api)?))
274    }
275
276    pub fn new_empty_non_fungible_bucket<Y: SystemObjectApi<E>, E: SystemApiError>(
277        &self,
278        api: &mut Y,
279    ) -> Result<NonFungibleBucket, E> {
280        Ok(NonFungibleBucket(self.new_empty_bucket(api)?))
281    }
282
283    pub fn new_empty_bucket<Y: SystemObjectApi<E>, E: SystemApiError>(
284        &self,
285        api: &mut Y,
286    ) -> Result<Bucket, E> {
287        let rtn = api.call_method(
288            self.0.as_node_id(),
289            RESOURCE_MANAGER_CREATE_EMPTY_BUCKET_IDENT,
290            scrypto_encode(&ResourceManagerCreateEmptyBucketInput {}).unwrap(),
291        )?;
292        Ok(scrypto_decode(&rtn).unwrap())
293    }
294
295    pub fn new_empty_vault<Y: SystemObjectApi<E>, E: SystemApiError>(
296        &self,
297        api: &mut Y,
298    ) -> Result<Own, E> {
299        let rtn = api.call_method(
300            self.0.as_node_id(),
301            RESOURCE_MANAGER_CREATE_EMPTY_VAULT_IDENT,
302            scrypto_encode(&ResourceManagerCreateEmptyVaultInput {}).unwrap(),
303        )?;
304        Ok(scrypto_decode(&rtn).unwrap())
305    }
306}