radix_engine_interface/blueprints/resource/
resource.rs1use crate::internal_prelude::*;
2use radix_common::data::scrypto::model::*;
3use radix_common::math::*;
4use radix_engine_interface::blueprints::resource::VaultFreezeFlags;
5use sbor::rust::prelude::*;
6
7#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
8pub enum ResourceError {
9 InsufficientBalance { requested: Decimal, actual: Decimal },
10 InvalidTakeAmount,
11 MissingNonFungibleLocalId(NonFungibleLocalId),
12 DecimalOverflow,
13}
14
15#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
16#[sbor(transparent)]
17pub struct LiquidFungibleResource {
18 amount: Decimal,
20}
21
22#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
23#[sbor(transparent)]
24pub struct VaultFrozenFlag {
25 pub frozen: VaultFreezeFlags,
26}
27
28impl Default for VaultFrozenFlag {
29 fn default() -> Self {
30 Self {
31 frozen: VaultFreezeFlags::empty(),
32 }
33 }
34}
35
36impl LiquidFungibleResource {
37 pub fn new(amount: Decimal) -> Self {
38 Self { amount }
39 }
40
41 pub fn amount(&self) -> Decimal {
42 self.amount
43 }
44
45 pub fn is_empty(&self) -> bool {
46 self.amount.is_zero()
47 }
48
49 pub fn put(&mut self, other: LiquidFungibleResource) {
50 self.amount = self.amount.checked_add(other.amount()).expect("Overflow");
54 }
55
56 pub fn take_by_amount(
57 &mut self,
58 amount_to_take: Decimal,
59 ) -> Result<LiquidFungibleResource, ResourceError> {
60 if self.amount < amount_to_take {
62 return Err(ResourceError::InsufficientBalance {
63 requested: amount_to_take,
64 actual: self.amount,
65 });
66 }
67 self.amount = self
68 .amount
69 .checked_sub(amount_to_take)
70 .ok_or(ResourceError::DecimalOverflow)?;
71 Ok(LiquidFungibleResource::new(amount_to_take))
72 }
73
74 pub fn take_all(&mut self) -> LiquidFungibleResource {
75 self.take_by_amount(self.amount())
76 .expect("Take all from `Resource` should not fail")
77 }
78}
79
80impl Default for LiquidFungibleResource {
81 fn default() -> Self {
82 Self::new(Decimal::zero())
83 }
84}
85
86#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
87pub struct LiquidNonFungibleResource {
88 pub ids: IndexSet<NonFungibleLocalId>,
90}
91
92impl LiquidNonFungibleResource {
93 pub fn new(ids: IndexSet<NonFungibleLocalId>) -> Self {
94 Self { ids }
95 }
96
97 pub fn ids(&self) -> &IndexSet<NonFungibleLocalId> {
98 &self.ids
99 }
100
101 pub fn into_ids(self) -> IndexSet<NonFungibleLocalId> {
102 self.ids
103 }
104
105 pub fn amount(&self) -> Decimal {
106 self.ids.len().into()
107 }
108
109 pub fn is_empty(&self) -> bool {
110 self.ids.is_empty()
111 }
112
113 pub fn put(&mut self, other: LiquidNonFungibleResource) -> Result<(), ResourceError> {
114 self.ids.extend(other.ids);
115 Ok(())
116 }
117
118 pub fn take_by_amount(&mut self, n: u32) -> Result<LiquidNonFungibleResource, ResourceError> {
119 if self.ids.len() < n as usize {
120 return Err(ResourceError::InsufficientBalance {
121 actual: Decimal::from(self.ids.len()),
122 requested: Decimal::from(n),
123 });
124 }
125 let ids: IndexSet<NonFungibleLocalId> = self.ids.iter().take(n as usize).cloned().collect();
126 self.take_by_ids(&ids)
127 }
128
129 pub fn take_by_ids(
130 &mut self,
131 ids_to_take: &IndexSet<NonFungibleLocalId>,
132 ) -> Result<LiquidNonFungibleResource, ResourceError> {
133 for id in ids_to_take {
134 if !self.ids.swap_remove(id) {
135 return Err(ResourceError::MissingNonFungibleLocalId(id.clone()));
136 }
137 }
138 Ok(LiquidNonFungibleResource::new(ids_to_take.clone()))
139 }
140
141 pub fn take_all(&mut self) -> LiquidNonFungibleResource {
142 LiquidNonFungibleResource {
143 ids: core::mem::replace(&mut self.ids, indexset!()),
144 }
145 }
146}
147
148impl Default for LiquidNonFungibleResource {
149 fn default() -> Self {
150 Self::new(IndexSet::default())
151 }
152}
153
154#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
155pub struct LockedFungibleResource {
156 pub amounts: IndexMap<Decimal, usize>,
158}
159
160impl LockedFungibleResource {
161 pub fn is_locked(&self) -> bool {
162 !self.amounts.is_empty()
163 }
164
165 pub fn amount(&self) -> Decimal {
166 let mut max = Decimal::ZERO;
167 for amount in self.amounts.keys() {
168 if amount > &max {
169 max = *amount
170 }
171 }
172 max
173 }
174}
175
176impl Default for LockedFungibleResource {
177 fn default() -> Self {
178 Self {
179 amounts: index_map_new(),
180 }
181 }
182}
183
184#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
185pub struct LockedNonFungibleResource {
186 pub ids: IndexMap<NonFungibleLocalId, usize>,
188}
189
190impl LockedNonFungibleResource {
191 pub fn is_locked(&self) -> bool {
192 !self.ids.is_empty()
193 }
194
195 pub fn amount(&self) -> Decimal {
196 self.ids.len().into()
197 }
198
199 pub fn ids(&self) -> IndexSet<NonFungibleLocalId> {
200 self.ids.keys().cloned().collect()
201 }
202}
203
204impl Default for LockedNonFungibleResource {
205 fn default() -> Self {
206 Self {
207 ids: index_map_new(),
208 }
209 }
210}
211
212#[derive(Debug, Clone, PartialEq, Eq, ScryptoSbor)]
213#[sbor(transparent)]
214pub struct LiquidNonFungibleVault {
215 pub amount: Decimal,
216}