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