radix_engine_interface/blueprints/resource/
resource.rs

1use 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    /// The total amount.
19    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        // update liquidity
51        // NOTE: Decimal arithmetic operation safe unwrap.
52        // Mint limit should prevent from overflowing
53        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        // deduct from liquidity pool
61        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    /// The total non-fungible ids.
89    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    /// The locked amounts and the corresponding times of being locked.
157    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    /// The locked non-fungible ids and the corresponding times of being locked.
187    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}