drive/util/batch/drive_op_batch/
token.rs

1use crate::drive::Drive;
2use crate::error::Error;
3use crate::fees::op::LowLevelDriveOperation;
4use crate::util::batch::drive_op_batch::DriveLowLevelOperationConverter;
5use dpp::balances::credits::TokenAmount;
6use dpp::block::block_info::BlockInfo;
7use dpp::identifier::Identifier;
8use dpp::prelude::{IdentityNonce, TimestampMillis};
9use dpp::tokens::status::TokenStatus;
10use dpp::tokens::token_event::TokenEvent;
11use grovedb::batch::KeyInfoPath;
12use grovedb::{EstimatedLayerInformation, TransactionArg};
13use platform_version::version::PlatformVersion;
14use std::collections::HashMap;
15use dpp::data_contract::associated_token::token_perpetual_distribution::reward_distribution_moment::RewardDistributionMoment;
16use dpp::tokens::token_pricing_schedule::TokenPricingSchedule;
17
18/// Operations on Tokens
19#[derive(Clone, Debug)]
20pub enum TokenOperationType {
21    /// Burns token from the account issuing the action.
22    TokenBurn {
23        /// The token id
24        token_id: Identifier,
25        /// The identity to burn from
26        identity_balance_holder_id: Identifier,
27        /// The amount to burn
28        burn_amount: TokenAmount,
29    },
30    /// Mints tokens
31    TokenMint {
32        /// The token id
33        token_id: Identifier,
34        /// The identity to mint to
35        identity_balance_holder_id: Identifier,
36        /// The amount to issue
37        mint_amount: TokenAmount,
38        /// Should we allow this to be the first ever mint
39        allow_first_mint: bool,
40        /// Should we allow a mint to saturate the upper bounds instead of giving an error?
41        /// For example if we were to add 10 to i64::Max - 5 we would get i64::Max
42        allow_saturation: bool,
43    },
44    /// Mints tokens to many recipients
45    TokenMintMany {
46        /// The token id
47        token_id: Identifier,
48        /// The identities that will receive this amount along with their weight
49        recipients: Vec<(Identifier, u64)>,
50        /// The amount to issue
51        mint_amount: TokenAmount,
52        /// Should we allow this to be the first ever mint
53        allow_first_mint: bool,
54    },
55    /// Marks the perpetual release as distributed
56    /// This removes the references in the queue
57    TokenMarkPerpetualReleaseAsDistributed {
58        /// The token id
59        token_id: Identifier,
60        /// The recipient of this operation, generally the person making the claim state transition
61        recipient_id: Identifier,
62        /// The beginning of the current perpetual release cycle.
63        /// For example if we pay every 10 blocks, and we are on block 54, this would be 50.
64        cycle_start_moment: RewardDistributionMoment,
65    },
66    /// Marks the pre-programmed release as distributed
67    /// This removes the references in the queue
68    TokenMarkPreProgrammedReleaseAsDistributed {
69        /// The token id
70        token_id: Identifier,
71        /// The recipient of this operation, generally the person making the state transition
72        recipient_id: Identifier,
73        /// The last release time, block or epoch
74        release_time: TimestampMillis,
75    },
76    /// Performs a token transfer
77    TokenTransfer {
78        /// The token id
79        token_id: Identifier,
80        /// The token id
81        sender_id: Identifier,
82        /// The recipient of the transfer
83        recipient_id: Identifier,
84        /// The amount to transfer
85        amount: TokenAmount,
86    },
87    /// Freezes an identity's token balance so money can no longer be sent out.
88    TokenFreeze {
89        /// The token id
90        token_id: Identifier,
91        /// The frozen identity id
92        frozen_identity_id: Identifier,
93    },
94    /// Unfreezes an identity's token balance so money can be sent out again.
95    TokenUnfreeze {
96        /// The token id
97        token_id: Identifier,
98        /// The frozen identity id
99        frozen_identity_id: Identifier,
100    },
101    /// Sets the status of the token.
102    TokenSetStatus {
103        /// The token id
104        token_id: Identifier,
105        /// The status
106        status: TokenStatus,
107    },
108    /// Adds a historical document explaining a token action.
109    TokenHistory {
110        /// The token id
111        token_id: Identifier,
112        /// The identity making the event
113        owner_id: Identifier,
114        /// The nonce
115        nonce: IdentityNonce,
116        /// The token event
117        event: TokenEvent,
118    },
119    /// Sets the price of a token for direct purchase
120    TokenSetPriceForDirectPurchase {
121        /// The token id
122        token_id: Identifier,
123        /// The price we are setting to
124        /// None means it's not currently for sale
125        price: Option<TokenPricingSchedule>,
126    },
127}
128
129impl DriveLowLevelOperationConverter for TokenOperationType {
130    fn into_low_level_drive_operations(
131        self,
132        drive: &Drive,
133        estimated_costs_only_with_layer_info: &mut Option<
134            HashMap<KeyInfoPath, EstimatedLayerInformation>,
135        >,
136        block_info: &BlockInfo,
137        transaction: TransactionArg,
138        platform_version: &PlatformVersion,
139    ) -> Result<Vec<LowLevelDriveOperation>, Error> {
140        match self {
141            TokenOperationType::TokenBurn {
142                token_id,
143                identity_balance_holder_id,
144                burn_amount,
145            } => {
146                let token_id_bytes: [u8; 32] = token_id.to_buffer();
147                let identity_id_bytes: [u8; 32] = identity_balance_holder_id.to_buffer();
148                let batch_operations = drive.token_burn_operations(
149                    token_id_bytes,
150                    identity_id_bytes,
151                    burn_amount,
152                    estimated_costs_only_with_layer_info,
153                    transaction,
154                    platform_version,
155                )?;
156                Ok(batch_operations)
157            }
158            TokenOperationType::TokenMint {
159                token_id,
160                identity_balance_holder_id,
161                mint_amount,
162                allow_first_mint,
163                allow_saturation,
164            } => {
165                let token_id_bytes: [u8; 32] = token_id.to_buffer();
166                let identity_id_bytes: [u8; 32] = identity_balance_holder_id.to_buffer();
167                let batch_operations = drive.token_mint_operations(
168                    token_id_bytes,
169                    identity_id_bytes,
170                    mint_amount,
171                    allow_first_mint,
172                    allow_saturation,
173                    estimated_costs_only_with_layer_info,
174                    transaction,
175                    platform_version,
176                )?;
177                Ok(batch_operations)
178            }
179            TokenOperationType::TokenMintMany {
180                token_id,
181                recipients,
182                mint_amount,
183                allow_first_mint,
184            } => {
185                let batch_operations = drive.token_mint_many_operations(
186                    token_id,
187                    recipients,
188                    mint_amount,
189                    allow_first_mint,
190                    estimated_costs_only_with_layer_info,
191                    transaction,
192                    platform_version,
193                )?;
194                Ok(batch_operations)
195            }
196            TokenOperationType::TokenTransfer {
197                token_id,
198                sender_id,
199                recipient_id,
200                amount,
201            } => {
202                let token_id_bytes: [u8; 32] = token_id.to_buffer();
203                let sender_id_bytes: [u8; 32] = sender_id.to_buffer();
204                let recipient_id_bytes: [u8; 32] = recipient_id.to_buffer();
205
206                let batch_operations = drive.token_transfer_operations(
207                    token_id_bytes,
208                    sender_id_bytes,
209                    recipient_id_bytes,
210                    amount,
211                    estimated_costs_only_with_layer_info,
212                    transaction,
213                    platform_version,
214                )?;
215                Ok(batch_operations)
216            }
217            TokenOperationType::TokenHistory {
218                token_id,
219                owner_id,
220                nonce,
221                event,
222            } => {
223                let batch_operations = drive.add_token_transaction_history_operations(
224                    token_id,
225                    owner_id,
226                    nonce,
227                    event,
228                    block_info,
229                    estimated_costs_only_with_layer_info,
230                    transaction,
231                    platform_version,
232                )?;
233                Ok(batch_operations)
234            }
235            TokenOperationType::TokenFreeze {
236                token_id,
237                frozen_identity_id,
238            } => {
239                let batch_operations = drive.token_freeze_operations(
240                    token_id,
241                    frozen_identity_id,
242                    estimated_costs_only_with_layer_info,
243                    transaction,
244                    platform_version,
245                )?;
246                Ok(batch_operations)
247            }
248            TokenOperationType::TokenUnfreeze {
249                token_id,
250                frozen_identity_id,
251            } => {
252                let batch_operations = drive.token_unfreeze_operations(
253                    token_id,
254                    frozen_identity_id,
255                    estimated_costs_only_with_layer_info,
256                    transaction,
257                    platform_version,
258                )?;
259                Ok(batch_operations)
260            }
261            TokenOperationType::TokenSetStatus { token_id, status } => {
262                let batch_operations = drive.token_apply_status_operations(
263                    token_id.to_buffer(),
264                    status,
265                    estimated_costs_only_with_layer_info,
266                    platform_version,
267                )?;
268                Ok(batch_operations)
269            }
270            TokenOperationType::TokenMarkPerpetualReleaseAsDistributed {
271                token_id,
272                recipient_id,
273                cycle_start_moment,
274            } => {
275                let batch_operations = drive.mark_perpetual_release_as_distributed_operations(
276                    token_id.to_buffer(),
277                    recipient_id.to_buffer(),
278                    cycle_start_moment,
279                    estimated_costs_only_with_layer_info,
280                    platform_version,
281                )?;
282                Ok(batch_operations)
283            }
284            TokenOperationType::TokenMarkPreProgrammedReleaseAsDistributed {
285                token_id,
286                recipient_id,
287                release_time,
288            } => {
289                let batch_operations = drive
290                    .mark_pre_programmed_release_as_distributed_operations(
291                        token_id.to_buffer(),
292                        recipient_id.to_buffer(),
293                        release_time,
294                        block_info,
295                        estimated_costs_only_with_layer_info,
296                        transaction,
297                        platform_version,
298                    )?;
299                Ok(batch_operations)
300            }
301            TokenOperationType::TokenSetPriceForDirectPurchase { token_id, price } => {
302                let batch_operations = drive.token_set_direct_purchase_price_operations(
303                    token_id.to_buffer(),
304                    price,
305                    estimated_costs_only_with_layer_info,
306                    platform_version,
307                )?;
308                Ok(batch_operations)
309            }
310        }
311    }
312}