referrerpolicy=no-referrer-when-downgrade

pallet_nfts/
types.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! This module contains various basic types and data structures used in the NFTs pallet.
19
20use super::*;
21use crate::macros::*;
22use alloc::{vec, vec::Vec};
23use codec::{DecodeWithMemTracking, EncodeLike};
24use enumflags2::{bitflags, BitFlags};
25use frame_support::{
26	pallet_prelude::{BoundedVec, MaxEncodedLen},
27	traits::Get,
28	BoundedBTreeMap, BoundedBTreeSet,
29};
30use scale_info::{build::Fields, meta_type, Path, Type, TypeInfo, TypeParameter};
31
32pub type BlockNumberFor<T, I = ()> =
33	<<T as Config<I>>::BlockNumberProvider as BlockNumberProvider>::BlockNumber;
34
35/// A type alias for handling balance deposits.
36pub type DepositBalanceOf<T, I = ()> =
37	<<T as Config<I>>::Currency as Currency<<T as SystemConfig>::AccountId>>::Balance;
38/// A type alias representing the details of a collection.
39pub type CollectionDetailsFor<T, I> =
40	CollectionDetails<<T as SystemConfig>::AccountId, DepositBalanceOf<T, I>>;
41/// A type alias for keeping track of approvals used by a single item.
42pub type ApprovalsOf<T, I = ()> = BoundedBTreeMap<
43	<T as SystemConfig>::AccountId,
44	Option<BlockNumberFor<T, I>>,
45	<T as Config<I>>::ApprovalsLimit,
46>;
47/// A type alias for keeping track of approvals for an item's attributes.
48pub type ItemAttributesApprovals<T, I = ()> =
49	BoundedBTreeSet<<T as SystemConfig>::AccountId, <T as Config<I>>::ItemAttributesApprovalsLimit>;
50/// A type that holds the deposit for a single item.
51pub type ItemDepositOf<T, I> = ItemDeposit<DepositBalanceOf<T, I>, <T as SystemConfig>::AccountId>;
52/// A type that holds the deposit amount for an item's attribute.
53pub type AttributeDepositOf<T, I> =
54	AttributeDeposit<DepositBalanceOf<T, I>, <T as SystemConfig>::AccountId>;
55/// A type that holds the deposit amount for an item's metadata.
56pub type ItemMetadataDepositOf<T, I> =
57	ItemMetadataDeposit<DepositBalanceOf<T, I>, <T as SystemConfig>::AccountId>;
58/// A type that holds the details of a single item.
59pub type ItemDetailsFor<T, I> =
60	ItemDetails<<T as SystemConfig>::AccountId, ItemDepositOf<T, I>, ApprovalsOf<T, I>>;
61/// A type alias for an accounts balance.
62pub type BalanceOf<T, I = ()> =
63	<<T as Config<I>>::Currency as Currency<<T as SystemConfig>::AccountId>>::Balance;
64/// A type alias to represent the price of an item.
65pub type ItemPrice<T, I = ()> = BalanceOf<T, I>;
66/// A type alias for the tips held by a single item.
67pub type ItemTipOf<T, I = ()> = ItemTip<
68	<T as Config<I>>::CollectionId,
69	<T as Config<I>>::ItemId,
70	<T as SystemConfig>::AccountId,
71	BalanceOf<T, I>,
72>;
73/// A type alias for the settings configuration of a collection.
74pub type CollectionConfigFor<T, I = ()> =
75	CollectionConfig<BalanceOf<T, I>, BlockNumberFor<T, I>, <T as Config<I>>::CollectionId>;
76/// A type alias for the pre-signed minting configuration for a specified collection.
77pub type PreSignedMintOf<T, I = ()> = PreSignedMint<
78	<T as Config<I>>::CollectionId,
79	<T as Config<I>>::ItemId,
80	<T as SystemConfig>::AccountId,
81	BlockNumberFor<T, I>,
82	BalanceOf<T, I>,
83>;
84/// A type alias for the pre-signed minting configuration on the attribute level of an item.
85pub type PreSignedAttributesOf<T, I = ()> = PreSignedAttributes<
86	<T as Config<I>>::CollectionId,
87	<T as Config<I>>::ItemId,
88	<T as SystemConfig>::AccountId,
89	BlockNumberFor<T, I>,
90>;
91
92/// Information about a collection.
93#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo, MaxEncodedLen)]
94pub struct CollectionDetails<AccountId, DepositBalance> {
95	/// Collection's owner.
96	pub owner: AccountId,
97	/// The total balance deposited by the owner for all the storage data associated with this
98	/// collection. Used by `destroy`.
99	pub owner_deposit: DepositBalance,
100	/// The total number of outstanding items of this collection.
101	pub items: u32,
102	/// The total number of outstanding item metadata of this collection.
103	pub item_metadatas: u32,
104	/// The total number of outstanding item configs of this collection.
105	pub item_configs: u32,
106	/// The total number of attributes for this collection.
107	pub attributes: u32,
108}
109
110/// Witness data for the destroy transactions.
111#[derive(
112	Copy,
113	Clone,
114	Encode,
115	Decode,
116	DecodeWithMemTracking,
117	Eq,
118	PartialEq,
119	Debug,
120	TypeInfo,
121	MaxEncodedLen,
122)]
123pub struct DestroyWitness {
124	/// The total number of items in this collection that have outstanding item metadata.
125	#[codec(compact)]
126	pub item_metadatas: u32,
127	/// The total number of outstanding item configs of this collection.
128	#[codec(compact)]
129	pub item_configs: u32,
130	/// The total number of attributes for this collection.
131	#[codec(compact)]
132	pub attributes: u32,
133}
134
135impl<AccountId, DepositBalance> CollectionDetails<AccountId, DepositBalance> {
136	pub fn destroy_witness(&self) -> DestroyWitness {
137		DestroyWitness {
138			item_metadatas: self.item_metadatas,
139			item_configs: self.item_configs,
140			attributes: self.attributes,
141		}
142	}
143}
144
145/// Witness data for items mint transactions.
146#[derive(Clone, Encode, Decode, DecodeWithMemTracking, Default, Eq, PartialEq, Debug, TypeInfo)]
147pub struct MintWitness<ItemId, Balance> {
148	/// Provide the id of the item in a required collection.
149	pub owned_item: Option<ItemId>,
150	/// The price specified in mint settings.
151	pub mint_price: Option<Balance>,
152}
153
154/// Information concerning the ownership of a single unique item.
155#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug, Default, TypeInfo, MaxEncodedLen)]
156pub struct ItemDetails<AccountId, Deposit, Approvals> {
157	/// The owner of this item.
158	pub owner: AccountId,
159	/// The approved transferrer of this item, if one is set.
160	pub approvals: Approvals,
161	/// The amount held in the pallet's default account for this item. Free-hold items will have
162	/// this as zero.
163	pub deposit: Deposit,
164}
165
166/// Information about the reserved item deposit.
167#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo, MaxEncodedLen)]
168pub struct ItemDeposit<DepositBalance, AccountId> {
169	/// A depositor account.
170	pub account: AccountId,
171	/// An amount that gets reserved.
172	pub amount: DepositBalance,
173}
174
175/// Information about the collection's metadata.
176#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug, Default, TypeInfo, MaxEncodedLen)]
177#[scale_info(skip_type_params(StringLimit))]
178#[codec(mel_bound(Deposit: MaxEncodedLen))]
179pub struct CollectionMetadata<Deposit, StringLimit: Get<u32>> {
180	/// The balance deposited for this metadata.
181	///
182	/// This pays for the data stored in this struct.
183	pub deposit: Deposit,
184	/// General information concerning this collection. Limited in length by `StringLimit`. This
185	/// will generally be either a JSON dump or the hash of some JSON which can be found on a
186	/// hash-addressable global publication system such as IPFS.
187	pub data: BoundedVec<u8, StringLimit>,
188}
189
190/// Information about the item's metadata.
191#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug, Default, TypeInfo, MaxEncodedLen)]
192#[scale_info(skip_type_params(StringLimit))]
193pub struct ItemMetadata<Deposit, StringLimit: Get<u32>> {
194	/// The balance deposited for this metadata.
195	///
196	/// This pays for the data stored in this struct.
197	pub deposit: Deposit,
198	/// General information concerning this item. Limited in length by `StringLimit`. This will
199	/// generally be either a JSON dump or the hash of some JSON which can be found on
200	/// hash-addressable global publication system such as IPFS.
201	pub data: BoundedVec<u8, StringLimit>,
202}
203
204/// Information about the tip.
205#[derive(
206	Clone, Encode, Decode, DecodeWithMemTracking, Eq, PartialEq, Debug, TypeInfo, MaxEncodedLen,
207)]
208pub struct ItemTip<CollectionId, ItemId, AccountId, Amount> {
209	/// The collection of the item.
210	pub collection: CollectionId,
211	/// An item of which the tip is sent for.
212	pub item: ItemId,
213	/// A sender of the tip.
214	pub receiver: AccountId,
215	/// An amount the sender is willing to tip.
216	pub amount: Amount,
217}
218
219/// Information about the pending swap.
220#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug, Default, TypeInfo, MaxEncodedLen)]
221pub struct PendingSwap<CollectionId, ItemId, ItemPriceWithDirection, Deadline> {
222	/// The collection that contains the item that the user wants to receive.
223	pub desired_collection: CollectionId,
224	/// The item the user wants to receive.
225	pub desired_item: Option<ItemId>,
226	/// A price for the desired `item` with the direction.
227	pub price: Option<ItemPriceWithDirection>,
228	/// A deadline for the swap.
229	pub deadline: Deadline,
230}
231
232/// Information about the reserved attribute deposit.
233#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo, MaxEncodedLen)]
234pub struct AttributeDeposit<DepositBalance, AccountId> {
235	/// A depositor account.
236	pub account: Option<AccountId>,
237	/// An amount that gets reserved.
238	pub amount: DepositBalance,
239}
240
241/// Information about the reserved item's metadata deposit.
242#[derive(Clone, Encode, Decode, Eq, PartialEq, Debug, TypeInfo, MaxEncodedLen)]
243pub struct ItemMetadataDeposit<DepositBalance, AccountId> {
244	/// A depositor account, None means the deposit is collection's owner.
245	pub account: Option<AccountId>,
246	/// An amount that gets reserved.
247	pub amount: DepositBalance,
248}
249
250/// Specifies whether the tokens will be sent or received.
251#[derive(
252	Clone, Encode, Decode, DecodeWithMemTracking, Eq, PartialEq, Debug, TypeInfo, MaxEncodedLen,
253)]
254pub enum PriceDirection {
255	/// Tokens will be sent.
256	Send,
257	/// Tokens will be received.
258	Receive,
259}
260
261/// Holds the details about the price.
262#[derive(
263	Clone, Encode, Decode, DecodeWithMemTracking, Eq, PartialEq, Debug, TypeInfo, MaxEncodedLen,
264)]
265pub struct PriceWithDirection<Amount> {
266	/// An amount.
267	pub amount: Amount,
268	/// A direction (send or receive).
269	pub direction: PriceDirection,
270}
271
272/// Support for up to 64 user-enabled features on a collection.
273#[bitflags]
274#[repr(u64)]
275#[derive(Copy, Clone, Debug, PartialEq, Eq, Encode, Decode, MaxEncodedLen, TypeInfo)]
276pub enum CollectionSetting {
277	/// Items in this collection are transferable.
278	TransferableItems,
279	/// The metadata of this collection can be modified.
280	UnlockedMetadata,
281	/// Attributes of this collection can be modified.
282	UnlockedAttributes,
283	/// The supply of this collection can be modified.
284	UnlockedMaxSupply,
285	/// When this isn't set then the deposit is required to hold the items of this collection.
286	DepositRequired,
287}
288
289/// Wrapper type for `BitFlags<CollectionSetting>` that implements `Codec`.
290#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)]
291pub struct CollectionSettings(pub BitFlags<CollectionSetting>);
292
293impl CollectionSettings {
294	pub fn all_enabled() -> Self {
295		Self(BitFlags::EMPTY)
296	}
297	pub fn get_disabled(&self) -> BitFlags<CollectionSetting> {
298		self.0
299	}
300	pub fn is_disabled(&self, setting: CollectionSetting) -> bool {
301		self.0.contains(setting)
302	}
303	pub fn from_disabled(settings: BitFlags<CollectionSetting>) -> Self {
304		Self(settings)
305	}
306}
307
308impl_codec_bitflags!(CollectionSettings, u64, CollectionSetting);
309// We can implement `DecodeWithMemTracking` for `CollectionSettings`
310// since `u64` also implements `DecodeWithMemTracking`.
311impl DecodeWithMemTracking for CollectionSettings {}
312
313/// Mint type. Can the NFT be create by anyone, or only the creator of the collection,
314/// or only by wallets that already hold an NFT from a certain collection?
315/// The ownership of a privately minted NFT is still publicly visible.
316#[derive(
317	Clone,
318	Copy,
319	Encode,
320	Decode,
321	DecodeWithMemTracking,
322	Eq,
323	PartialEq,
324	Debug,
325	TypeInfo,
326	MaxEncodedLen,
327)]
328pub enum MintType<CollectionId> {
329	/// Only an `Issuer` could mint items.
330	Issuer,
331	/// Anyone could mint items.
332	Public,
333	/// Only holders of items in specified collection could mint new items.
334	HolderOf(CollectionId),
335}
336
337/// Holds the information about minting.
338#[derive(
339	Clone,
340	Copy,
341	Encode,
342	Decode,
343	DecodeWithMemTracking,
344	Eq,
345	PartialEq,
346	Debug,
347	TypeInfo,
348	MaxEncodedLen,
349)]
350pub struct MintSettings<Price, BlockNumber, CollectionId> {
351	/// Whether anyone can mint or if minters are restricted to some subset.
352	pub mint_type: MintType<CollectionId>,
353	/// An optional price per mint.
354	pub price: Option<Price>,
355	/// When the mint starts.
356	pub start_block: Option<BlockNumber>,
357	/// When the mint ends.
358	pub end_block: Option<BlockNumber>,
359	/// Default settings each item will get during the mint.
360	pub default_item_settings: ItemSettings,
361}
362
363impl<Price, BlockNumber, CollectionId> Default for MintSettings<Price, BlockNumber, CollectionId> {
364	fn default() -> Self {
365		Self {
366			mint_type: MintType::Issuer,
367			price: None,
368			start_block: None,
369			end_block: None,
370			default_item_settings: ItemSettings::all_enabled(),
371		}
372	}
373}
374
375/// Attribute namespaces for non-fungible tokens.
376#[derive(
377	Clone,
378	Encode,
379	Decode,
380	DecodeWithMemTracking,
381	Eq,
382	PartialEq,
383	Debug,
384	scale_info::TypeInfo,
385	MaxEncodedLen,
386)]
387pub enum AttributeNamespace<AccountId> {
388	/// An attribute was set by the pallet.
389	Pallet,
390	/// An attribute was set by collection's owner.
391	CollectionOwner,
392	/// An attribute was set by item's owner.
393	ItemOwner,
394	/// An attribute was set by pre-approved account.
395	Account(AccountId),
396}
397
398/// A witness data to cancel attributes approval operation.
399#[derive(Clone, Encode, Decode, DecodeWithMemTracking, Eq, PartialEq, Debug, TypeInfo)]
400pub struct CancelAttributesApprovalWitness {
401	/// An amount of attributes previously created by account.
402	pub account_attributes: u32,
403}
404
405/// A list of possible pallet-level attributes.
406#[derive(
407	Clone, Encode, Decode, DecodeWithMemTracking, Eq, PartialEq, Debug, TypeInfo, MaxEncodedLen,
408)]
409pub enum PalletAttributes<CollectionId> {
410	/// Marks an item as being used in order to claim another item.
411	UsedToClaim(CollectionId),
412	/// Marks an item as being restricted from transferring.
413	TransferDisabled,
414}
415
416/// Collection's configuration.
417#[derive(
418	Clone,
419	Copy,
420	Decode,
421	DecodeWithMemTracking,
422	Default,
423	Encode,
424	MaxEncodedLen,
425	PartialEq,
426	Debug,
427	TypeInfo,
428)]
429pub struct CollectionConfig<Price, BlockNumber, CollectionId> {
430	/// Collection's settings.
431	pub settings: CollectionSettings,
432	/// Collection's max supply.
433	pub max_supply: Option<u32>,
434	/// Default settings each item will get during the mint.
435	pub mint_settings: MintSettings<Price, BlockNumber, CollectionId>,
436}
437
438impl<Price, BlockNumber, CollectionId> CollectionConfig<Price, BlockNumber, CollectionId> {
439	pub fn is_setting_enabled(&self, setting: CollectionSetting) -> bool {
440		!self.settings.is_disabled(setting)
441	}
442	pub fn has_disabled_setting(&self, setting: CollectionSetting) -> bool {
443		self.settings.is_disabled(setting)
444	}
445	pub fn enable_setting(&mut self, setting: CollectionSetting) {
446		self.settings.0.remove(setting);
447	}
448	pub fn disable_setting(&mut self, setting: CollectionSetting) {
449		self.settings.0.insert(setting);
450	}
451}
452
453/// Support for up to 64 user-enabled features on an item.
454#[bitflags]
455#[repr(u64)]
456#[derive(Copy, Clone, Debug, PartialEq, Eq, Encode, Decode, MaxEncodedLen, TypeInfo)]
457pub enum ItemSetting {
458	/// This item is transferable.
459	Transferable,
460	/// The metadata of this item can be modified.
461	UnlockedMetadata,
462	/// Attributes of this item can be modified.
463	UnlockedAttributes,
464}
465
466/// Wrapper type for `BitFlags<ItemSetting>` that implements `Codec`.
467#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)]
468pub struct ItemSettings(pub BitFlags<ItemSetting>);
469
470impl ItemSettings {
471	pub fn all_enabled() -> Self {
472		Self(BitFlags::EMPTY)
473	}
474	pub fn get_disabled(&self) -> BitFlags<ItemSetting> {
475		self.0
476	}
477	pub fn is_disabled(&self, setting: ItemSetting) -> bool {
478		self.0.contains(setting)
479	}
480	pub fn from_disabled(settings: BitFlags<ItemSetting>) -> Self {
481		Self(settings)
482	}
483}
484
485impl_codec_bitflags!(ItemSettings, u64, ItemSetting);
486// We can implement `DecodeWithMemTracking` for `ItemSettings`
487// since `u64` also implements `DecodeWithMemTracking`.
488impl DecodeWithMemTracking for ItemSettings {}
489
490/// Item's configuration.
491#[derive(
492	Encode,
493	Decode,
494	DecodeWithMemTracking,
495	Default,
496	PartialEq,
497	Debug,
498	Clone,
499	Copy,
500	MaxEncodedLen,
501	TypeInfo,
502)]
503pub struct ItemConfig {
504	/// Item's settings.
505	pub settings: ItemSettings,
506}
507
508impl ItemConfig {
509	pub fn is_setting_enabled(&self, setting: ItemSetting) -> bool {
510		!self.settings.is_disabled(setting)
511	}
512	pub fn has_disabled_setting(&self, setting: ItemSetting) -> bool {
513		self.settings.is_disabled(setting)
514	}
515	pub fn has_disabled_settings(&self) -> bool {
516		!self.settings.get_disabled().is_empty()
517	}
518	pub fn enable_setting(&mut self, setting: ItemSetting) {
519		self.settings.0.remove(setting);
520	}
521	pub fn disable_setting(&mut self, setting: ItemSetting) {
522		self.settings.0.insert(setting);
523	}
524}
525
526/// Support for up to 64 system-enabled features on a collection.
527#[bitflags]
528#[repr(u64)]
529#[derive(Copy, Clone, Debug, PartialEq, Eq, Encode, Decode, MaxEncodedLen, TypeInfo)]
530pub enum PalletFeature {
531	/// Enable/disable trading operations.
532	Trading,
533	/// Allow/disallow setting attributes.
534	Attributes,
535	/// Allow/disallow transfer approvals.
536	Approvals,
537	/// Allow/disallow atomic items swap.
538	Swaps,
539}
540
541/// Wrapper type for `BitFlags<PalletFeature>` that implements `Codec`.
542#[derive(Default, Debug)]
543pub struct PalletFeatures(pub BitFlags<PalletFeature>);
544
545impl PalletFeatures {
546	pub fn all_enabled() -> Self {
547		Self(BitFlags::EMPTY)
548	}
549	pub fn from_disabled(features: BitFlags<PalletFeature>) -> Self {
550		Self(features)
551	}
552	pub fn is_enabled(&self, feature: PalletFeature) -> bool {
553		!self.0.contains(feature)
554	}
555}
556impl_codec_bitflags!(PalletFeatures, u64, PalletFeature);
557
558/// Support for up to 8 different roles for collections.
559#[bitflags]
560#[repr(u8)]
561#[derive(Copy, Clone, Debug, PartialEq, Eq, Encode, Decode, MaxEncodedLen, TypeInfo)]
562pub enum CollectionRole {
563	/// Can mint items.
564	Issuer,
565	/// Can freeze items.
566	Freezer,
567	/// Can thaw items, force transfers and burn items from any account.
568	Admin,
569}
570
571/// A wrapper type that implements `Codec`.
572#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)]
573pub struct CollectionRoles(pub BitFlags<CollectionRole>);
574
575impl CollectionRoles {
576	pub fn none() -> Self {
577		Self(BitFlags::EMPTY)
578	}
579	pub fn has_role(&self, role: CollectionRole) -> bool {
580		self.0.contains(role)
581	}
582	pub fn add_role(&mut self, role: CollectionRole) {
583		self.0.insert(role);
584	}
585	pub fn max_roles() -> u8 {
586		let all: BitFlags<CollectionRole> = BitFlags::all();
587		all.len() as u8
588	}
589}
590impl_codec_bitflags!(CollectionRoles, u8, CollectionRole);
591
592#[derive(Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
593pub struct PreSignedMint<CollectionId, ItemId, AccountId, Deadline, Balance> {
594	/// A collection of the item to be minted.
595	pub collection: CollectionId,
596	/// Item's ID.
597	pub item: ItemId,
598	/// Additional item's key-value attributes.
599	pub attributes: Vec<(Vec<u8>, Vec<u8>)>,
600	/// Additional item's metadata.
601	pub metadata: Vec<u8>,
602	/// Restrict the claim to a particular account.
603	pub only_account: Option<AccountId>,
604	/// A deadline for the signature.
605	pub deadline: Deadline,
606	/// An optional price the claimer would need to pay for the mint.
607	pub mint_price: Option<Balance>,
608}
609
610#[derive(Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, Debug, TypeInfo)]
611pub struct PreSignedAttributes<CollectionId, ItemId, AccountId, Deadline> {
612	/// Collection's ID.
613	pub collection: CollectionId,
614	/// Item's ID.
615	pub item: ItemId,
616	/// Key-value attributes.
617	pub attributes: Vec<(Vec<u8>, Vec<u8>)>,
618	/// Attributes' namespace.
619	pub namespace: AttributeNamespace<AccountId>,
620	/// A deadline for the signature.
621	pub deadline: Deadline,
622}