radix_engine_interface/blueprints/locker/
invocations.rs

1use crate::blueprints::account::*;
2use crate::blueprints::component::*;
3use crate::blueprints::macros::*;
4use crate::blueprints::resource::*;
5use radix_common::data::manifest::model::*;
6use radix_common::prelude::*;
7
8define_type_marker!(Some(LOCKER_PACKAGE), AccountLocker);
9
10pub const ACCOUNT_LOCKER_BLUEPRINT: &str = "AccountLocker";
11
12//===========
13// Functions
14//===========
15
16define_invocation! {
17    blueprint_name: AccountLocker,
18    function_name: instantiate,
19    input: struct {
20        owner_role: OwnerRole,
21        storer_role: AccessRule,
22        storer_updater_role: AccessRule,
23        recoverer_role: AccessRule,
24        recoverer_updater_role: AccessRule,
25        address_reservation: Option<GlobalAddressReservation>
26    },
27    output: type Global<AccountLockerMarker>,
28    manifest_input: struct {
29        owner_role: ManifestOwnerRole,
30        storer_role: ManifestAccessRule,
31        storer_updater_role: ManifestAccessRule,
32        recoverer_role: ManifestAccessRule,
33        recoverer_updater_role: ManifestAccessRule,
34        address_reservation: Option<ManifestAddressReservation>
35    }
36}
37
38define_invocation! {
39    blueprint_name: AccountLocker,
40    function_name: instantiate_simple,
41    input: struct {
42        allow_recover: bool
43    },
44    output: type (Global<AccountLockerMarker>, Bucket),
45    manifest_input: struct {
46        allow_recover: bool
47    }
48}
49
50//================
51// Storer Methods
52//================
53
54define_invocation! {
55    blueprint_name: AccountLocker,
56    function_name: store,
57    input: struct {
58        claimant: Global<AccountMarker>,
59        bucket: Bucket,
60        try_direct_send: bool
61    },
62    output: type (),
63    manifest_input: struct {
64        claimant: GenericGlobal<ManifestComponentAddress, AccountMarker>,
65        bucket: ManifestBucket,
66        try_direct_send: bool
67    }
68}
69
70define_invocation! {
71    blueprint_name: AccountLocker,
72    function_name: airdrop,
73    input: struct {
74        claimants: IndexMap<Global<AccountMarker>, ResourceSpecifier>,
75        bucket: Bucket,
76        try_direct_send: bool
77    },
78    output: type Option<Bucket>,
79    manifest_input: struct {
80        claimants: IndexMap<GenericGlobal<ManifestComponentAddress, AccountMarker>, ResourceSpecifier>,
81        bucket: ManifestBucket,
82        try_direct_send: bool
83    }
84}
85
86//===================
87// Recoverer Methods
88//===================
89
90define_invocation! {
91    blueprint_name: AccountLocker,
92    function_name: recover,
93    input: struct {
94        claimant: Global<AccountMarker>,
95        resource_address: ResourceAddress,
96        amount: Decimal
97    },
98    output: type Bucket,
99    manifest_input: struct {
100        claimant: GenericGlobal<ManifestComponentAddress, AccountMarker>,
101        resource_address: ManifestResourceAddress,
102        amount: Decimal
103    }
104}
105
106define_invocation! {
107    blueprint_name: AccountLocker,
108    function_name: recover_non_fungibles,
109    input: struct {
110        claimant: Global<AccountMarker>,
111        resource_address: ResourceAddress,
112        ids: IndexSet<NonFungibleLocalId>
113    },
114    output: type Bucket,
115    manifest_input: struct {
116        claimant: GenericGlobal<ManifestComponentAddress, AccountMarker>,
117        resource_address: ManifestResourceAddress,
118        ids: IndexSet<NonFungibleLocalId>
119    }
120}
121
122//=====================
123// Public User Methods
124//=====================
125
126define_invocation! {
127    blueprint_name: AccountLocker,
128    function_name: claim,
129    input: struct {
130        claimant: Global<AccountMarker>,
131        resource_address: ResourceAddress,
132        amount: Decimal
133    },
134    output: type Bucket,
135    manifest_input: struct {
136        claimant: GenericGlobal<ManifestComponentAddress, AccountMarker>,
137        resource_address: ManifestResourceAddress,
138        amount: Decimal
139    }
140}
141
142define_invocation! {
143    blueprint_name: AccountLocker,
144    function_name: claim_non_fungibles,
145    input: struct {
146        claimant: Global<AccountMarker>,
147        resource_address: ResourceAddress,
148        ids: IndexSet<NonFungibleLocalId>
149    },
150    output: type Bucket,
151    manifest_input: struct {
152        claimant: GenericGlobal<ManifestComponentAddress, AccountMarker>,
153        resource_address: ManifestResourceAddress,
154        ids: IndexSet<NonFungibleLocalId>
155    }
156}
157
158//================
159// Getter Methods
160//================
161
162define_invocation! {
163    blueprint_name: AccountLocker,
164    function_name: get_amount,
165    input: struct {
166        claimant: Global<AccountMarker>,
167        resource_address: ResourceAddress,
168    },
169    output: type Decimal,
170    manifest_input: struct {
171        claimant: GenericGlobal<ManifestComponentAddress, AccountMarker>,
172        resource_address: DynamicResourceAddress,
173    }
174}
175
176define_invocation! {
177    blueprint_name: AccountLocker,
178    function_name: get_non_fungible_local_ids,
179    input: struct {
180        claimant: Global<AccountMarker>,
181        resource_address: ResourceAddress,
182        limit: u32
183    },
184    output: type IndexSet<NonFungibleLocalId>,
185    manifest_input: struct {
186        claimant: GenericGlobal<ManifestComponentAddress, AccountMarker>,
187        resource_address: ManifestResourceAddress,
188        limit: u32
189    }
190}
191
192//==================
193// Additional Types
194//==================
195
196#[derive(Clone, Debug, ScryptoSbor, ManifestSbor, PartialEq, Eq)]
197pub enum ResourceSpecifier {
198    Fungible(Decimal),
199    NonFungible(IndexSet<NonFungibleLocalId>),
200}
201
202impl ResourceSpecifier {
203    pub fn new_empty(resource_address: ResourceAddress) -> Self {
204        if resource_address.is_fungible() {
205            Self::Fungible(Default::default())
206        } else {
207            Self::NonFungible(Default::default())
208        }
209    }
210
211    pub fn checked_add(&self, other: &Self) -> Option<Self> {
212        match (self, other) {
213            (ResourceSpecifier::Fungible(amount1), ResourceSpecifier::Fungible(amount2)) => amount1
214                .checked_add(*amount2)
215                .map(ResourceSpecifier::Fungible),
216            (ResourceSpecifier::NonFungible(ids1), ResourceSpecifier::NonFungible(ids2)) => Some(
217                ResourceSpecifier::NonFungible(ids1.clone().union(ids2).cloned().collect()),
218            ),
219            (ResourceSpecifier::Fungible(_), ResourceSpecifier::NonFungible(_))
220            | (ResourceSpecifier::NonFungible(_), ResourceSpecifier::Fungible(_)) => None,
221        }
222    }
223
224    pub fn checked_sub(&self, other: &Self) -> Option<Self> {
225        match (self, other) {
226            (ResourceSpecifier::Fungible(amount1), ResourceSpecifier::Fungible(amount2)) => {
227                // Ensure that amount 2 is smaller than or equal to amount 1
228                if amount2 <= amount1 {
229                    amount1.checked_sub(*amount2).map(Self::Fungible)
230                } else {
231                    None
232                }
233            }
234            (ResourceSpecifier::NonFungible(ids1), ResourceSpecifier::NonFungible(ids2)) => {
235                // Ensure that ids2 is a subset of ids1
236                if ids2.is_subset(ids1) {
237                    Some(Self::NonFungible(
238                        ids1.clone().difference(ids2).cloned().collect(),
239                    ))
240                } else {
241                    None
242                }
243            }
244            (ResourceSpecifier::Fungible(_), ResourceSpecifier::NonFungible(_))
245            | (ResourceSpecifier::NonFungible(_), ResourceSpecifier::Fungible(_)) => None,
246        }
247    }
248}