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, RuntimeDebug, 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	RuntimeDebug,
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(
147	Clone, Encode, Decode, DecodeWithMemTracking, Default, Eq, PartialEq, RuntimeDebug, TypeInfo,
148)]
149pub struct MintWitness<ItemId, Balance> {
150	/// Provide the id of the item in a required collection.
151	pub owned_item: Option<ItemId>,
152	/// The price specified in mint settings.
153	pub mint_price: Option<Balance>,
154}
155
156/// Information concerning the ownership of a single unique item.
157#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, TypeInfo, MaxEncodedLen)]
158pub struct ItemDetails<AccountId, Deposit, Approvals> {
159	/// The owner of this item.
160	pub owner: AccountId,
161	/// The approved transferrer of this item, if one is set.
162	pub approvals: Approvals,
163	/// The amount held in the pallet's default account for this item. Free-hold items will have
164	/// this as zero.
165	pub deposit: Deposit,
166}
167
168/// Information about the reserved item deposit.
169#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
170pub struct ItemDeposit<DepositBalance, AccountId> {
171	/// A depositor account.
172	pub account: AccountId,
173	/// An amount that gets reserved.
174	pub amount: DepositBalance,
175}
176
177/// Information about the collection's metadata.
178#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, TypeInfo, MaxEncodedLen)]
179#[scale_info(skip_type_params(StringLimit))]
180#[codec(mel_bound(Deposit: MaxEncodedLen))]
181pub struct CollectionMetadata<Deposit, StringLimit: Get<u32>> {
182	/// The balance deposited for this metadata.
183	///
184	/// This pays for the data stored in this struct.
185	pub deposit: Deposit,
186	/// General information concerning this collection. Limited in length by `StringLimit`. This
187	/// will generally be either a JSON dump or the hash of some JSON which can be found on a
188	/// hash-addressable global publication system such as IPFS.
189	pub data: BoundedVec<u8, StringLimit>,
190}
191
192/// Information about the item's metadata.
193#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, TypeInfo, MaxEncodedLen)]
194#[scale_info(skip_type_params(StringLimit))]
195pub struct ItemMetadata<Deposit, StringLimit: Get<u32>> {
196	/// The balance deposited for this metadata.
197	///
198	/// This pays for the data stored in this struct.
199	pub deposit: Deposit,
200	/// General information concerning this item. Limited in length by `StringLimit`. This will
201	/// generally be either a JSON dump or the hash of some JSON which can be found on
202	/// hash-addressable global publication system such as IPFS.
203	pub data: BoundedVec<u8, StringLimit>,
204}
205
206/// Information about the tip.
207#[derive(
208	Clone,
209	Encode,
210	Decode,
211	DecodeWithMemTracking,
212	Eq,
213	PartialEq,
214	RuntimeDebug,
215	TypeInfo,
216	MaxEncodedLen,
217)]
218pub struct ItemTip<CollectionId, ItemId, AccountId, Amount> {
219	/// The collection of the item.
220	pub collection: CollectionId,
221	/// An item of which the tip is sent for.
222	pub item: ItemId,
223	/// A sender of the tip.
224	pub receiver: AccountId,
225	/// An amount the sender is willing to tip.
226	pub amount: Amount,
227}
228
229/// Information about the pending swap.
230#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, Default, TypeInfo, MaxEncodedLen)]
231pub struct PendingSwap<CollectionId, ItemId, ItemPriceWithDirection, Deadline> {
232	/// The collection that contains the item that the user wants to receive.
233	pub desired_collection: CollectionId,
234	/// The item the user wants to receive.
235	pub desired_item: Option<ItemId>,
236	/// A price for the desired `item` with the direction.
237	pub price: Option<ItemPriceWithDirection>,
238	/// A deadline for the swap.
239	pub deadline: Deadline,
240}
241
242/// Information about the reserved attribute deposit.
243#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
244pub struct AttributeDeposit<DepositBalance, AccountId> {
245	/// A depositor account.
246	pub account: Option<AccountId>,
247	/// An amount that gets reserved.
248	pub amount: DepositBalance,
249}
250
251/// Information about the reserved item's metadata deposit.
252#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
253pub struct ItemMetadataDeposit<DepositBalance, AccountId> {
254	/// A depositor account, None means the deposit is collection's owner.
255	pub account: Option<AccountId>,
256	/// An amount that gets reserved.
257	pub amount: DepositBalance,
258}
259
260/// Specifies whether the tokens will be sent or received.
261#[derive(
262	Clone,
263	Encode,
264	Decode,
265	DecodeWithMemTracking,
266	Eq,
267	PartialEq,
268	RuntimeDebug,
269	TypeInfo,
270	MaxEncodedLen,
271)]
272pub enum PriceDirection {
273	/// Tokens will be sent.
274	Send,
275	/// Tokens will be received.
276	Receive,
277}
278
279/// Holds the details about the price.
280#[derive(
281	Clone,
282	Encode,
283	Decode,
284	DecodeWithMemTracking,
285	Eq,
286	PartialEq,
287	RuntimeDebug,
288	TypeInfo,
289	MaxEncodedLen,
290)]
291pub struct PriceWithDirection<Amount> {
292	/// An amount.
293	pub amount: Amount,
294	/// A direction (send or receive).
295	pub direction: PriceDirection,
296}
297
298/// Support for up to 64 user-enabled features on a collection.
299#[bitflags]
300#[repr(u64)]
301#[derive(Copy, Clone, RuntimeDebug, PartialEq, Eq, Encode, Decode, MaxEncodedLen, TypeInfo)]
302pub enum CollectionSetting {
303	/// Items in this collection are transferable.
304	TransferableItems,
305	/// The metadata of this collection can be modified.
306	UnlockedMetadata,
307	/// Attributes of this collection can be modified.
308	UnlockedAttributes,
309	/// The supply of this collection can be modified.
310	UnlockedMaxSupply,
311	/// When this isn't set then the deposit is required to hold the items of this collection.
312	DepositRequired,
313}
314
315/// Wrapper type for `BitFlags<CollectionSetting>` that implements `Codec`.
316#[derive(Clone, Copy, PartialEq, Eq, Default, RuntimeDebug)]
317pub struct CollectionSettings(pub BitFlags<CollectionSetting>);
318
319impl CollectionSettings {
320	pub fn all_enabled() -> Self {
321		Self(BitFlags::EMPTY)
322	}
323	pub fn get_disabled(&self) -> BitFlags<CollectionSetting> {
324		self.0
325	}
326	pub fn is_disabled(&self, setting: CollectionSetting) -> bool {
327		self.0.contains(setting)
328	}
329	pub fn from_disabled(settings: BitFlags<CollectionSetting>) -> Self {
330		Self(settings)
331	}
332}
333
334impl_codec_bitflags!(CollectionSettings, u64, CollectionSetting);
335// We can implement `DecodeWithMemTracking` for `CollectionSettings`
336// since `u64` also implements `DecodeWithMemTracking`.
337impl DecodeWithMemTracking for CollectionSettings {}
338
339/// Mint type. Can the NFT be create by anyone, or only the creator of the collection,
340/// or only by wallets that already hold an NFT from a certain collection?
341/// The ownership of a privately minted NFT is still publicly visible.
342#[derive(
343	Clone,
344	Copy,
345	Encode,
346	Decode,
347	DecodeWithMemTracking,
348	Eq,
349	PartialEq,
350	RuntimeDebug,
351	TypeInfo,
352	MaxEncodedLen,
353)]
354pub enum MintType<CollectionId> {
355	/// Only an `Issuer` could mint items.
356	Issuer,
357	/// Anyone could mint items.
358	Public,
359	/// Only holders of items in specified collection could mint new items.
360	HolderOf(CollectionId),
361}
362
363/// Holds the information about minting.
364#[derive(
365	Clone,
366	Copy,
367	Encode,
368	Decode,
369	DecodeWithMemTracking,
370	Eq,
371	PartialEq,
372	RuntimeDebug,
373	TypeInfo,
374	MaxEncodedLen,
375)]
376pub struct MintSettings<Price, BlockNumber, CollectionId> {
377	/// Whether anyone can mint or if minters are restricted to some subset.
378	pub mint_type: MintType<CollectionId>,
379	/// An optional price per mint.
380	pub price: Option<Price>,
381	/// When the mint starts.
382	pub start_block: Option<BlockNumber>,
383	/// When the mint ends.
384	pub end_block: Option<BlockNumber>,
385	/// Default settings each item will get during the mint.
386	pub default_item_settings: ItemSettings,
387}
388
389impl<Price, BlockNumber, CollectionId> Default for MintSettings<Price, BlockNumber, CollectionId> {
390	fn default() -> Self {
391		Self {
392			mint_type: MintType::Issuer,
393			price: None,
394			start_block: None,
395			end_block: None,
396			default_item_settings: ItemSettings::all_enabled(),
397		}
398	}
399}
400
401/// Attribute namespaces for non-fungible tokens.
402#[derive(
403	Clone,
404	Encode,
405	Decode,
406	DecodeWithMemTracking,
407	Eq,
408	PartialEq,
409	RuntimeDebug,
410	scale_info::TypeInfo,
411	MaxEncodedLen,
412)]
413pub enum AttributeNamespace<AccountId> {
414	/// An attribute was set by the pallet.
415	Pallet,
416	/// An attribute was set by collection's owner.
417	CollectionOwner,
418	/// An attribute was set by item's owner.
419	ItemOwner,
420	/// An attribute was set by pre-approved account.
421	Account(AccountId),
422}
423
424/// A witness data to cancel attributes approval operation.
425#[derive(Clone, Encode, Decode, DecodeWithMemTracking, Eq, PartialEq, RuntimeDebug, TypeInfo)]
426pub struct CancelAttributesApprovalWitness {
427	/// An amount of attributes previously created by account.
428	pub account_attributes: u32,
429}
430
431/// A list of possible pallet-level attributes.
432#[derive(
433	Clone,
434	Encode,
435	Decode,
436	DecodeWithMemTracking,
437	Eq,
438	PartialEq,
439	RuntimeDebug,
440	TypeInfo,
441	MaxEncodedLen,
442)]
443pub enum PalletAttributes<CollectionId> {
444	/// Marks an item as being used in order to claim another item.
445	UsedToClaim(CollectionId),
446	/// Marks an item as being restricted from transferring.
447	TransferDisabled,
448}
449
450/// Collection's configuration.
451#[derive(
452	Clone,
453	Copy,
454	Decode,
455	DecodeWithMemTracking,
456	Default,
457	Encode,
458	MaxEncodedLen,
459	PartialEq,
460	RuntimeDebug,
461	TypeInfo,
462)]
463pub struct CollectionConfig<Price, BlockNumber, CollectionId> {
464	/// Collection's settings.
465	pub settings: CollectionSettings,
466	/// Collection's max supply.
467	pub max_supply: Option<u32>,
468	/// Default settings each item will get during the mint.
469	pub mint_settings: MintSettings<Price, BlockNumber, CollectionId>,
470}
471
472impl<Price, BlockNumber, CollectionId> CollectionConfig<Price, BlockNumber, CollectionId> {
473	pub fn is_setting_enabled(&self, setting: CollectionSetting) -> bool {
474		!self.settings.is_disabled(setting)
475	}
476	pub fn has_disabled_setting(&self, setting: CollectionSetting) -> bool {
477		self.settings.is_disabled(setting)
478	}
479	pub fn enable_setting(&mut self, setting: CollectionSetting) {
480		self.settings.0.remove(setting);
481	}
482	pub fn disable_setting(&mut self, setting: CollectionSetting) {
483		self.settings.0.insert(setting);
484	}
485}
486
487/// Support for up to 64 user-enabled features on an item.
488#[bitflags]
489#[repr(u64)]
490#[derive(Copy, Clone, RuntimeDebug, PartialEq, Eq, Encode, Decode, MaxEncodedLen, TypeInfo)]
491pub enum ItemSetting {
492	/// This item is transferable.
493	Transferable,
494	/// The metadata of this item can be modified.
495	UnlockedMetadata,
496	/// Attributes of this item can be modified.
497	UnlockedAttributes,
498}
499
500/// Wrapper type for `BitFlags<ItemSetting>` that implements `Codec`.
501#[derive(Clone, Copy, PartialEq, Eq, Default, RuntimeDebug)]
502pub struct ItemSettings(pub BitFlags<ItemSetting>);
503
504impl ItemSettings {
505	pub fn all_enabled() -> Self {
506		Self(BitFlags::EMPTY)
507	}
508	pub fn get_disabled(&self) -> BitFlags<ItemSetting> {
509		self.0
510	}
511	pub fn is_disabled(&self, setting: ItemSetting) -> bool {
512		self.0.contains(setting)
513	}
514	pub fn from_disabled(settings: BitFlags<ItemSetting>) -> Self {
515		Self(settings)
516	}
517}
518
519impl_codec_bitflags!(ItemSettings, u64, ItemSetting);
520// We can implement `DecodeWithMemTracking` for `ItemSettings`
521// since `u64` also implements `DecodeWithMemTracking`.
522impl DecodeWithMemTracking for ItemSettings {}
523
524/// Item's configuration.
525#[derive(
526	Encode,
527	Decode,
528	DecodeWithMemTracking,
529	Default,
530	PartialEq,
531	RuntimeDebug,
532	Clone,
533	Copy,
534	MaxEncodedLen,
535	TypeInfo,
536)]
537pub struct ItemConfig {
538	/// Item's settings.
539	pub settings: ItemSettings,
540}
541
542impl ItemConfig {
543	pub fn is_setting_enabled(&self, setting: ItemSetting) -> bool {
544		!self.settings.is_disabled(setting)
545	}
546	pub fn has_disabled_setting(&self, setting: ItemSetting) -> bool {
547		self.settings.is_disabled(setting)
548	}
549	pub fn has_disabled_settings(&self) -> bool {
550		!self.settings.get_disabled().is_empty()
551	}
552	pub fn enable_setting(&mut self, setting: ItemSetting) {
553		self.settings.0.remove(setting);
554	}
555	pub fn disable_setting(&mut self, setting: ItemSetting) {
556		self.settings.0.insert(setting);
557	}
558}
559
560/// Support for up to 64 system-enabled features on a collection.
561#[bitflags]
562#[repr(u64)]
563#[derive(Copy, Clone, RuntimeDebug, PartialEq, Eq, Encode, Decode, MaxEncodedLen, TypeInfo)]
564pub enum PalletFeature {
565	/// Enable/disable trading operations.
566	Trading,
567	/// Allow/disallow setting attributes.
568	Attributes,
569	/// Allow/disallow transfer approvals.
570	Approvals,
571	/// Allow/disallow atomic items swap.
572	Swaps,
573}
574
575/// Wrapper type for `BitFlags<PalletFeature>` that implements `Codec`.
576#[derive(Default, RuntimeDebug)]
577pub struct PalletFeatures(pub BitFlags<PalletFeature>);
578
579impl PalletFeatures {
580	pub fn all_enabled() -> Self {
581		Self(BitFlags::EMPTY)
582	}
583	pub fn from_disabled(features: BitFlags<PalletFeature>) -> Self {
584		Self(features)
585	}
586	pub fn is_enabled(&self, feature: PalletFeature) -> bool {
587		!self.0.contains(feature)
588	}
589}
590impl_codec_bitflags!(PalletFeatures, u64, PalletFeature);
591
592/// Support for up to 8 different roles for collections.
593#[bitflags]
594#[repr(u8)]
595#[derive(Copy, Clone, RuntimeDebug, PartialEq, Eq, Encode, Decode, MaxEncodedLen, TypeInfo)]
596pub enum CollectionRole {
597	/// Can mint items.
598	Issuer,
599	/// Can freeze items.
600	Freezer,
601	/// Can thaw items, force transfers and burn items from any account.
602	Admin,
603}
604
605/// A wrapper type that implements `Codec`.
606#[derive(Clone, Copy, PartialEq, Eq, Default, RuntimeDebug)]
607pub struct CollectionRoles(pub BitFlags<CollectionRole>);
608
609impl CollectionRoles {
610	pub fn none() -> Self {
611		Self(BitFlags::EMPTY)
612	}
613	pub fn has_role(&self, role: CollectionRole) -> bool {
614		self.0.contains(role)
615	}
616	pub fn add_role(&mut self, role: CollectionRole) {
617		self.0.insert(role);
618	}
619	pub fn max_roles() -> u8 {
620		let all: BitFlags<CollectionRole> = BitFlags::all();
621		all.len() as u8
622	}
623}
624impl_codec_bitflags!(CollectionRoles, u8, CollectionRole);
625
626#[derive(Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, RuntimeDebug, TypeInfo)]
627pub struct PreSignedMint<CollectionId, ItemId, AccountId, Deadline, Balance> {
628	/// A collection of the item to be minted.
629	pub collection: CollectionId,
630	/// Item's ID.
631	pub item: ItemId,
632	/// Additional item's key-value attributes.
633	pub attributes: Vec<(Vec<u8>, Vec<u8>)>,
634	/// Additional item's metadata.
635	pub metadata: Vec<u8>,
636	/// Restrict the claim to a particular account.
637	pub only_account: Option<AccountId>,
638	/// A deadline for the signature.
639	pub deadline: Deadline,
640	/// An optional price the claimer would need to pay for the mint.
641	pub mint_price: Option<Balance>,
642}
643
644#[derive(Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, RuntimeDebug, TypeInfo)]
645pub struct PreSignedAttributes<CollectionId, ItemId, AccountId, Deadline> {
646	/// Collection's ID.
647	pub collection: CollectionId,
648	/// Item's ID.
649	pub item: ItemId,
650	/// Key-value attributes.
651	pub attributes: Vec<(Vec<u8>, Vec<u8>)>,
652	/// Attributes' namespace.
653	pub namespace: AttributeNamespace<AccountId>,
654	/// A deadline for the signature.
655	pub deadline: Deadline,
656}