radix_native_sdk/resource/
proof.rs

1use radix_common::constants::RESOURCE_PACKAGE;
2use radix_common::data::scrypto::model::*;
3use radix_common::data::scrypto::{scrypto_decode, scrypto_encode};
4use radix_common::math::Decimal;
5use radix_engine_interface::api::*;
6use radix_engine_interface::blueprints::resource::*;
7use radix_engine_interface::types::*;
8use sbor::rust::collections::IndexSet;
9
10use super::ResourceManager;
11
12// TODO: Move the fungible/non-fungible parts out of NativeProof,
13//       and require the user opt in with `as_fungible` / `as_non_fungible` like in Scrypto.
14//       This will be a breaking change, so likely need some communication.
15
16pub trait NativeProof {
17    type ResourceManager;
18
19    fn amount<Y: SystemObjectApi<E>, E: SystemApiError>(&self, api: &mut Y) -> Result<Decimal, E>;
20
21    fn resource_address<Y: SystemObjectApi<E>, E: SystemApiError>(
22        &self,
23        api: &mut Y,
24    ) -> Result<ResourceAddress, E>;
25
26    fn resource_manager<Y: SystemObjectApi<E>, E: SystemApiError>(
27        &self,
28        api: &mut Y,
29    ) -> Result<Self::ResourceManager, E>;
30
31    fn clone<Y: SystemObjectApi<E>, E: SystemApiError>(&self, api: &mut Y) -> Result<Proof, E>;
32
33    fn drop<Y: SystemApi<E>, E: SystemApiError>(self, api: &mut Y) -> Result<(), E>;
34}
35
36pub trait NativeFungibleProof {}
37
38pub trait NativeNonFungibleProof {
39    fn non_fungible_local_ids<Y: SystemObjectApi<E>, E: SystemApiError>(
40        &self,
41        api: &mut Y,
42    ) -> Result<IndexSet<NonFungibleLocalId>, E>;
43}
44
45impl NativeProof for Proof {
46    type ResourceManager = ResourceManager;
47
48    fn amount<Y: SystemObjectApi<E>, E: SystemApiError>(&self, api: &mut Y) -> Result<Decimal, E> {
49        let rtn = api.call_method(
50            self.0.as_node_id(),
51            PROOF_GET_AMOUNT_IDENT,
52            scrypto_encode(&ProofGetAmountInput {}).unwrap(),
53        )?;
54        Ok(scrypto_decode(&rtn).unwrap())
55    }
56
57    fn resource_address<Y: SystemObjectApi<E>, E: SystemApiError>(
58        &self,
59        api: &mut Y,
60    ) -> Result<ResourceAddress, E> {
61        let address = api.get_outer_object(self.0.as_node_id())?;
62        Ok(ResourceAddress::try_from(address).unwrap())
63    }
64
65    fn resource_manager<Y: SystemObjectApi<E>, E: SystemApiError>(
66        &self,
67        api: &mut Y,
68    ) -> Result<ResourceManager, E> {
69        Ok(ResourceManager(self.resource_address(api)?))
70    }
71
72    fn clone<Y: SystemObjectApi<E>, E: SystemApiError>(&self, api: &mut Y) -> Result<Proof, E> {
73        let rtn = api.call_method(
74            self.0.as_node_id(),
75            PROOF_CLONE_IDENT,
76            scrypto_encode(&ProofCloneInput {}).unwrap(),
77        )?;
78        Ok(scrypto_decode(&rtn).unwrap())
79    }
80
81    fn drop<Y: SystemObjectApi<E> + SystemBlueprintApi<E>, E: SystemApiError>(
82        self,
83        api: &mut Y,
84    ) -> Result<(), E> {
85        let blueprint_id = api.get_blueprint_id(self.0.as_node_id())?;
86        api.call_function(
87            RESOURCE_PACKAGE,
88            blueprint_id.blueprint_name.as_str(),
89            PROOF_DROP_IDENT,
90            scrypto_encode(&ProofDropInput {
91                proof: Proof(self.0),
92            })
93            .unwrap(),
94        )?;
95        Ok(())
96    }
97}
98
99pub trait SpecializedProof: AsRef<Proof> + Into<Proof> {
100    type ResourceManager: From<ResourceManager>;
101
102    /// Purposefully not From because we want to only use this when
103    /// we are confident it's the correct type
104    fn from_proof_of_correct_type(proof: Proof) -> Self;
105}
106
107impl SpecializedProof for FungibleProof {
108    // Change when we have a native FungibleResourceManager
109    type ResourceManager = ResourceManager;
110
111    fn from_proof_of_correct_type(proof: Proof) -> Self {
112        Self(proof)
113    }
114}
115
116impl SpecializedProof for NonFungibleProof {
117    // Change when we have a native NonFungibleResourceManager
118    type ResourceManager = ResourceManager;
119
120    fn from_proof_of_correct_type(proof: Proof) -> Self {
121        Self(proof)
122    }
123}
124
125impl<T: SpecializedProof> NativeProof for T {
126    type ResourceManager = <Self as SpecializedProof>::ResourceManager;
127
128    fn amount<Y: SystemObjectApi<E>, E: SystemApiError>(&self, api: &mut Y) -> Result<Decimal, E> {
129        self.as_ref().amount(api)
130    }
131
132    fn resource_address<Y: SystemObjectApi<E>, E: SystemApiError>(
133        &self,
134        api: &mut Y,
135    ) -> Result<ResourceAddress, E> {
136        self.as_ref().resource_address(api)
137    }
138
139    fn resource_manager<Y: SystemObjectApi<E>, E: SystemApiError>(
140        &self,
141        api: &mut Y,
142    ) -> Result<Self::ResourceManager, E> {
143        Ok(ResourceManager(self.resource_address(api)?).into())
144    }
145
146    fn clone<Y: SystemObjectApi<E>, E: SystemApiError>(&self, api: &mut Y) -> Result<Proof, E> {
147        self.as_ref().clone(api)
148    }
149
150    fn drop<Y: SystemApi<E>, E: SystemApiError>(self, api: &mut Y) -> Result<(), E> {
151        self.into().drop(api)
152    }
153}
154
155impl NativeFungibleProof for Proof {}
156
157impl NativeFungibleProof for FungibleProof {}
158
159impl NativeNonFungibleProof for Proof {
160    fn non_fungible_local_ids<Y: SystemObjectApi<E>, E: SystemApiError>(
161        &self,
162        api: &mut Y,
163    ) -> Result<IndexSet<NonFungibleLocalId>, E> {
164        let rtn = api.call_method(
165            self.0.as_node_id(),
166            NON_FUNGIBLE_PROOF_GET_LOCAL_IDS_IDENT,
167            scrypto_encode(&NonFungibleProofGetLocalIdsInput {}).unwrap(),
168        )?;
169        Ok(scrypto_decode(&rtn).unwrap())
170    }
171}
172
173impl NativeNonFungibleProof for NonFungibleProof {
174    fn non_fungible_local_ids<Y: SystemObjectApi<E>, E: SystemApiError>(
175        &self,
176        api: &mut Y,
177    ) -> Result<IndexSet<NonFungibleLocalId>, E> {
178        self.as_ref().non_fungible_local_ids(api)
179    }
180}