git.delta.rocks / unique-network / refs/commits / 13f1ef471526

difftreelog

replace `Vec` with `RawEncoded`

Grigoriy Simonov2023-04-07parent: #38560bb.patch.diff
in: master

2 files changed

modifiedprimitives/data-structs/src/lib.rsdiffbeforeafterboth
before · primitives/data-structs/src/lib.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! # Primitives crate.18//!19//! This crate contains types, traits and constants.2021#![cfg_attr(not(feature = "std"), no_std)]2223use core::{24	convert::{TryFrom, TryInto},25	fmt,26};27use frame_support::storage::{bounded_btree_map::BoundedBTreeMap, bounded_btree_set::BoundedBTreeSet};2829#[cfg(feature = "serde")]30use serde::{Serialize, Deserialize};3132use sp_core::U256;33use sp_runtime::{ArithmeticError, sp_std::prelude::Vec};34use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};35use bondrewd::Bitfields;36use frame_support::{BoundedVec, traits::ConstU32};37use derivative::Derivative;38use scale_info::TypeInfo;3940mod bondrewd_codec;41mod bounded;42pub mod budget;43pub mod mapping;44mod migration;4546/// Maximum of decimal points.47pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;4849/// Maximum pieces for refungible token.50pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;51pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;5253/// Maximum tokens for user.54pub const MAX_TOKEN_OWNERSHIP: u32 = if cfg!(not(feature = "limit-testing")) {55	100_00056} else {57	1058};5960/// Maximum for collections can be created.61pub const COLLECTION_NUMBER_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {62	100_00063} else {64	1065};6667/// Maximum for various custom data of token.68pub const CUSTOM_DATA_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {69	204870} else {71	1072};7374/// Maximum admins per collection.75pub const COLLECTION_ADMINS_LIMIT: u32 = 5;7677/// Maximum tokens per collection.78pub const COLLECTION_TOKEN_LIMIT: u32 = u32::MAX;7980/// Maximum tokens per account.81pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {82	1_000_00083} else {84	1085};8687/// Default timeout for transfer sponsoring NFT item.88pub const NFT_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;89/// Default timeout for transfer sponsoring fungible item.90pub const FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;91/// Default timeout for transfer sponsoring refungible item.92pub const REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;9394/// Default timeout for sponsored approving.95pub const SPONSOR_APPROVE_TIMEOUT: u32 = 5;9697// Schema limits98pub const OFFCHAIN_SCHEMA_LIMIT: u32 = 8192;99pub const VARIABLE_ON_CHAIN_SCHEMA_LIMIT: u32 = 8192;100pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 32768;101102// TODO: not used. Delete?103pub const COLLECTION_FIELD_LIMIT: u32 = CONST_ON_CHAIN_SCHEMA_LIMIT;104105/// Maximal length of a collection name.106pub const MAX_COLLECTION_NAME_LENGTH: u32 = 64;107108/// Maximal length of a collection description.109pub const MAX_COLLECTION_DESCRIPTION_LENGTH: u32 = 256;110111/// Maximal length of a token prefix.112pub const MAX_TOKEN_PREFIX_LENGTH: u32 = 16;113114/// Maximal length of a property key.115pub const MAX_PROPERTY_KEY_LENGTH: u32 = 256;116117/// Maximal length of a property value.118pub const MAX_PROPERTY_VALUE_LENGTH: u32 = 32768;119120/// A maximum number of token properties.121pub const MAX_PROPERTIES_PER_ITEM: u32 = 64;122123/// Maximal lenght of extended property value.124pub const MAX_AUX_PROPERTY_VALUE_LENGTH: u32 = 2048;125126/// Maximum size for all collection properties.127pub const MAX_COLLECTION_PROPERTIES_SIZE: u32 = 40960;128129/// Maximum size of all token properties.130pub const MAX_TOKEN_PROPERTIES_SIZE: u32 = 32768;131132/// How much items can be created per single133/// create_many call.134pub const MAX_ITEMS_PER_BATCH: u32 = 200;135136/// Used for limit bounded types of token custom data.137pub type CustomDataLimit = ConstU32<CUSTOM_DATA_LIMIT>;138139/// Collection id.140#[derive(141	Encode,142	Decode,143	PartialEq,144	Eq,145	PartialOrd,146	Ord,147	Clone,148	Copy,149	Debug,150	Default,151	TypeInfo,152	MaxEncodedLen,153)]154#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]155pub struct CollectionId(pub u32);156impl EncodeLike<u32> for CollectionId {}157impl EncodeLike<CollectionId> for u32 {}158159impl From<u32> for CollectionId {160	fn from(value: u32) -> Self {161		Self(value)162	}163}164165/// Token id.166#[derive(167	Encode,168	Decode,169	PartialEq,170	Eq,171	PartialOrd,172	Ord,173	Clone,174	Copy,175	Debug,176	Default,177	TypeInfo,178	MaxEncodedLen,179)]180#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]181pub struct TokenId(pub u32);182impl EncodeLike<u32> for TokenId {}183impl EncodeLike<TokenId> for u32 {}184185impl TokenId {186	/// Try to get next token id.187	///188	/// If next id cause overflow, then [`ArithmeticError::Overflow`] returned.189	pub fn try_next(self) -> Result<TokenId, ArithmeticError> {190		self.0191			.checked_add(1)192			.ok_or(ArithmeticError::Overflow)193			.map(Self)194	}195}196197impl From<TokenId> for U256 {198	fn from(t: TokenId) -> Self {199		t.0.into()200	}201}202203impl TryFrom<U256> for TokenId {204	type Error = &'static str;205206	fn try_from(value: U256) -> Result<Self, Self::Error> {207		Ok(TokenId(value.try_into().map_err(|_| "too large token id")?))208	}209}210211/// Token data.212#[struct_versioning::versioned(version = 2, upper)]213#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]214#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]215pub struct TokenData<CrossAccountId> {216	/// Properties of token.217	pub properties: Vec<Property>,218219	/// Token owner.220	pub owner: Option<CrossAccountId>,221222	/// Token pieces.223	#[version(2.., upper(0))]224	pub pieces: u128,225}226227// TODO: unused type228pub struct OverflowError;229impl From<OverflowError> for &'static str {230	fn from(_: OverflowError) -> Self {231		"overflow occured"232	}233}234235/// Alias for decimal points type.236pub type DecimalPoints = u8;237238/// Collection mode.239///240/// Collection can represent various types of tokens.241/// Each collection can contain only one type of tokens at a time.242/// This type helps to understand which tokens the collection contains.243#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]244#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]245pub enum CollectionMode {246	/// Non fungible tokens.247	NFT,248	/// Fungible tokens.249	Fungible(DecimalPoints),250	/// Refungible tokens.251	ReFungible,252}253254impl CollectionMode {255	/// Get collection mod as number.256	pub fn id(&self) -> u8 {257		match self {258			CollectionMode::NFT => 1,259			CollectionMode::Fungible(_) => 2,260			CollectionMode::ReFungible => 3,261		}262	}263}264265// TODO: unused trait266pub trait SponsoringResolve<AccountId, Call> {267	fn resolve(who: &AccountId, call: &Call) -> Option<AccountId>;268}269270/// Access mode for some token operations.271#[derive(Encode, Decode, Eq, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]272#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]273pub enum AccessMode {274	/// Access grant for owner and admins. Used as default.275	Normal,276	/// Like a [`Normal`](AccessMode::Normal) but also users in allow list.277	AllowList,278}279impl Default for AccessMode {280	fn default() -> Self {281		Self::Normal282	}283}284285// TODO: remove in future.286#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]287#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]288pub enum SchemaVersion {289	ImageURL,290	Unique,291}292impl Default for SchemaVersion {293	fn default() -> Self {294		Self::ImageURL295	}296}297298// TODO: unused type299#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, TypeInfo)]300#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]301pub struct Ownership<AccountId> {302	pub owner: AccountId,303	pub fraction: u128,304}305306/// The state of collection sponsorship.307#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]308#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]309pub enum SponsorshipState<AccountId> {310	/// The fees are applied to the transaction sender.311	Disabled,312	/// The sponsor is under consideration. Until the sponsor gives his consent,313	/// the fee will still be charged to sender.314	Unconfirmed(AccountId),315	/// Transactions are sponsored by specified account.316	Confirmed(AccountId),317}318319impl<AccountId> SponsorshipState<AccountId> {320	/// Get a sponsor of the collection who has confirmed his status.321	pub fn sponsor(&self) -> Option<&AccountId> {322		match self {323			Self::Confirmed(sponsor) => Some(sponsor),324			_ => None,325		}326	}327328	/// Get a sponsor of the collection who has pending or confirmed status.329	pub fn pending_sponsor(&self) -> Option<&AccountId> {330		match self {331			Self::Unconfirmed(sponsor) | Self::Confirmed(sponsor) => Some(sponsor),332			_ => None,333		}334	}335336	/// Whether the sponsorship is confirmed.337	pub fn confirmed(&self) -> bool {338		matches!(self, Self::Confirmed(_))339	}340}341342impl<T> Default for SponsorshipState<T> {343	fn default() -> Self {344		Self::Disabled345	}346}347348pub type CollectionName = BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>;349pub type CollectionDescription = BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>;350pub type CollectionTokenPrefix = BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>;351352#[derive(Bitfields, Clone, Copy, PartialEq, Eq, Debug, Default)]353#[bondrewd(enforce_bytes = 1)]354pub struct CollectionFlags {355	/// Tokens in foreign collections can be transferred, but not burnt356	#[bondrewd(bits = "0..1")]357	pub foreign: bool,358	/// Supports ERC721Metadata359	#[bondrewd(bits = "1..2")]360	pub erc721metadata: bool,361	/// External collections can't be managed using `unique` api362	#[bondrewd(bits = "7..8")]363	pub external: bool,364365	#[bondrewd(reserve, bits = "2..7")]366	pub reserved: u8,367}368bondrewd_codec!(CollectionFlags);369370/// Base structure for represent collection.371///372/// Used to provide basic functionality for all types of collections.373///374/// #### Note375/// Collection parameters, used in storage (see [`RpcCollection`] for the RPC version).376#[struct_versioning::versioned(version = 2, upper)]377#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen)]378pub struct Collection<AccountId> {379	/// Collection owner account.380	pub owner: AccountId,381382	/// Collection mode.383	pub mode: CollectionMode,384385	/// Access mode.386	#[version(..2)]387	pub access: AccessMode,388389	/// Collection name.390	pub name: CollectionName,391392	/// Collection description.393	pub description: CollectionDescription,394395	/// Token prefix.396	pub token_prefix: CollectionTokenPrefix,397398	#[version(..2)]399	pub mint_mode: bool,400401	#[version(..2)]402	pub offchain_schema: BoundedVec<u8, ConstU32<OFFCHAIN_SCHEMA_LIMIT>>,403404	#[version(..2)]405	pub schema_version: SchemaVersion,406407	/// The state of sponsorship of the collection.408	pub sponsorship: SponsorshipState<AccountId>,409410	/// Collection limits.411	pub limits: CollectionLimits,412413	/// Collection permissions.414	#[version(2.., upper(Default::default()))]415	pub permissions: CollectionPermissions,416417	#[version(2.., upper(Default::default()))]418	pub flags: CollectionFlags,419420	#[version(..2)]421	pub variable_on_chain_schema: BoundedVec<u8, ConstU32<VARIABLE_ON_CHAIN_SCHEMA_LIMIT>>,422423	#[version(..2)]424	pub const_on_chain_schema: BoundedVec<u8, ConstU32<CONST_ON_CHAIN_SCHEMA_LIMIT>>,425426	#[version(..2)]427	pub meta_update_permission: MetaUpdatePermission,428}429430#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]431#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]432pub struct RpcCollectionFlags {433	/// Is collection is foreign.434	pub foreign: bool,435	/// Collection supports ERC721Metadata.436	pub erc721metadata: bool,437}438439/// Collection parameters, used in RPC calls (see [`Collection`] for the storage version).440#[struct_versioning::versioned(version = 2, upper)]441#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]442#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]443pub struct RpcCollection<AccountId> {444	/// Collection owner account.445	pub owner: AccountId,446447	/// Collection mode.448	pub mode: CollectionMode,449450	/// Collection name.451	pub name: Vec<u16>,452453	/// Collection description.454	pub description: Vec<u16>,455456	/// Token prefix.457	pub token_prefix: Vec<u8>,458459	/// The state of sponsorship of the collection.460	pub sponsorship: SponsorshipState<AccountId>,461462	/// Collection limits.463	pub limits: CollectionLimits,464465	/// Collection permissions.466	pub permissions: CollectionPermissions,467468	/// Token property permissions.469	pub token_property_permissions: Vec<PropertyKeyPermission>,470471	/// Collection properties.472	pub properties: Vec<Property>,473474	/// Is collection read only.475	pub read_only: bool,476477	/// Extra collection flags478	#[version(2.., upper(RpcCollectionFlags {foreign: false, erc721metadata: false}))]479	pub flags: RpcCollectionFlags,480}481482impl<AccountId> From<CollectionVersion1<AccountId>> for RpcCollection<AccountId> {483	fn from(value: CollectionVersion1<AccountId>) -> Self {484		let CollectionVersion1 {485			name,486			description,487			owner,488			mode,489			access,490			token_prefix,491			mint_mode,492			sponsorship,493			limits,494			..495		} = value;496497		RpcCollection {498			name: name.into_inner(),499			description: description.into_inner(),500			owner,501			mode,502			token_prefix: token_prefix.into_inner(),503			sponsorship,504			limits,505			permissions: CollectionPermissions {506				access: Some(access),507				mint_mode: Some(mint_mode),508				nesting: None,509			},510			token_property_permissions: Vec::default(),511			properties: Vec::default(),512			read_only: true,513514			flags: RpcCollectionFlags {515				foreign: false,516				erc721metadata: false,517			},518		}519	}520}521522/// Data used for create collection.523///524/// All fields are wrapped in [`Option`], where `None` means chain default.525#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, Derivative, MaxEncodedLen)]526#[derivative(Debug, Default(bound = ""))]527pub struct CreateCollectionData<AccountId> {528	/// Collection mode.529	#[derivative(Default(value = "CollectionMode::NFT"))]530	pub mode: CollectionMode,531532	/// Access mode.533	pub access: Option<AccessMode>,534535	/// Collection name.536	pub name: CollectionName,537538	/// Collection description.539	pub description: CollectionDescription,540541	/// Token prefix.542	pub token_prefix: CollectionTokenPrefix,543544	/// Pending collection sponsor.545	pub pending_sponsor: Option<AccountId>,546547	/// Collection limits.548	pub limits: Option<CollectionLimits>,549550	/// Collection permissions.551	pub permissions: Option<CollectionPermissions>,552553	/// Token property permissions.554	pub token_property_permissions: CollectionPropertiesPermissionsVec,555556	/// Collection properties.557	pub properties: CollectionPropertiesVec,558}559560/// Bounded vector of properties permissions. Max length is [`MAX_PROPERTIES_PER_ITEM`].561// TODO: maybe rename to PropertiesPermissionsVec562pub type CollectionPropertiesPermissionsVec =563	BoundedVec<PropertyKeyPermission, ConstU32<MAX_PROPERTIES_PER_ITEM>>;564565/// Bounded vector of properties. Max length is [`MAX_PROPERTIES_PER_ITEM`].566pub type CollectionPropertiesVec = BoundedVec<Property, ConstU32<MAX_PROPERTIES_PER_ITEM>>;567568/// Limits and restrictions of a collection.569///570/// All fields are wrapped in [`Option`], where `None` means chain default.571///572/// Update with `pallet_common::Pallet::clamp_limits`.573// IMPORTANT: When adding/removing fields from this struct - don't forget to also574#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]575#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]576// When adding/removing fields from this struct - don't forget to also update with `pallet_common::Pallet::clamp_limits`.577// TODO: move `pallet_common::Pallet::clamp_limits` into `impl CollectionLimits`.578// TODO: may be remove [`Option`] and **pub** from fields and create struct with default values.579pub struct CollectionLimits {580	/// How many tokens can a user have on one account.581	/// * Default - [`ACCOUNT_TOKEN_OWNERSHIP_LIMIT`].582	/// * Limit - [`MAX_TOKEN_OWNERSHIP`].583	pub account_token_ownership_limit: Option<u32>,584585	/// How many bytes of data are available for sponsorship.586	/// * Default - [`CUSTOM_DATA_LIMIT`].587	/// * Limit - [`CUSTOM_DATA_LIMIT`].588	pub sponsored_data_size: Option<u32>,589590	// FIXME should we delete this or repurpose it?591	/// Times in how many blocks we sponsor data.592	///593	/// If is `Some(v)` then **setVariableMetadata** is sponsored if there is `v` block between transactions.594	///595	/// * Default - [`SponsoringDisabled`](SponsoringRateLimit::SponsoringDisabled).596	/// * Limit - [`MAX_SPONSOR_TIMEOUT`].597	///598	/// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]599	pub sponsored_data_rate_limit: Option<SponsoringRateLimit>,600	/// Maximum amount of tokens inside the collection. Chain default: [`COLLECTION_TOKEN_LIMIT`]601602	/// How many tokens can be mined into this collection.603	///604	/// * Default - [`COLLECTION_TOKEN_LIMIT`].605	/// * Limit - [`COLLECTION_TOKEN_LIMIT`].606	pub token_limit: Option<u32>,607608	/// Timeouts for transfer sponsoring.609	///610	/// * Default611	///   - **Fungible** - [`FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT`]612	///   - **NFT** - [`NFT_SPONSOR_TRANSFER_TIMEOUT`]613	///   - **Refungible** - [`REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT`]614	/// * Limit - [`MAX_SPONSOR_TIMEOUT`].615	pub sponsor_transfer_timeout: Option<u32>,616617	/// Timeout for sponsoring an approval in passed blocks.618	///619	/// * Default - [`SPONSOR_APPROVE_TIMEOUT`].620	/// * Limit - [`MAX_SPONSOR_TIMEOUT`].621	pub sponsor_approve_timeout: Option<u32>,622623	/// Whether the collection owner of the collection can send tokens (which belong to other users).624	///625	/// * Default - **false**.626	pub owner_can_transfer: Option<bool>,627628	/// Can the collection owner burn other people's tokens.629	///630	/// * Default - **true**.631	pub owner_can_destroy: Option<bool>,632633	/// Is it possible to send tokens from this collection between users.634	///635	/// * Default - **true**.636	pub transfers_enabled: Option<bool>,637}638639impl CollectionLimits {640	pub fn with_default_limits(collection_type: CollectionMode) -> Self {641		CollectionLimits {642			account_token_ownership_limit: Some(ACCOUNT_TOKEN_OWNERSHIP_LIMIT),643			sponsored_data_size: Some(CUSTOM_DATA_LIMIT),644			sponsored_data_rate_limit: Some(SponsoringRateLimit::SponsoringDisabled),645			token_limit: Some(COLLECTION_TOKEN_LIMIT),646			sponsor_transfer_timeout: match collection_type {647				CollectionMode::NFT => Some(NFT_SPONSOR_TRANSFER_TIMEOUT),648				CollectionMode::ReFungible => Some(REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT),649				CollectionMode::Fungible(_) => Some(FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT),650			},651			sponsor_approve_timeout: Some(SPONSOR_APPROVE_TIMEOUT),652			owner_can_transfer: Some(false),653			owner_can_destroy: Some(true),654			transfers_enabled: Some(true),655		}656	}657658	/// Get effective value for [`account_token_ownership_limit`](self.account_token_ownership_limit).659	pub fn account_token_ownership_limit(&self) -> u32 {660		self.account_token_ownership_limit661			.unwrap_or(ACCOUNT_TOKEN_OWNERSHIP_LIMIT)662			.min(MAX_TOKEN_OWNERSHIP)663	}664665	/// Get effective value for [`sponsored_data_size`](self.sponsored_data_size).666	pub fn sponsored_data_size(&self) -> u32 {667		self.sponsored_data_size668			.unwrap_or(CUSTOM_DATA_LIMIT)669			.min(CUSTOM_DATA_LIMIT)670	}671672	/// Get effective value for [`token_limit`](self.token_limit).673	pub fn token_limit(&self) -> u32 {674		self.token_limit675			.unwrap_or(COLLECTION_TOKEN_LIMIT)676			.min(COLLECTION_TOKEN_LIMIT)677	}678679	// TODO: may be replace u32 to mode?680	/// Get effective value for [`sponsor_transfer_timeout`](self.sponsor_transfer_timeout).681	pub fn sponsor_transfer_timeout(&self, default: u32) -> u32 {682		self.sponsor_transfer_timeout683			.unwrap_or(default)684			.min(MAX_SPONSOR_TIMEOUT)685	}686687	/// Get effective value for [`sponsor_approve_timeout`](self.sponsor_approve_timeout).688	pub fn sponsor_approve_timeout(&self) -> u32 {689		self.sponsor_approve_timeout690			.unwrap_or(SPONSOR_APPROVE_TIMEOUT)691			.min(MAX_SPONSOR_TIMEOUT)692	}693694	/// Get effective value for [`owner_can_transfer`](self.owner_can_transfer).695	pub fn owner_can_transfer(&self) -> bool {696		self.owner_can_transfer.unwrap_or(false)697	}698699	/// Get effective value for [`owner_can_transfer_instaled`](self.owner_can_transfer_instaled).700	pub fn owner_can_transfer_instaled(&self) -> bool {701		self.owner_can_transfer.is_some()702	}703704	/// Get effective value for [`owner_can_destroy`](self.owner_can_destroy).705	pub fn owner_can_destroy(&self) -> bool {706		self.owner_can_destroy.unwrap_or(true)707	}708709	/// Get effective value for [`transfers_enabled`](self.transfers_enabled).710	pub fn transfers_enabled(&self) -> bool {711		self.transfers_enabled.unwrap_or(true)712	}713714	/// Get effective value for [`sponsored_data_rate_limit`](self.sponsored_data_rate_limit).715	pub fn sponsored_data_rate_limit(&self) -> Option<u32> {716		match self717			.sponsored_data_rate_limit718			.unwrap_or(SponsoringRateLimit::SponsoringDisabled)719		{720			SponsoringRateLimit::SponsoringDisabled => None,721			SponsoringRateLimit::Blocks(v) => Some(v.min(MAX_SPONSOR_TIMEOUT)),722		}723	}724}725726/// Permissions on certain operations within a collection.727///728/// Some fields are wrapped in [`Option`], where `None` means chain default.729///730/// Update with `pallet_common::Pallet::clamp_permissions`.731#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]732#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]733// When adding/removing fields from this struct - don't forget to also update `pallet_common::Pallet::clamp_permissions`.734// TODO: move `pallet_common::Pallet::clamp_permissions` into `impl CollectionPermissions`.735pub struct CollectionPermissions {736	/// Access mode.737	///738	/// * Default - [`AccessMode::Normal`].739	pub access: Option<AccessMode>,740741	/// Minting allowance.742	///743	/// * Default - **false**.744	pub mint_mode: Option<bool>,745746	/// Permissions for nesting.747	///748	/// * Default749	///   - `token_owner` - **false**750	///   - `collection_admin` - **false**751	///   - `restricted` - **None**752	pub nesting: Option<NestingPermissions>,753}754755impl CollectionPermissions {756	/// Get effective value for [`access`](self.access).757	pub fn access(&self) -> AccessMode {758		self.access.unwrap_or(AccessMode::Normal)759	}760761	/// Get effective value for [`mint_mode`](self.mint_mode).762	pub fn mint_mode(&self) -> bool {763		self.mint_mode.unwrap_or(false)764	}765766	/// Get effective value for [`nesting`](self.nesting).767	pub fn nesting(&self) -> &NestingPermissions {768		static DEFAULT: NestingPermissions = NestingPermissions {769			token_owner: false,770			collection_admin: false,771			restricted: None,772			#[cfg(feature = "runtime-benchmarks")]773			permissive: false,774		};775		self.nesting.as_ref().unwrap_or(&DEFAULT)776	}777}778779/// Inner set for collections allowed to nest.780type OwnerRestrictedSetInner = BoundedBTreeSet<CollectionId, ConstU32<16>>;781782/// Wraper for collections set allowing nest.783#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]784#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]785#[derivative(Debug)]786pub struct OwnerRestrictedSet(787	#[cfg_attr(feature = "serde1", serde(with = "bounded::set_serde"))]788	#[derivative(Debug(format_with = "bounded::set_debug"))]789	pub OwnerRestrictedSetInner,790);791792impl OwnerRestrictedSet {793	/// Create new set.794	pub fn new() -> Self {795		Self(Default::default())796	}797}798impl core::ops::Deref for OwnerRestrictedSet {799	type Target = OwnerRestrictedSetInner;800	fn deref(&self) -> &Self::Target {801		&self.0802	}803}804impl core::ops::DerefMut for OwnerRestrictedSet {805	fn deref_mut(&mut self) -> &mut Self::Target {806		&mut self.0807	}808}809810/// Part of collection permissions, if set, defines who is able to nest tokens into other tokens.811#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]812#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]813#[derivative(Debug)]814pub struct NestingPermissions {815	/// Owner of token can nest tokens under it.816	pub token_owner: bool,817	/// Admin of token collection can nest tokens under token.818	pub collection_admin: bool,819	/// If set - only tokens from specified collections can be nested.820	pub restricted: Option<OwnerRestrictedSet>,821822	#[cfg(feature = "runtime-benchmarks")]823	/// Anyone can nest tokens, mutually exclusive with `token_owner`, `admin`.824	pub permissive: bool,825}826827/// Enum denominating how often can sponsoring occur if it is enabled.828///829/// Used for [`collection limits`](CollectionLimits).830#[derive(Encode, Decode, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]831#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]832pub enum SponsoringRateLimit {833	/// Sponsoring is disabled, and the collection sponsor will not pay for transactions834	SponsoringDisabled,835	/// Once per how many blocks can sponsorship of a transaction type occur836	Blocks(u32),837}838839/// Data used to describe an NFT at creation.840#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]841#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]842#[derivative(Debug)]843pub struct CreateNftData {844	/// Key-value pairs used to describe the token as metadata845	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]846	#[derivative(Debug(format_with = "bounded::vec_debug"))]847	/// Properties that wil be assignet to created item.848	pub properties: CollectionPropertiesVec,849}850851/// Data used to describe a Fungible token at creation.852#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq, TypeInfo)]853#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]854pub struct CreateFungibleData {855	/// Number of fungible coins minted856	pub value: u128,857}858859/// Data used to describe a Refungible token at creation.860#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]861#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]862#[derivative(Debug)]863pub struct CreateReFungibleData {864	/// Number of pieces the RFT is split into865	pub pieces: u128,866867	/// Key-value pairs used to describe the token as metadata868	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]869	#[derivative(Debug(format_with = "bounded::vec_debug"))]870	pub properties: CollectionPropertiesVec,871}872873// TODO: remove this.874#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]875#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]876pub enum MetaUpdatePermission {877	ItemOwner,878	Admin,879	None,880}881882/// Enum holding data used for creation of all three item types.883/// Unified data for create item.884#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]885#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]886pub enum CreateItemData {887	/// Data for create NFT.888	NFT(CreateNftData),889	/// Data for create Fungible item.890	Fungible(CreateFungibleData),891	/// Data for create ReFungible item.892	ReFungible(CreateReFungibleData),893}894895/// Extended data for create NFT.896#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]897#[derivative(Debug)]898pub struct CreateNftExData<CrossAccountId> {899	/// Properties that wil be assignet to created item.900	#[derivative(Debug(format_with = "bounded::vec_debug"))]901	pub properties: CollectionPropertiesVec,902903	/// Owner of creating item.904	pub owner: CrossAccountId,905}906907/// Extended data for create ReFungible item.908#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]909#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]910pub struct CreateRefungibleExMultipleOwners<CrossAccountId> {911	#[derivative(Debug(format_with = "bounded::map_debug"))]912	pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,913	#[derivative(Debug(format_with = "bounded::vec_debug"))]914	pub properties: CollectionPropertiesVec,915}916917/// Extended data for create ReFungible item.918#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]919#[derivative(Debug(bound = "CrossAccountId: fmt::Debug"))]920pub struct CreateRefungibleExSingleOwner<CrossAccountId> {921	pub user: CrossAccountId,922	pub pieces: u128,923	#[derivative(Debug(format_with = "bounded::vec_debug"))]924	pub properties: CollectionPropertiesVec,925}926927/// Unified extended data for creating item.928#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]929#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]930pub enum CreateItemExData<CrossAccountId> {931	/// Extended data for create NFT.932	NFT(933		#[derivative(Debug(format_with = "bounded::vec_debug"))]934		BoundedVec<CreateNftExData<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,935	),936937	/// Extended data for create Fungible item.938	Fungible(939		#[derivative(Debug(format_with = "bounded::map_debug"))]940		BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,941	),942943	/// Extended data for create ReFungible item in case of944	/// many tokens, each may have only one owner945	RefungibleMultipleItems(946		#[derivative(Debug(format_with = "bounded::vec_debug"))]947		BoundedVec<CreateRefungibleExSingleOwner<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,948	),949950	/// Extended data for create ReFungible item in case of951	/// single token, which may have many owners952	RefungibleMultipleOwners(CreateRefungibleExMultipleOwners<CrossAccountId>),953}954955impl From<CreateNftData> for CreateItemData {956	fn from(item: CreateNftData) -> Self {957		CreateItemData::NFT(item)958	}959}960961impl From<CreateReFungibleData> for CreateItemData {962	fn from(item: CreateReFungibleData) -> Self {963		CreateItemData::ReFungible(item)964	}965}966967impl From<CreateFungibleData> for CreateItemData {968	fn from(item: CreateFungibleData) -> Self {969		CreateItemData::Fungible(item)970	}971}972973/// Token's address, dictated by its collection and token IDs.974#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]975#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]976// todo possibly rename to be used generally as an address pair977pub struct TokenChild {978	/// Token id.979	pub token: TokenId,980981	/// Collection id.982	pub collection: CollectionId,983}984985/// Collection statistics.986#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]987#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]988pub struct CollectionStats {989	/// Number of created items.990	pub created: u32,991992	/// Number of burned items.993	pub destroyed: u32,994995	/// Number of current items.996	pub alive: u32,997}998999/// This type works like [`PhantomData`] but supports generating _scale-info_ descriptions to generate node metadata.1000#[derive(Encode, Decode, Clone, Debug)]1001#[cfg_attr(feature = "std", derive(PartialEq))]1002pub struct PhantomType<T>(core::marker::PhantomData<T>);10031004impl<T: TypeInfo + 'static> TypeInfo for PhantomType<T> {1005	type Identity = PhantomType<T>;10061007	fn type_info() -> scale_info::Type {1008		use scale_info::{1009			Type, Path,1010			build::{FieldsBuilder, UnnamedFields},1011			form::MetaForm,1012			type_params,1013		};1014		Type::builder()1015			.path(Path::new("up_data_structs", "PhantomType"))1016			.type_params(type_params!(T))1017			.composite(1018				<FieldsBuilder<MetaForm, UnnamedFields>>::default().field(|b| b.ty::<[T; 0]>()),1019			)1020	}1021}1022impl<T> MaxEncodedLen for PhantomType<T> {1023	fn max_encoded_len() -> usize {1024		01025	}1026}10271028/// Bounded vector of bytes.1029pub type BoundedBytes<S> = BoundedVec<u8, S>;10301031/// Extra properties for external collections.1032pub type AuxPropertyValue = BoundedBytes<ConstU32<MAX_AUX_PROPERTY_VALUE_LENGTH>>;10331034/// Property key.1035pub type PropertyKey = BoundedBytes<ConstU32<MAX_PROPERTY_KEY_LENGTH>>;10361037/// Property value.1038pub type PropertyValue = BoundedBytes<ConstU32<MAX_PROPERTY_VALUE_LENGTH>>;10391040/// Property permission.1041#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone, Default)]1042#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1043pub struct PropertyPermission {1044	/// Permission to change the property and property permission.1045	///1046	/// If it **false** then you can not change corresponding property even if [`collection_admin`] and [`token_owner`] are **true**.1047	pub mutable: bool,10481049	/// Change permission for the collection administrator.1050	pub collection_admin: bool,10511052	/// Permission to change the property for the owner of the token.1053	pub token_owner: bool,1054}10551056impl PropertyPermission {1057	/// Creates mutable property permission but changes restricted for collection admin and token owner.1058	pub fn none() -> Self {1059		Self {1060			mutable: true,1061			collection_admin: false,1062			token_owner: false,1063		}1064	}1065}10661067/// Property is simpl key-value record.1068#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, MaxEncodedLen)]1069#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1070pub struct Property {1071	/// Property key.1072	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1073	pub key: PropertyKey,10741075	/// Property value.1076	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1077	pub value: PropertyValue,1078}10791080impl Into<(PropertyKey, PropertyValue)> for Property {1081	fn into(self) -> (PropertyKey, PropertyValue) {1082		(self.key, self.value)1083	}1084}10851086/// Record for proprty key permission.1087#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone)]1088#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1089pub struct PropertyKeyPermission {1090	/// Key.1091	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1092	pub key: PropertyKey,10931094	/// Permission.1095	pub permission: PropertyPermission,1096}10971098impl Into<(PropertyKey, PropertyPermission)> for PropertyKeyPermission {1099	fn into(self) -> (PropertyKey, PropertyPermission) {1100		(self.key, self.permission)1101	}1102}11031104/// Errors for properties actions.1105#[derive(Debug)]1106pub enum PropertiesError {1107	/// The space allocated for properties has run out.1108	///1109	/// * Limit for colection - [`MAX_COLLECTION_PROPERTIES_SIZE`].1110	/// * Limit for token - [`MAX_TOKEN_PROPERTIES_SIZE`].1111	NoSpaceForProperty,11121113	/// The property limit has been reached.1114	///1115	/// * Limit - [`MAX_PROPERTIES_PER_ITEM`].1116	PropertyLimitReached,11171118	/// Property key contains not allowed character.1119	InvalidCharacterInPropertyKey,11201121	/// Property key length is too long.1122	///1123	/// * Limit - [`MAX_PROPERTY_KEY_LENGTH`].1124	PropertyKeyIsTooLong,11251126	/// Property key is empty.1127	EmptyPropertyKey,1128}11291130/// Token owner error: it could be either `NotFound` ot `MultipleOwners`.1131#[derive(Debug)]1132pub enum TokenOwnerError {1133	NotFound,1134	MultipleOwners,1135}11361137/// Marker for scope of property.1138///1139/// Scoped property can't be changed by user. Used for external collections.1140#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Clone, Copy)]1141pub enum PropertyScope {1142	None,1143	Rmrk,1144}11451146impl PropertyScope {1147	pub fn prefix(&self) -> &'static [u8] {1148		match self {1149			Self::None => b"",1150			Self::Rmrk => b"rmrk:",1151		}1152	}1153	/// Apply scope to property key.1154	pub fn apply(self, key: PropertyKey) -> Result<PropertyKey, PropertiesError> {1155		let prefix = self.prefix();1156		if prefix == b"" {1157			return Ok(key);1158		}1159		[prefix, key.as_slice()]1160			.concat()1161			.try_into()1162			.map_err(|_| PropertiesError::PropertyKeyIsTooLong)1163	}1164}11651166/// Trait for operate with properties.1167pub trait TrySetProperty: Sized {1168	type Value;11691170	/// Try to set property with scope.1171	fn try_scoped_set(1172		&mut self,1173		scope: PropertyScope,1174		key: PropertyKey,1175		value: Self::Value,1176	) -> Result<Option<Self::Value>, PropertiesError>;11771178	/// Try to set property with scope from iterator.1179	fn try_scoped_set_from_iter<I, KV>(1180		&mut self,1181		scope: PropertyScope,1182		iter: I,1183	) -> Result<(), PropertiesError>1184	where1185		I: Iterator<Item = KV>,1186		KV: Into<(PropertyKey, Self::Value)>,1187	{1188		for kv in iter {1189			let (key, value) = kv.into();1190			self.try_scoped_set(scope, key, value)?;1191		}11921193		Ok(())1194	}11951196	/// Try to set property.1197	fn try_set(1198		&mut self,1199		key: PropertyKey,1200		value: Self::Value,1201	) -> Result<Option<Self::Value>, PropertiesError> {1202		self.try_scoped_set(PropertyScope::None, key, value)1203	}12041205	/// Try to set property from iterator.1206	fn try_set_from_iter<I, KV>(&mut self, iter: I) -> Result<(), PropertiesError>1207	where1208		I: Iterator<Item = KV>,1209		KV: Into<(PropertyKey, Self::Value)>,1210	{1211		self.try_scoped_set_from_iter(PropertyScope::None, iter)1212	}1213}12141215/// Wrapped map for storing properties.1216#[derive(Encode, Decode, TypeInfo, Derivative, Clone, PartialEq, MaxEncodedLen)]1217#[derivative(Default(bound = ""))]1218pub struct PropertiesMap<Value>(1219	BoundedBTreeMap<PropertyKey, Value, ConstU32<MAX_PROPERTIES_PER_ITEM>>,1220);12211222impl<Value> PropertiesMap<Value> {1223	/// Create new property map.1224	pub fn new() -> Self {1225		Self(BoundedBTreeMap::new())1226	}12271228	/// Remove property from map.1229	pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<Value>, PropertiesError> {1230		Self::check_property_key(key)?;12311232		Ok(self.0.remove(key))1233	}12341235	/// Get property with appropriate key from map.1236	pub fn get(&self, key: &PropertyKey) -> Option<&Value> {1237		self.0.get(key)1238	}12391240	/// Check if map contains key.1241	pub fn contains_key(&self, key: &PropertyKey) -> bool {1242		self.0.contains_key(key)1243	}12441245	/// Check if map contains key with key validation.1246	fn check_property_key(key: &PropertyKey) -> Result<(), PropertiesError> {1247		if key.is_empty() {1248			return Err(PropertiesError::EmptyPropertyKey);1249		}12501251		for byte in key.as_slice().iter() {1252			let byte = *byte;12531254			if !byte.is_ascii_alphanumeric() && byte != b'_' && byte != b'-' && byte != b'.' {1255				return Err(PropertiesError::InvalidCharacterInPropertyKey);1256			}1257		}12581259		Ok(())1260	}12611262	pub fn values(&self) -> impl Iterator<Item = &Value> {1263		self.0.values()1264	}12651266	pub fn iter(&self) -> impl Iterator<Item = (&PropertyKey, &Value)> {1267		self.0.iter()1268	}1269}12701271impl<Value> IntoIterator for PropertiesMap<Value> {1272	type Item = (PropertyKey, Value);1273	type IntoIter = <1274		BoundedBTreeMap<1275			PropertyKey,1276			Value,1277			ConstU32<MAX_PROPERTIES_PER_ITEM>1278		> as IntoIterator1279	>::IntoIter;12801281	fn into_iter(self) -> Self::IntoIter {1282		self.0.into_iter()1283	}1284}12851286impl<Value> TrySetProperty for PropertiesMap<Value> {1287	type Value = Value;12881289	fn try_scoped_set(1290		&mut self,1291		scope: PropertyScope,1292		key: PropertyKey,1293		value: Self::Value,1294	) -> Result<Option<Self::Value>, PropertiesError> {1295		Self::check_property_key(&key)?;12961297		let key = scope.apply(key)?;1298		self.01299			.try_insert(key, value)1300			.map_err(|_| PropertiesError::PropertyLimitReached)1301	}1302}13031304/// Alias for property permissions map.1305pub type PropertiesPermissionMap = PropertiesMap<PropertyPermission>;13061307fn slice_size(data: &[u8]) -> u32 {1308	scoped_slice_size(PropertyScope::None, data)1309}1310fn scoped_slice_size(scope: PropertyScope, data: &[u8]) -> u32 {1311	use codec::Compact;1312	let prefix = scope.prefix();1313	<Compact<u32>>::encoded_size(&Compact(data.len() as u32 + prefix.len() as u32)) as u321314		+ data.len() as u321315		+ prefix.len() as u321316}13171318/// Wrapper for properties map with consumed space control.1319#[derive(Encode, Decode, TypeInfo, Clone, PartialEq)]1320pub struct Properties<const S: u32> {1321	map: PropertiesMap<PropertyValue>,1322	consumed_space: u32,1323	// May be not zero, previously served as a current S generic1324	_reserved: u32,1325}13261327impl<const S: u32> MaxEncodedLen for Properties<S> {1328	fn max_encoded_len() -> usize {1329		// len of map + len of consumed_space + len of space_limit1330		u32::max_encoded_len() * 3 + S as usize1331	}1332}13331334impl<const S: u32> Default for Properties<S> {1335	fn default() -> Self {1336		Self::new()1337	}1338}13391340impl<const S: u32> Properties<S> {1341	/// Create new properies container.1342	pub fn new() -> Self {1343		Self {1344			map: PropertiesMap::new(),1345			consumed_space: 0,1346			_reserved: 0,1347		}1348	}13491350	/// Remove propery with appropiate key.1351	pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<PropertyValue>, PropertiesError> {1352		let value = self.map.remove(key)?;13531354		if let Some(ref value) = value {1355			let kv_len = slice_size(key) + slice_size(value);1356			self.consumed_space = self.consumed_space.saturating_sub(kv_len);1357		}13581359		Ok(value)1360	}13611362	/// Get property with appropriate key.1363	pub fn get(&self, key: &PropertyKey) -> Option<&PropertyValue> {1364		self.map.get(key)1365	}13661367	/// Recomputes the consumed space for the current properties state.1368	/// Needed to repair a token due to a bug fixed in the [PR #733](https://github.com/UniqueNetwork/unique-chain/pull/773).1369	pub fn recompute_consumed_space(&mut self) {1370		self.consumed_space = self1371			.map1372			.iter()1373			.map(|(key, value)| slice_size(key) + slice_size(value))1374			.sum();1375	}1376}13771378impl<const S: u32> IntoIterator for Properties<S> {1379	type Item = (PropertyKey, PropertyValue);1380	type IntoIter = <PropertiesMap<PropertyValue> as IntoIterator>::IntoIter;13811382	fn into_iter(self) -> Self::IntoIter {1383		self.map.into_iter()1384	}1385}13861387impl<const S: u32> TrySetProperty for Properties<S> {1388	type Value = PropertyValue;13891390	fn try_scoped_set(1391		&mut self,1392		scope: PropertyScope,1393		key: PropertyKey,1394		value: Self::Value,1395	) -> Result<Option<Self::Value>, PropertiesError> {1396		let key_size = scoped_slice_size(scope, &key);1397		let value_size = slice_size(&value) as u32;13981399		if self.consumed_space + value_size + key_size > S && !cfg!(feature = "runtime-benchmarks")1400		{1401			return Err(PropertiesError::NoSpaceForProperty);1402		}14031404		let old_value = self.map.try_scoped_set(scope, key, value)?;14051406		if let Some(old_value) = old_value.as_ref() {1407			let old_value_size = slice_size(&old_value);1408			self.consumed_space = self.consumed_space.saturating_sub(old_value_size) + value_size;1409		} else {1410			self.consumed_space += key_size + value_size;1411		}14121413		Ok(old_value)1414	}1415}14161417pub type CollectionProperties = Properties<MAX_COLLECTION_PROPERTIES_SIZE>;1418pub type TokenProperties = Properties<MAX_TOKEN_PROPERTIES_SIZE>;14191420#[cfg(test)]1421mod tests {1422	use super::*;1423	use codec::IoReader;14241425	#[test]1426	fn rpc_collection_supports_decoding_old_versions() {1427		let encoded_rpc_collection: [u8; 1013] = [1428			0, 1, 250, 241, 137, 120, 188, 29, 94, 210, 193, 237, 186, 22, 203, 241, 52, 248, 167,1429			235, 241, 211, 236, 28, 138, 156, 59, 160, 156, 105, 39, 247, 207, 101, 0, 0, 48, 65,1430			0, 73, 0, 32, 0, 67, 0, 114, 0, 101, 0, 97, 0, 116, 0, 105, 0, 111, 0, 110, 0, 115, 0,1431			252, 65, 0, 32, 0, 112, 0, 105, 0, 101, 0, 99, 0, 101, 0, 32, 0, 111, 0, 102, 0, 32, 0,1432			97, 0, 32, 0, 109, 0, 97, 0, 99, 0, 104, 0, 105, 0, 110, 0, 101, 0, 32, 0, 109, 0, 105,1433			0, 110, 0, 100, 0, 46, 0, 32, 0, 69, 0, 118, 0, 101, 0, 114, 0, 121, 0, 32, 0, 78, 0,1434			70, 0, 84, 0, 32, 0, 105, 0, 115, 0, 32, 0, 109, 0, 97, 0, 100, 0, 101, 0, 32, 0, 101,1435			0, 120, 0, 99, 0, 108, 0, 117, 0, 115, 0, 105, 0, 118, 0, 101, 0, 108, 0, 121, 0, 32,1436			0, 98, 0, 121, 0, 32, 0, 65, 0, 73, 0, 46, 0, 12, 65, 73, 67, 0, 0, 1, 0, 0, 0, 0, 0,1437			0, 0, 0, 0, 0, 17, 1, 123, 34, 99, 111, 108, 108, 101, 99, 116, 105, 111, 110, 67, 111,1438			118, 101, 114, 34, 58, 34, 81, 109, 98, 52, 104, 122, 76, 101, 51, 49, 102, 98, 71, 74,1439			77, 89, 68, 82, 88, 84, 115, 107, 56, 49, 76, 103, 76, 97, 88, 76, 69, 112, 121, 97,1440			122, 102, 66, 85, 103, 111, 110, 118, 49, 118, 84, 85, 34, 125, 125, 11, 123, 34, 110,1441			101, 115, 116, 101, 100, 34, 58, 123, 34, 111, 110, 67, 104, 97, 105, 110, 77, 101,1442			116, 97, 68, 97, 116, 97, 34, 58, 123, 34, 110, 101, 115, 116, 101, 100, 34, 58, 123,1443			34, 78, 70, 84, 77, 101, 116, 97, 34, 58, 123, 34, 102, 105, 101, 108, 100, 115, 34,1444			58, 123, 34, 105, 112, 102, 115, 74, 115, 111, 110, 34, 58, 123, 34, 105, 100, 34, 58,1445			49, 44, 34, 114, 117, 108, 101, 34, 58, 34, 114, 101, 113, 117, 105, 114, 101, 100, 34,1446			44, 34, 116, 121, 112, 101, 34, 58, 34, 115, 116, 114, 105, 110, 103, 34, 125, 44, 34,1447			67, 111, 108, 111, 114, 34, 58, 123, 34, 105, 100, 34, 58, 50, 44, 34, 114, 117, 108,1448			101, 34, 58, 34, 114, 101, 113, 117, 105, 114, 101, 100, 34, 44, 34, 116, 121, 112,1449			101, 34, 58, 34, 67, 111, 108, 111, 114, 34, 125, 44, 34, 73, 110, 116, 101, 110, 115,1450			105, 111, 110, 115, 34, 58, 123, 34, 105, 100, 34, 58, 51, 44, 34, 114, 117, 108, 101,1451			34, 58, 34, 114, 101, 113, 117, 105, 114, 101, 100, 34, 44, 34, 116, 121, 112, 101, 34,1452			58, 34, 73, 110, 116, 101, 110, 115, 105, 111, 110, 115, 34, 125, 44, 34, 77, 111, 111,1453			100, 34, 58, 123, 34, 105, 100, 34, 58, 52, 44, 34, 114, 117, 108, 101, 34, 58, 34,1454			114, 101, 113, 117, 105, 114, 101, 100, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 77,1455			111, 111, 100, 34, 125, 125, 125, 44, 34, 67, 111, 108, 111, 114, 34, 58, 123, 34, 111,1456			112, 116, 105, 111, 110, 115, 34, 58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 34,1457			123, 92, 34, 101, 110, 92, 34, 58, 92, 34, 67, 111, 108, 111, 114, 101, 100, 92, 34,1458			125, 34, 44, 34, 102, 105, 101, 108, 100, 50, 34, 58, 34, 123, 92, 34, 101, 110, 92,1459			34, 58, 92, 34, 66, 108, 97, 99, 107, 38, 87, 104, 105, 116, 101, 92, 34, 125, 34, 125,1460			44, 34, 118, 97, 108, 117, 101, 115, 34, 58, 123, 34, 102, 105, 101, 108, 100, 49, 34,1461			58, 48, 44, 34, 102, 105, 101, 108, 100, 50, 34, 58, 49, 125, 125, 44, 34, 73, 110,1462			116, 101, 110, 115, 105, 111, 110, 115, 34, 58, 123, 34, 111, 112, 116, 105, 111, 110,1463			115, 34, 58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 34, 123, 92, 34, 101, 110,1464			92, 34, 58, 92, 34, 101, 118, 105, 108, 92, 34, 125, 34, 44, 34, 102, 105, 101, 108,1465			100, 50, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92, 34, 103, 111, 111, 100, 92,1466			34, 125, 34, 44, 34, 102, 105, 101, 108, 100, 51, 34, 58, 34, 123, 92, 34, 101, 110,1467			92, 34, 58, 92, 34, 110, 101, 117, 116, 114, 97, 108, 92, 34, 125, 34, 125, 44, 34,1468			118, 97, 108, 117, 101, 115, 34, 58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 48,1469			44, 34, 102, 105, 101, 108, 100, 50, 34, 58, 49, 44, 34, 102, 105, 101, 108, 100, 51,1470			34, 58, 50, 125, 125, 44, 34, 77, 111, 111, 100, 34, 58, 123, 34, 111, 112, 116, 105,1471			111, 110, 115, 34, 58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 34, 123, 92, 34,1472			101, 110, 92, 34, 58, 92, 34, 65, 98, 115, 116, 114, 97, 99, 116, 92, 34, 125, 34, 44,1473			34, 102, 105, 101, 108, 100, 50, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92, 34,1474			85, 110, 99, 97, 110, 110, 101, 121, 32, 118, 97, 108, 108, 101, 121, 92, 34, 125, 34,1475			44, 34, 102, 105, 101, 108, 100, 51, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92,1476			34, 83, 117, 114, 114, 101, 97, 108, 105, 115, 116, 92, 34, 125, 34, 125, 44, 34, 118,1477			97, 108, 117, 101, 115, 34, 58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 48, 44,1478			34, 102, 105, 101, 108, 100, 50, 34, 58, 49, 44, 34, 102, 105, 101, 108, 100, 51, 34,1479			58, 50, 125, 125, 125, 125, 125, 125, 0,1480		];1481		let mut bytes = IoReader(encoded_rpc_collection.as_slice());1482		CollectionVersion1::<[u8; 34]>::decode(&mut bytes).unwrap();1483	}14841485	#[test]1486	fn rpc_collection_supports_decoding_new_versions() {1487		let encoded_rpc_collection: [u8; 1576] = [1488			0, 1, 238, 236, 179, 149, 150, 47, 71, 194, 69, 174, 250, 116, 251, 148, 90, 15, 56,1489			220, 91, 79, 49, 79, 45, 197, 171, 98, 14, 171, 80, 23, 58, 92, 0, 96, 77, 0, 105, 0,1490			110, 0, 116, 0, 70, 0, 101, 0, 115, 0, 116, 0, 32, 0, 83, 0, 121, 0, 109, 0, 109, 0,1491			101, 0, 116, 0, 114, 0, 121, 0, 32, 0, 66, 0, 114, 0, 101, 0, 97, 0, 99, 0, 104, 0,1492			113, 3, 83, 0, 121, 0, 109, 0, 109, 0, 101, 0, 116, 0, 114, 0, 121, 0, 32, 0, 104, 0,1493			97, 0, 115, 0, 32, 0, 115, 0, 111, 0, 109, 0, 101, 0, 116, 0, 104, 0, 105, 0, 110, 0,1494			103, 0, 32, 0, 105, 0, 110, 0, 116, 0, 111, 0, 120, 0, 105, 0, 99, 0, 97, 0, 116, 0,1495			105, 0, 110, 0, 103, 0, 32, 0, 116, 0, 104, 0, 97, 0, 116, 0, 32, 0, 100, 0, 114, 0,1496			97, 0, 119, 0, 115, 0, 32, 0, 121, 0, 111, 0, 117, 0, 32, 0, 105, 0, 110, 0, 46, 0, 10,1497			0, 73, 0, 110, 0, 115, 0, 112, 0, 105, 0, 114, 0, 101, 0, 100, 0, 32, 0, 98, 0, 121, 0,1498			32, 0, 116, 0, 104, 0, 101, 0, 32, 0, 112, 0, 101, 0, 114, 0, 102, 0, 101, 0, 99, 0,1499			116, 0, 105, 0, 111, 0, 110, 0, 32, 0, 111, 0, 102, 0, 32, 0, 116, 0, 104, 0, 101, 0,1500			32, 0, 115, 0, 121, 0, 109, 0, 109, 0, 101, 0, 116, 0, 114, 0, 121, 0, 44, 0, 32, 0,1501			73, 0, 32, 0, 104, 0, 97, 0, 118, 0, 101, 0, 32, 0, 99, 0, 114, 0, 101, 0, 97, 0, 116,1502			0, 101, 0, 100, 0, 32, 0, 115, 0, 121, 0, 109, 0, 109, 0, 101, 0, 116, 0, 114, 0, 105,1503			0, 99, 0, 97, 0, 108, 0, 32, 0, 105, 0, 109, 0, 97, 0, 103, 0, 101, 0, 115, 0, 32, 0,1504			111, 0, 102, 0, 32, 0, 115, 0, 101, 0, 118, 0, 101, 0, 114, 0, 97, 0, 108, 0, 32, 0,1505			118, 0, 101, 0, 114, 0, 116, 0, 105, 0, 99, 0, 101, 0, 115, 0, 44, 0, 32, 0, 98, 0,1506			117, 0, 116, 0, 32, 0, 115, 0, 111, 0, 109, 0, 101, 0, 32, 0, 115, 0, 121, 0, 109, 0,1507			109, 0, 101, 0, 116, 0, 114, 0, 121, 0, 32, 0, 98, 0, 114, 0, 101, 0, 97, 0, 99, 0,1508			104, 0, 101, 0, 115, 0, 32, 0, 97, 0, 110, 0, 100, 0, 32, 0, 99, 0, 111, 0, 108, 0,1509			111, 0, 114, 0, 115, 0, 32, 0, 116, 0, 104, 0, 97, 0, 116, 0, 32, 0, 109, 0, 97, 0,1510			107, 0, 101, 0, 32, 0, 101, 0, 97, 0, 99, 0, 104, 0, 32, 0, 105, 0, 109, 0, 97, 0, 103,1511			0, 101, 0, 32, 0, 85, 0, 78, 0, 73, 0, 81, 0, 85, 0, 69, 0, 46, 0, 12, 83, 121, 66, 0,1512			0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 4, 56, 95, 111, 108, 100, 95, 99,1513			111, 110, 115, 116, 68, 97, 116, 97, 0, 1, 0, 12, 92, 95, 111, 108, 100, 95, 99, 111,1514			110, 115, 116, 79, 110, 67, 104, 97, 105, 110, 83, 99, 104, 101, 109, 97, 97, 13, 123,1515			34, 110, 101, 115, 116, 101, 100, 34, 58, 123, 34, 111, 110, 67, 104, 97, 105, 110, 77,1516			101, 116, 97, 68, 97, 116, 97, 34, 58, 123, 34, 110, 101, 115, 116, 101, 100, 34, 58,1517			123, 34, 78, 70, 84, 77, 101, 116, 97, 34, 58, 123, 34, 102, 105, 101, 108, 100, 115,1518			34, 58, 123, 34, 105, 112, 102, 115, 74, 115, 111, 110, 34, 58, 123, 34, 105, 100, 34,1519			58, 49, 44, 34, 114, 117, 108, 101, 34, 58, 34, 114, 101, 113, 117, 105, 114, 101, 100,1520			34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 115, 116, 114, 105, 110, 103, 34, 125, 44,1521			34, 67, 111, 108, 111, 114, 34, 58, 123, 34, 105, 100, 34, 58, 50, 44, 34, 114, 117,1522			108, 101, 34, 58, 34, 114, 101, 113, 117, 105, 114, 101, 100, 34, 44, 34, 116, 121,1523			112, 101, 34, 58, 34, 67, 111, 108, 111, 114, 34, 125, 44, 34, 83, 121, 109, 109, 101,1524			116, 114, 121, 32, 66, 114, 101, 97, 99, 104, 34, 58, 123, 34, 105, 100, 34, 58, 51,1525			44, 34, 114, 117, 108, 101, 34, 58, 34, 114, 101, 113, 117, 105, 114, 101, 100, 34, 44,1526			34, 116, 121, 112, 101, 34, 58, 34, 83, 121, 109, 109, 101, 116, 114, 121, 32, 66, 114,1527			101, 97, 99, 104, 34, 125, 44, 34, 86, 101, 114, 116, 105, 99, 101, 34, 58, 123, 34,1528			105, 100, 34, 58, 52, 44, 34, 114, 117, 108, 101, 34, 58, 34, 114, 101, 113, 117, 105,1529			114, 101, 100, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 86, 101, 114, 116, 105, 99,1530			101, 34, 125, 125, 125, 44, 34, 67, 111, 108, 111, 114, 34, 58, 123, 34, 111, 112, 116,1531			105, 111, 110, 115, 34, 58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 34, 123, 92,1532			34, 101, 110, 92, 34, 58, 92, 34, 49, 32, 32, 32, 92, 34, 125, 34, 44, 34, 102, 105,1533			101, 108, 100, 50, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92, 34, 50, 32, 92,1534			34, 125, 34, 44, 34, 102, 105, 101, 108, 100, 51, 34, 58, 34, 123, 92, 34, 101, 110,1535			92, 34, 58, 92, 34, 51, 92, 34, 125, 34, 125, 44, 34, 118, 97, 108, 117, 101, 115, 34,1536			58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 48, 44, 34, 102, 105, 101, 108, 100,1537			50, 34, 58, 49, 44, 34, 102, 105, 101, 108, 100, 51, 34, 58, 50, 125, 125, 44, 34, 83,1538			121, 109, 109, 101, 116, 114, 121, 32, 66, 114, 101, 97, 99, 104, 34, 58, 123, 34, 111,1539			112, 116, 105, 111, 110, 115, 34, 58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 34,1540			123, 92, 34, 101, 110, 92, 34, 58, 92, 34, 49, 92, 34, 125, 34, 44, 34, 102, 105, 101,1541			108, 100, 50, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92, 34, 50, 92, 34, 125,1542			34, 125, 44, 34, 118, 97, 108, 117, 101, 115, 34, 58, 123, 34, 102, 105, 101, 108, 100,1543			49, 34, 58, 48, 44, 34, 102, 105, 101, 108, 100, 50, 34, 58, 49, 125, 125, 44, 34, 86,1544			101, 114, 116, 105, 99, 101, 34, 58, 123, 34, 111, 112, 116, 105, 111, 110, 115, 34,1545			58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34,1546			58, 92, 34, 54, 92, 34, 125, 34, 44, 34, 102, 105, 101, 108, 100, 50, 34, 58, 34, 123,1547			92, 34, 101, 110, 92, 34, 58, 92, 34, 55, 92, 34, 125, 34, 44, 34, 102, 105, 101, 108,1548			100, 51, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92, 34, 56, 92, 34, 125, 34,1549			44, 34, 102, 105, 101, 108, 100, 52, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92,1550			34, 57, 92, 34, 125, 34, 44, 34, 102, 105, 101, 108, 100, 53, 34, 58, 34, 123, 92, 34,1551			101, 110, 92, 34, 58, 92, 34, 49, 48, 92, 34, 125, 34, 44, 34, 102, 105, 101, 108, 100,1552			54, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92, 34, 49, 49, 92, 34, 125, 34, 44,1553			34, 102, 105, 101, 108, 100, 55, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92, 34,1554			49, 50, 92, 34, 125, 34, 125, 44, 34, 118, 97, 108, 117, 101, 115, 34, 58, 123, 34,1555			102, 105, 101, 108, 100, 49, 34, 58, 48, 44, 34, 102, 105, 101, 108, 100, 50, 34, 58,1556			49, 44, 34, 102, 105, 101, 108, 100, 51, 34, 58, 50, 44, 34, 102, 105, 101, 108, 100,1557			52, 34, 58, 51, 44, 34, 102, 105, 101, 108, 100, 53, 34, 58, 52, 44, 34, 102, 105, 101,1558			108, 100, 54, 34, 58, 53, 44, 34, 102, 105, 101, 108, 100, 55, 34, 58, 54, 125, 125,1559			125, 125, 125, 125, 72, 95, 111, 108, 100, 95, 115, 99, 104, 101, 109, 97, 86, 101,1560			114, 115, 105, 111, 110, 24, 85, 110, 105, 113, 117, 101, 104, 95, 111, 108, 100, 95,1561			118, 97, 114, 105, 97, 98, 108, 101, 79, 110, 67, 104, 97, 105, 110, 83, 99, 104, 101,1562			109, 97, 17, 1, 123, 34, 99, 111, 108, 108, 101, 99, 116, 105, 111, 110, 67, 111, 118,1563			101, 114, 34, 58, 34, 81, 109, 82, 67, 77, 84, 109, 57, 118, 81, 107, 76, 89, 86, 65,1564			54, 54, 87, 80, 49, 75, 72, 57, 55, 106, 84, 76, 76, 115, 56, 74, 78, 86, 65, 114, 80,1565			66, 52, 56, 98, 106, 87, 84, 75, 74, 110, 34, 125, 0, 0, 0,1566		];1567		let mut bytes = IoReader(encoded_rpc_collection.as_slice());1568		RpcCollection::<[u8; 34]>::decode(&mut bytes).unwrap();1569	}1570}
after · primitives/data-structs/src/lib.rs
1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! # Primitives crate.18//!19//! This crate contains types, traits and constants.2021#![cfg_attr(not(feature = "std"), no_std)]2223use core::{24	convert::{TryFrom, TryInto},25	fmt,26	ops::Deref,27};28use frame_support::storage::{bounded_btree_map::BoundedBTreeMap, bounded_btree_set::BoundedBTreeSet};2930#[cfg(feature = "serde")]31use serde::{Serialize, Deserialize};3233use sp_core::U256;34use sp_runtime::{ArithmeticError, sp_std::prelude::Vec};35use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};36use bondrewd::Bitfields;37use frame_support::{BoundedVec, traits::ConstU32};38use derivative::Derivative;39use scale_info::TypeInfo;4041mod bondrewd_codec;42mod bounded;43pub mod budget;44pub mod mapping;45mod migration;4647/// Maximum of decimal points.48pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;4950/// Maximum pieces for refungible token.51pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;52pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;5354/// Maximum tokens for user.55pub const MAX_TOKEN_OWNERSHIP: u32 = if cfg!(not(feature = "limit-testing")) {56	100_00057} else {58	1059};6061/// Maximum for collections can be created.62pub const COLLECTION_NUMBER_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {63	100_00064} else {65	1066};6768/// Maximum for various custom data of token.69pub const CUSTOM_DATA_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {70	204871} else {72	1073};7475/// Maximum admins per collection.76pub const COLLECTION_ADMINS_LIMIT: u32 = 5;7778/// Maximum tokens per collection.79pub const COLLECTION_TOKEN_LIMIT: u32 = u32::MAX;8081/// Maximum tokens per account.82pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {83	1_000_00084} else {85	1086};8788/// Default timeout for transfer sponsoring NFT item.89pub const NFT_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;90/// Default timeout for transfer sponsoring fungible item.91pub const FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;92/// Default timeout for transfer sponsoring refungible item.93pub const REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;9495/// Default timeout for sponsored approving.96pub const SPONSOR_APPROVE_TIMEOUT: u32 = 5;9798// Schema limits99pub const OFFCHAIN_SCHEMA_LIMIT: u32 = 8192;100pub const VARIABLE_ON_CHAIN_SCHEMA_LIMIT: u32 = 8192;101pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 32768;102103// TODO: not used. Delete?104pub const COLLECTION_FIELD_LIMIT: u32 = CONST_ON_CHAIN_SCHEMA_LIMIT;105106/// Maximal length of a collection name.107pub const MAX_COLLECTION_NAME_LENGTH: u32 = 64;108109/// Maximal length of a collection description.110pub const MAX_COLLECTION_DESCRIPTION_LENGTH: u32 = 256;111112/// Maximal length of a token prefix.113pub const MAX_TOKEN_PREFIX_LENGTH: u32 = 16;114115/// Maximal length of a property key.116pub const MAX_PROPERTY_KEY_LENGTH: u32 = 256;117118/// Maximal length of a property value.119pub const MAX_PROPERTY_VALUE_LENGTH: u32 = 32768;120121/// A maximum number of token properties.122pub const MAX_PROPERTIES_PER_ITEM: u32 = 64;123124/// Maximal lenght of extended property value.125pub const MAX_AUX_PROPERTY_VALUE_LENGTH: u32 = 2048;126127/// Maximum size for all collection properties.128pub const MAX_COLLECTION_PROPERTIES_SIZE: u32 = 40960;129130/// Maximum size of all token properties.131pub const MAX_TOKEN_PROPERTIES_SIZE: u32 = 32768;132133/// How much items can be created per single134/// create_many call.135pub const MAX_ITEMS_PER_BATCH: u32 = 200;136137/// Used for limit bounded types of token custom data.138pub type CustomDataLimit = ConstU32<CUSTOM_DATA_LIMIT>;139140/// Collection id.141#[derive(142	Encode,143	Decode,144	PartialEq,145	Eq,146	PartialOrd,147	Ord,148	Clone,149	Copy,150	Debug,151	Default,152	TypeInfo,153	MaxEncodedLen,154)]155#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]156pub struct CollectionId(pub u32);157impl EncodeLike<u32> for CollectionId {}158impl EncodeLike<CollectionId> for u32 {}159160impl From<u32> for CollectionId {161	fn from(value: u32) -> Self {162		Self(value)163	}164}165166/// Token id.167#[derive(168	Encode,169	Decode,170	PartialEq,171	Eq,172	PartialOrd,173	Ord,174	Clone,175	Copy,176	Debug,177	Default,178	TypeInfo,179	MaxEncodedLen,180)]181#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]182pub struct TokenId(pub u32);183impl EncodeLike<u32> for TokenId {}184impl EncodeLike<TokenId> for u32 {}185186impl TokenId {187	/// Try to get next token id.188	///189	/// If next id cause overflow, then [`ArithmeticError::Overflow`] returned.190	pub fn try_next(self) -> Result<TokenId, ArithmeticError> {191		self.0192			.checked_add(1)193			.ok_or(ArithmeticError::Overflow)194			.map(Self)195	}196}197198impl From<TokenId> for U256 {199	fn from(t: TokenId) -> Self {200		t.0.into()201	}202}203204impl TryFrom<U256> for TokenId {205	type Error = &'static str;206207	fn try_from(value: U256) -> Result<Self, Self::Error> {208		Ok(TokenId(value.try_into().map_err(|_| "too large token id")?))209	}210}211212/// Token data.213#[struct_versioning::versioned(version = 2, upper)]214#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]215#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]216pub struct TokenData<CrossAccountId> {217	/// Properties of token.218	pub properties: Vec<Property>,219220	/// Token owner.221	pub owner: Option<CrossAccountId>,222223	/// Token pieces.224	#[version(2.., upper(0))]225	pub pieces: u128,226}227228// TODO: unused type229pub struct OverflowError;230impl From<OverflowError> for &'static str {231	fn from(_: OverflowError) -> Self {232		"overflow occured"233	}234}235236/// Alias for decimal points type.237pub type DecimalPoints = u8;238239/// Collection mode.240///241/// Collection can represent various types of tokens.242/// Each collection can contain only one type of tokens at a time.243/// This type helps to understand which tokens the collection contains.244#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]245#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]246pub enum CollectionMode {247	/// Non fungible tokens.248	NFT,249	/// Fungible tokens.250	Fungible(DecimalPoints),251	/// Refungible tokens.252	ReFungible,253}254255impl CollectionMode {256	/// Get collection mod as number.257	pub fn id(&self) -> u8 {258		match self {259			CollectionMode::NFT => 1,260			CollectionMode::Fungible(_) => 2,261			CollectionMode::ReFungible => 3,262		}263	}264}265266// TODO: unused trait267pub trait SponsoringResolve<AccountId, Call> {268	fn resolve(who: &AccountId, call: &Call) -> Option<AccountId>;269}270271/// Access mode for some token operations.272#[derive(Encode, Decode, Eq, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]273#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]274pub enum AccessMode {275	/// Access grant for owner and admins. Used as default.276	Normal,277	/// Like a [`Normal`](AccessMode::Normal) but also users in allow list.278	AllowList,279}280impl Default for AccessMode {281	fn default() -> Self {282		Self::Normal283	}284}285286// TODO: remove in future.287#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]288#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]289pub enum SchemaVersion {290	ImageURL,291	Unique,292}293impl Default for SchemaVersion {294	fn default() -> Self {295		Self::ImageURL296	}297}298299// TODO: unused type300#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, TypeInfo)]301#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]302pub struct Ownership<AccountId> {303	pub owner: AccountId,304	pub fraction: u128,305}306307/// The state of collection sponsorship.308#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]309#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]310pub enum SponsorshipState<AccountId> {311	/// The fees are applied to the transaction sender.312	Disabled,313	/// The sponsor is under consideration. Until the sponsor gives his consent,314	/// the fee will still be charged to sender.315	Unconfirmed(AccountId),316	/// Transactions are sponsored by specified account.317	Confirmed(AccountId),318}319320impl<AccountId> SponsorshipState<AccountId> {321	/// Get a sponsor of the collection who has confirmed his status.322	pub fn sponsor(&self) -> Option<&AccountId> {323		match self {324			Self::Confirmed(sponsor) => Some(sponsor),325			_ => None,326		}327	}328329	/// Get a sponsor of the collection who has pending or confirmed status.330	pub fn pending_sponsor(&self) -> Option<&AccountId> {331		match self {332			Self::Unconfirmed(sponsor) | Self::Confirmed(sponsor) => Some(sponsor),333			_ => None,334		}335	}336337	/// Whether the sponsorship is confirmed.338	pub fn confirmed(&self) -> bool {339		matches!(self, Self::Confirmed(_))340	}341}342343impl<T> Default for SponsorshipState<T> {344	fn default() -> Self {345		Self::Disabled346	}347}348349pub type CollectionName = BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>;350pub type CollectionDescription = BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>;351pub type CollectionTokenPrefix = BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>;352353#[derive(Bitfields, Clone, Copy, PartialEq, Eq, Debug, Default)]354#[bondrewd(enforce_bytes = 1)]355pub struct CollectionFlags {356	/// Tokens in foreign collections can be transferred, but not burnt357	#[bondrewd(bits = "0..1")]358	pub foreign: bool,359	/// Supports ERC721Metadata360	#[bondrewd(bits = "1..2")]361	pub erc721metadata: bool,362	/// External collections can't be managed using `unique` api363	#[bondrewd(bits = "7..8")]364	pub external: bool,365366	#[bondrewd(reserve, bits = "2..7")]367	pub reserved: u8,368}369bondrewd_codec!(CollectionFlags);370371/// Base structure for represent collection.372///373/// Used to provide basic functionality for all types of collections.374///375/// #### Note376/// Collection parameters, used in storage (see [`RpcCollection`] for the RPC version).377#[struct_versioning::versioned(version = 2, upper)]378#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen)]379pub struct Collection<AccountId> {380	/// Collection owner account.381	pub owner: AccountId,382383	/// Collection mode.384	pub mode: CollectionMode,385386	/// Access mode.387	#[version(..2)]388	pub access: AccessMode,389390	/// Collection name.391	pub name: CollectionName,392393	/// Collection description.394	pub description: CollectionDescription,395396	/// Token prefix.397	pub token_prefix: CollectionTokenPrefix,398399	#[version(..2)]400	pub mint_mode: bool,401402	#[version(..2)]403	pub offchain_schema: BoundedVec<u8, ConstU32<OFFCHAIN_SCHEMA_LIMIT>>,404405	#[version(..2)]406	pub schema_version: SchemaVersion,407408	/// The state of sponsorship of the collection.409	pub sponsorship: SponsorshipState<AccountId>,410411	/// Collection limits.412	pub limits: CollectionLimits,413414	/// Collection permissions.415	#[version(2.., upper(Default::default()))]416	pub permissions: CollectionPermissions,417418	#[version(2.., upper(Default::default()))]419	pub flags: CollectionFlags,420421	#[version(..2)]422	pub variable_on_chain_schema: BoundedVec<u8, ConstU32<VARIABLE_ON_CHAIN_SCHEMA_LIMIT>>,423424	#[version(..2)]425	pub const_on_chain_schema: BoundedVec<u8, ConstU32<CONST_ON_CHAIN_SCHEMA_LIMIT>>,426427	#[version(..2)]428	pub meta_update_permission: MetaUpdatePermission,429}430431#[derive(Debug, Encode, Decode, Clone, PartialEq, TypeInfo)]432#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]433pub struct RpcCollectionFlags {434	/// Is collection is foreign.435	pub foreign: bool,436	/// Collection supports ERC721Metadata.437	pub erc721metadata: bool,438}439440/// Collection parameters, used in RPC calls (see [`Collection`] for the storage version).441#[struct_versioning::versioned(version = 2, upper)]442#[derive(Debug, Encode, Decode, Clone, PartialEq, TypeInfo)]443#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]444pub struct RpcCollection<AccountId> {445	/// Collection owner account.446	pub owner: AccountId,447448	/// Collection mode.449	pub mode: CollectionMode,450451	/// Collection name.452	pub name: Vec<u16>,453454	/// Collection description.455	pub description: Vec<u16>,456457	/// Token prefix.458	pub token_prefix: Vec<u8>,459460	/// The state of sponsorship of the collection.461	pub sponsorship: SponsorshipState<AccountId>,462463	/// Collection limits.464	pub limits: CollectionLimits,465466	/// Collection permissions.467	pub permissions: CollectionPermissions,468469	/// Token property permissions.470	pub token_property_permissions: Vec<PropertyKeyPermission>,471472	/// Collection properties.473	pub properties: Vec<Property>,474475	/// Is collection read only.476	pub read_only: bool,477478	/// Extra collection flags479	#[version(2.., upper(RpcCollectionFlags {foreign: false, erc721metadata: false}))]480	pub flags: RpcCollectionFlags,481}482483impl<AccountId> From<CollectionVersion1<AccountId>> for RpcCollection<AccountId> {484	fn from(value: CollectionVersion1<AccountId>) -> Self {485		let CollectionVersion1 {486			name,487			description,488			owner,489			mode,490			access,491			token_prefix,492			mint_mode,493			sponsorship,494			limits,495			..496		} = value;497498		RpcCollection {499			name: name.into_inner(),500			description: description.into_inner(),501			owner,502			mode,503			token_prefix: token_prefix.into_inner(),504			sponsorship,505			limits,506			permissions: CollectionPermissions {507				access: Some(access),508				mint_mode: Some(mint_mode),509				nesting: None,510			},511			token_property_permissions: Vec::default(),512			properties: Vec::default(),513			read_only: true,514515			flags: RpcCollectionFlags {516				foreign: false,517				erc721metadata: false,518			},519		}520	}521}522523pub struct RawEncoded(Vec<u8>);524525impl codec::Decode for RawEncoded {526	fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {527		let mut out = Vec::new();528		while let Ok(v) = input.read_byte() {529			out.push(v);530		}531		Ok(Self(out))532	}533}534535impl Deref for RawEncoded {536	type Target = Vec<u8>;537538	fn deref(&self) -> &Self::Target {539		return &self.0;540	}541}542543/// Data used for create collection.544///545/// All fields are wrapped in [`Option`], where `None` means chain default.546#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, Derivative, MaxEncodedLen)]547#[derivative(Debug, Default(bound = ""))]548pub struct CreateCollectionData<AccountId> {549	/// Collection mode.550	#[derivative(Default(value = "CollectionMode::NFT"))]551	pub mode: CollectionMode,552553	/// Access mode.554	pub access: Option<AccessMode>,555556	/// Collection name.557	pub name: CollectionName,558559	/// Collection description.560	pub description: CollectionDescription,561562	/// Token prefix.563	pub token_prefix: CollectionTokenPrefix,564565	/// Pending collection sponsor.566	pub pending_sponsor: Option<AccountId>,567568	/// Collection limits.569	pub limits: Option<CollectionLimits>,570571	/// Collection permissions.572	pub permissions: Option<CollectionPermissions>,573574	/// Token property permissions.575	pub token_property_permissions: CollectionPropertiesPermissionsVec,576577	/// Collection properties.578	pub properties: CollectionPropertiesVec,579}580581/// Bounded vector of properties permissions. Max length is [`MAX_PROPERTIES_PER_ITEM`].582// TODO: maybe rename to PropertiesPermissionsVec583pub type CollectionPropertiesPermissionsVec =584	BoundedVec<PropertyKeyPermission, ConstU32<MAX_PROPERTIES_PER_ITEM>>;585586/// Bounded vector of properties. Max length is [`MAX_PROPERTIES_PER_ITEM`].587pub type CollectionPropertiesVec = BoundedVec<Property, ConstU32<MAX_PROPERTIES_PER_ITEM>>;588589/// Limits and restrictions of a collection.590///591/// All fields are wrapped in [`Option`], where `None` means chain default.592///593/// Update with `pallet_common::Pallet::clamp_limits`.594// IMPORTANT: When adding/removing fields from this struct - don't forget to also595#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]596#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]597// When adding/removing fields from this struct - don't forget to also update with `pallet_common::Pallet::clamp_limits`.598// TODO: move `pallet_common::Pallet::clamp_limits` into `impl CollectionLimits`.599// TODO: may be remove [`Option`] and **pub** from fields and create struct with default values.600pub struct CollectionLimits {601	/// How many tokens can a user have on one account.602	/// * Default - [`ACCOUNT_TOKEN_OWNERSHIP_LIMIT`].603	/// * Limit - [`MAX_TOKEN_OWNERSHIP`].604	pub account_token_ownership_limit: Option<u32>,605606	/// How many bytes of data are available for sponsorship.607	/// * Default - [`CUSTOM_DATA_LIMIT`].608	/// * Limit - [`CUSTOM_DATA_LIMIT`].609	pub sponsored_data_size: Option<u32>,610611	// FIXME should we delete this or repurpose it?612	/// Times in how many blocks we sponsor data.613	///614	/// If is `Some(v)` then **setVariableMetadata** is sponsored if there is `v` block between transactions.615	///616	/// * Default - [`SponsoringDisabled`](SponsoringRateLimit::SponsoringDisabled).617	/// * Limit - [`MAX_SPONSOR_TIMEOUT`].618	///619	/// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]620	pub sponsored_data_rate_limit: Option<SponsoringRateLimit>,621	/// Maximum amount of tokens inside the collection. Chain default: [`COLLECTION_TOKEN_LIMIT`]622623	/// How many tokens can be mined into this collection.624	///625	/// * Default - [`COLLECTION_TOKEN_LIMIT`].626	/// * Limit - [`COLLECTION_TOKEN_LIMIT`].627	pub token_limit: Option<u32>,628629	/// Timeouts for transfer sponsoring.630	///631	/// * Default632	///   - **Fungible** - [`FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT`]633	///   - **NFT** - [`NFT_SPONSOR_TRANSFER_TIMEOUT`]634	///   - **Refungible** - [`REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT`]635	/// * Limit - [`MAX_SPONSOR_TIMEOUT`].636	pub sponsor_transfer_timeout: Option<u32>,637638	/// Timeout for sponsoring an approval in passed blocks.639	///640	/// * Default - [`SPONSOR_APPROVE_TIMEOUT`].641	/// * Limit - [`MAX_SPONSOR_TIMEOUT`].642	pub sponsor_approve_timeout: Option<u32>,643644	/// Whether the collection owner of the collection can send tokens (which belong to other users).645	///646	/// * Default - **false**.647	pub owner_can_transfer: Option<bool>,648649	/// Can the collection owner burn other people's tokens.650	///651	/// * Default - **true**.652	pub owner_can_destroy: Option<bool>,653654	/// Is it possible to send tokens from this collection between users.655	///656	/// * Default - **true**.657	pub transfers_enabled: Option<bool>,658}659660impl CollectionLimits {661	pub fn with_default_limits(collection_type: CollectionMode) -> Self {662		CollectionLimits {663			account_token_ownership_limit: Some(ACCOUNT_TOKEN_OWNERSHIP_LIMIT),664			sponsored_data_size: Some(CUSTOM_DATA_LIMIT),665			sponsored_data_rate_limit: Some(SponsoringRateLimit::SponsoringDisabled),666			token_limit: Some(COLLECTION_TOKEN_LIMIT),667			sponsor_transfer_timeout: match collection_type {668				CollectionMode::NFT => Some(NFT_SPONSOR_TRANSFER_TIMEOUT),669				CollectionMode::ReFungible => Some(REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT),670				CollectionMode::Fungible(_) => Some(FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT),671			},672			sponsor_approve_timeout: Some(SPONSOR_APPROVE_TIMEOUT),673			owner_can_transfer: Some(false),674			owner_can_destroy: Some(true),675			transfers_enabled: Some(true),676		}677	}678679	/// Get effective value for [`account_token_ownership_limit`](self.account_token_ownership_limit).680	pub fn account_token_ownership_limit(&self) -> u32 {681		self.account_token_ownership_limit682			.unwrap_or(ACCOUNT_TOKEN_OWNERSHIP_LIMIT)683			.min(MAX_TOKEN_OWNERSHIP)684	}685686	/// Get effective value for [`sponsored_data_size`](self.sponsored_data_size).687	pub fn sponsored_data_size(&self) -> u32 {688		self.sponsored_data_size689			.unwrap_or(CUSTOM_DATA_LIMIT)690			.min(CUSTOM_DATA_LIMIT)691	}692693	/// Get effective value for [`token_limit`](self.token_limit).694	pub fn token_limit(&self) -> u32 {695		self.token_limit696			.unwrap_or(COLLECTION_TOKEN_LIMIT)697			.min(COLLECTION_TOKEN_LIMIT)698	}699700	// TODO: may be replace u32 to mode?701	/// Get effective value for [`sponsor_transfer_timeout`](self.sponsor_transfer_timeout).702	pub fn sponsor_transfer_timeout(&self, default: u32) -> u32 {703		self.sponsor_transfer_timeout704			.unwrap_or(default)705			.min(MAX_SPONSOR_TIMEOUT)706	}707708	/// Get effective value for [`sponsor_approve_timeout`](self.sponsor_approve_timeout).709	pub fn sponsor_approve_timeout(&self) -> u32 {710		self.sponsor_approve_timeout711			.unwrap_or(SPONSOR_APPROVE_TIMEOUT)712			.min(MAX_SPONSOR_TIMEOUT)713	}714715	/// Get effective value for [`owner_can_transfer`](self.owner_can_transfer).716	pub fn owner_can_transfer(&self) -> bool {717		self.owner_can_transfer.unwrap_or(false)718	}719720	/// Get effective value for [`owner_can_transfer_instaled`](self.owner_can_transfer_instaled).721	pub fn owner_can_transfer_instaled(&self) -> bool {722		self.owner_can_transfer.is_some()723	}724725	/// Get effective value for [`owner_can_destroy`](self.owner_can_destroy).726	pub fn owner_can_destroy(&self) -> bool {727		self.owner_can_destroy.unwrap_or(true)728	}729730	/// Get effective value for [`transfers_enabled`](self.transfers_enabled).731	pub fn transfers_enabled(&self) -> bool {732		self.transfers_enabled.unwrap_or(true)733	}734735	/// Get effective value for [`sponsored_data_rate_limit`](self.sponsored_data_rate_limit).736	pub fn sponsored_data_rate_limit(&self) -> Option<u32> {737		match self738			.sponsored_data_rate_limit739			.unwrap_or(SponsoringRateLimit::SponsoringDisabled)740		{741			SponsoringRateLimit::SponsoringDisabled => None,742			SponsoringRateLimit::Blocks(v) => Some(v.min(MAX_SPONSOR_TIMEOUT)),743		}744	}745}746747/// Permissions on certain operations within a collection.748///749/// Some fields are wrapped in [`Option`], where `None` means chain default.750///751/// Update with `pallet_common::Pallet::clamp_permissions`.752#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]753#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]754// When adding/removing fields from this struct - don't forget to also update `pallet_common::Pallet::clamp_permissions`.755// TODO: move `pallet_common::Pallet::clamp_permissions` into `impl CollectionPermissions`.756pub struct CollectionPermissions {757	/// Access mode.758	///759	/// * Default - [`AccessMode::Normal`].760	pub access: Option<AccessMode>,761762	/// Minting allowance.763	///764	/// * Default - **false**.765	pub mint_mode: Option<bool>,766767	/// Permissions for nesting.768	///769	/// * Default770	///   - `token_owner` - **false**771	///   - `collection_admin` - **false**772	///   - `restricted` - **None**773	pub nesting: Option<NestingPermissions>,774}775776impl CollectionPermissions {777	/// Get effective value for [`access`](self.access).778	pub fn access(&self) -> AccessMode {779		self.access.unwrap_or(AccessMode::Normal)780	}781782	/// Get effective value for [`mint_mode`](self.mint_mode).783	pub fn mint_mode(&self) -> bool {784		self.mint_mode.unwrap_or(false)785	}786787	/// Get effective value for [`nesting`](self.nesting).788	pub fn nesting(&self) -> &NestingPermissions {789		static DEFAULT: NestingPermissions = NestingPermissions {790			token_owner: false,791			collection_admin: false,792			restricted: None,793			#[cfg(feature = "runtime-benchmarks")]794			permissive: false,795		};796		self.nesting.as_ref().unwrap_or(&DEFAULT)797	}798}799800/// Inner set for collections allowed to nest.801type OwnerRestrictedSetInner = BoundedBTreeSet<CollectionId, ConstU32<16>>;802803/// Wraper for collections set allowing nest.804#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]805#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]806#[derivative(Debug)]807pub struct OwnerRestrictedSet(808	#[cfg_attr(feature = "serde1", serde(with = "bounded::set_serde"))]809	#[derivative(Debug(format_with = "bounded::set_debug"))]810	pub OwnerRestrictedSetInner,811);812813impl OwnerRestrictedSet {814	/// Create new set.815	pub fn new() -> Self {816		Self(Default::default())817	}818}819impl core::ops::Deref for OwnerRestrictedSet {820	type Target = OwnerRestrictedSetInner;821	fn deref(&self) -> &Self::Target {822		&self.0823	}824}825impl core::ops::DerefMut for OwnerRestrictedSet {826	fn deref_mut(&mut self) -> &mut Self::Target {827		&mut self.0828	}829}830831/// Part of collection permissions, if set, defines who is able to nest tokens into other tokens.832#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]833#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]834#[derivative(Debug)]835pub struct NestingPermissions {836	/// Owner of token can nest tokens under it.837	pub token_owner: bool,838	/// Admin of token collection can nest tokens under token.839	pub collection_admin: bool,840	/// If set - only tokens from specified collections can be nested.841	pub restricted: Option<OwnerRestrictedSet>,842843	#[cfg(feature = "runtime-benchmarks")]844	/// Anyone can nest tokens, mutually exclusive with `token_owner`, `admin`.845	pub permissive: bool,846}847848/// Enum denominating how often can sponsoring occur if it is enabled.849///850/// Used for [`collection limits`](CollectionLimits).851#[derive(Encode, Decode, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]852#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]853pub enum SponsoringRateLimit {854	/// Sponsoring is disabled, and the collection sponsor will not pay for transactions855	SponsoringDisabled,856	/// Once per how many blocks can sponsorship of a transaction type occur857	Blocks(u32),858}859860/// Data used to describe an NFT at creation.861#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]862#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]863#[derivative(Debug)]864pub struct CreateNftData {865	/// Key-value pairs used to describe the token as metadata866	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]867	#[derivative(Debug(format_with = "bounded::vec_debug"))]868	/// Properties that wil be assignet to created item.869	pub properties: CollectionPropertiesVec,870}871872/// Data used to describe a Fungible token at creation.873#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq, TypeInfo)]874#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]875pub struct CreateFungibleData {876	/// Number of fungible coins minted877	pub value: u128,878}879880/// Data used to describe a Refungible token at creation.881#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]882#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]883#[derivative(Debug)]884pub struct CreateReFungibleData {885	/// Number of pieces the RFT is split into886	pub pieces: u128,887888	/// Key-value pairs used to describe the token as metadata889	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]890	#[derivative(Debug(format_with = "bounded::vec_debug"))]891	pub properties: CollectionPropertiesVec,892}893894// TODO: remove this.895#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]896#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]897pub enum MetaUpdatePermission {898	ItemOwner,899	Admin,900	None,901}902903/// Enum holding data used for creation of all three item types.904/// Unified data for create item.905#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]906#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]907pub enum CreateItemData {908	/// Data for create NFT.909	NFT(CreateNftData),910	/// Data for create Fungible item.911	Fungible(CreateFungibleData),912	/// Data for create ReFungible item.913	ReFungible(CreateReFungibleData),914}915916/// Extended data for create NFT.917#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]918#[derivative(Debug)]919pub struct CreateNftExData<CrossAccountId> {920	/// Properties that wil be assignet to created item.921	#[derivative(Debug(format_with = "bounded::vec_debug"))]922	pub properties: CollectionPropertiesVec,923924	/// Owner of creating item.925	pub owner: CrossAccountId,926}927928/// Extended data for create ReFungible item.929#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]930#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]931pub struct CreateRefungibleExMultipleOwners<CrossAccountId> {932	#[derivative(Debug(format_with = "bounded::map_debug"))]933	pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,934	#[derivative(Debug(format_with = "bounded::vec_debug"))]935	pub properties: CollectionPropertiesVec,936}937938/// Extended data for create ReFungible item.939#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]940#[derivative(Debug(bound = "CrossAccountId: fmt::Debug"))]941pub struct CreateRefungibleExSingleOwner<CrossAccountId> {942	pub user: CrossAccountId,943	pub pieces: u128,944	#[derivative(Debug(format_with = "bounded::vec_debug"))]945	pub properties: CollectionPropertiesVec,946}947948/// Unified extended data for creating item.949#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]950#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]951pub enum CreateItemExData<CrossAccountId> {952	/// Extended data for create NFT.953	NFT(954		#[derivative(Debug(format_with = "bounded::vec_debug"))]955		BoundedVec<CreateNftExData<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,956	),957958	/// Extended data for create Fungible item.959	Fungible(960		#[derivative(Debug(format_with = "bounded::map_debug"))]961		BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,962	),963964	/// Extended data for create ReFungible item in case of965	/// many tokens, each may have only one owner966	RefungibleMultipleItems(967		#[derivative(Debug(format_with = "bounded::vec_debug"))]968		BoundedVec<CreateRefungibleExSingleOwner<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,969	),970971	/// Extended data for create ReFungible item in case of972	/// single token, which may have many owners973	RefungibleMultipleOwners(CreateRefungibleExMultipleOwners<CrossAccountId>),974}975976impl From<CreateNftData> for CreateItemData {977	fn from(item: CreateNftData) -> Self {978		CreateItemData::NFT(item)979	}980}981982impl From<CreateReFungibleData> for CreateItemData {983	fn from(item: CreateReFungibleData) -> Self {984		CreateItemData::ReFungible(item)985	}986}987988impl From<CreateFungibleData> for CreateItemData {989	fn from(item: CreateFungibleData) -> Self {990		CreateItemData::Fungible(item)991	}992}993994/// Token's address, dictated by its collection and token IDs.995#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]996#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]997// todo possibly rename to be used generally as an address pair998pub struct TokenChild {999	/// Token id.1000	pub token: TokenId,10011002	/// Collection id.1003	pub collection: CollectionId,1004}10051006/// Collection statistics.1007#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]1008#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1009pub struct CollectionStats {1010	/// Number of created items.1011	pub created: u32,10121013	/// Number of burned items.1014	pub destroyed: u32,10151016	/// Number of current items.1017	pub alive: u32,1018}10191020/// This type works like [`PhantomData`] but supports generating _scale-info_ descriptions to generate node metadata.1021#[derive(Encode, Decode, Clone, Debug)]1022#[cfg_attr(feature = "std", derive(PartialEq))]1023pub struct PhantomType<T>(core::marker::PhantomData<T>);10241025impl<T: TypeInfo + 'static> TypeInfo for PhantomType<T> {1026	type Identity = PhantomType<T>;10271028	fn type_info() -> scale_info::Type {1029		use scale_info::{1030			Type, Path,1031			build::{FieldsBuilder, UnnamedFields},1032			form::MetaForm,1033			type_params,1034		};1035		Type::builder()1036			.path(Path::new("up_data_structs", "PhantomType"))1037			.type_params(type_params!(T))1038			.composite(1039				<FieldsBuilder<MetaForm, UnnamedFields>>::default().field(|b| b.ty::<[T; 0]>()),1040			)1041	}1042}1043impl<T> MaxEncodedLen for PhantomType<T> {1044	fn max_encoded_len() -> usize {1045		01046	}1047}10481049/// Bounded vector of bytes.1050pub type BoundedBytes<S> = BoundedVec<u8, S>;10511052/// Extra properties for external collections.1053pub type AuxPropertyValue = BoundedBytes<ConstU32<MAX_AUX_PROPERTY_VALUE_LENGTH>>;10541055/// Property key.1056pub type PropertyKey = BoundedBytes<ConstU32<MAX_PROPERTY_KEY_LENGTH>>;10571058/// Property value.1059pub type PropertyValue = BoundedBytes<ConstU32<MAX_PROPERTY_VALUE_LENGTH>>;10601061/// Property permission.1062#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone, Default)]1063#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1064pub struct PropertyPermission {1065	/// Permission to change the property and property permission.1066	///1067	/// If it **false** then you can not change corresponding property even if [`collection_admin`] and [`token_owner`] are **true**.1068	pub mutable: bool,10691070	/// Change permission for the collection administrator.1071	pub collection_admin: bool,10721073	/// Permission to change the property for the owner of the token.1074	pub token_owner: bool,1075}10761077impl PropertyPermission {1078	/// Creates mutable property permission but changes restricted for collection admin and token owner.1079	pub fn none() -> Self {1080		Self {1081			mutable: true,1082			collection_admin: false,1083			token_owner: false,1084		}1085	}1086}10871088/// Property is simpl key-value record.1089#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, MaxEncodedLen)]1090#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1091pub struct Property {1092	/// Property key.1093	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1094	pub key: PropertyKey,10951096	/// Property value.1097	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1098	pub value: PropertyValue,1099}11001101impl Into<(PropertyKey, PropertyValue)> for Property {1102	fn into(self) -> (PropertyKey, PropertyValue) {1103		(self.key, self.value)1104	}1105}11061107/// Record for proprty key permission.1108#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone)]1109#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1110pub struct PropertyKeyPermission {1111	/// Key.1112	#[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1113	pub key: PropertyKey,11141115	/// Permission.1116	pub permission: PropertyPermission,1117}11181119impl Into<(PropertyKey, PropertyPermission)> for PropertyKeyPermission {1120	fn into(self) -> (PropertyKey, PropertyPermission) {1121		(self.key, self.permission)1122	}1123}11241125/// Errors for properties actions.1126#[derive(Debug)]1127pub enum PropertiesError {1128	/// The space allocated for properties has run out.1129	///1130	/// * Limit for colection - [`MAX_COLLECTION_PROPERTIES_SIZE`].1131	/// * Limit for token - [`MAX_TOKEN_PROPERTIES_SIZE`].1132	NoSpaceForProperty,11331134	/// The property limit has been reached.1135	///1136	/// * Limit - [`MAX_PROPERTIES_PER_ITEM`].1137	PropertyLimitReached,11381139	/// Property key contains not allowed character.1140	InvalidCharacterInPropertyKey,11411142	/// Property key length is too long.1143	///1144	/// * Limit - [`MAX_PROPERTY_KEY_LENGTH`].1145	PropertyKeyIsTooLong,11461147	/// Property key is empty.1148	EmptyPropertyKey,1149}11501151/// Token owner error: it could be either `NotFound` ot `MultipleOwners`.1152#[derive(Debug)]1153pub enum TokenOwnerError {1154	NotFound,1155	MultipleOwners,1156}11571158/// Marker for scope of property.1159///1160/// Scoped property can't be changed by user. Used for external collections.1161#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Clone, Copy)]1162pub enum PropertyScope {1163	None,1164	Rmrk,1165}11661167impl PropertyScope {1168	pub fn prefix(&self) -> &'static [u8] {1169		match self {1170			Self::None => b"",1171			Self::Rmrk => b"rmrk:",1172		}1173	}1174	/// Apply scope to property key.1175	pub fn apply(self, key: PropertyKey) -> Result<PropertyKey, PropertiesError> {1176		let prefix = self.prefix();1177		if prefix == b"" {1178			return Ok(key);1179		}1180		[prefix, key.as_slice()]1181			.concat()1182			.try_into()1183			.map_err(|_| PropertiesError::PropertyKeyIsTooLong)1184	}1185}11861187/// Trait for operate with properties.1188pub trait TrySetProperty: Sized {1189	type Value;11901191	/// Try to set property with scope.1192	fn try_scoped_set(1193		&mut self,1194		scope: PropertyScope,1195		key: PropertyKey,1196		value: Self::Value,1197	) -> Result<Option<Self::Value>, PropertiesError>;11981199	/// Try to set property with scope from iterator.1200	fn try_scoped_set_from_iter<I, KV>(1201		&mut self,1202		scope: PropertyScope,1203		iter: I,1204	) -> Result<(), PropertiesError>1205	where1206		I: Iterator<Item = KV>,1207		KV: Into<(PropertyKey, Self::Value)>,1208	{1209		for kv in iter {1210			let (key, value) = kv.into();1211			self.try_scoped_set(scope, key, value)?;1212		}12131214		Ok(())1215	}12161217	/// Try to set property.1218	fn try_set(1219		&mut self,1220		key: PropertyKey,1221		value: Self::Value,1222	) -> Result<Option<Self::Value>, PropertiesError> {1223		self.try_scoped_set(PropertyScope::None, key, value)1224	}12251226	/// Try to set property from iterator.1227	fn try_set_from_iter<I, KV>(&mut self, iter: I) -> Result<(), PropertiesError>1228	where1229		I: Iterator<Item = KV>,1230		KV: Into<(PropertyKey, Self::Value)>,1231	{1232		self.try_scoped_set_from_iter(PropertyScope::None, iter)1233	}1234}12351236/// Wrapped map for storing properties.1237#[derive(Encode, Decode, TypeInfo, Derivative, Clone, PartialEq, MaxEncodedLen)]1238#[derivative(Default(bound = ""))]1239pub struct PropertiesMap<Value>(1240	BoundedBTreeMap<PropertyKey, Value, ConstU32<MAX_PROPERTIES_PER_ITEM>>,1241);12421243impl<Value> PropertiesMap<Value> {1244	/// Create new property map.1245	pub fn new() -> Self {1246		Self(BoundedBTreeMap::new())1247	}12481249	/// Remove property from map.1250	pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<Value>, PropertiesError> {1251		Self::check_property_key(key)?;12521253		Ok(self.0.remove(key))1254	}12551256	/// Get property with appropriate key from map.1257	pub fn get(&self, key: &PropertyKey) -> Option<&Value> {1258		self.0.get(key)1259	}12601261	/// Check if map contains key.1262	pub fn contains_key(&self, key: &PropertyKey) -> bool {1263		self.0.contains_key(key)1264	}12651266	/// Check if map contains key with key validation.1267	fn check_property_key(key: &PropertyKey) -> Result<(), PropertiesError> {1268		if key.is_empty() {1269			return Err(PropertiesError::EmptyPropertyKey);1270		}12711272		for byte in key.as_slice().iter() {1273			let byte = *byte;12741275			if !byte.is_ascii_alphanumeric() && byte != b'_' && byte != b'-' && byte != b'.' {1276				return Err(PropertiesError::InvalidCharacterInPropertyKey);1277			}1278		}12791280		Ok(())1281	}12821283	pub fn values(&self) -> impl Iterator<Item = &Value> {1284		self.0.values()1285	}12861287	pub fn iter(&self) -> impl Iterator<Item = (&PropertyKey, &Value)> {1288		self.0.iter()1289	}1290}12911292impl<Value> IntoIterator for PropertiesMap<Value> {1293	type Item = (PropertyKey, Value);1294	type IntoIter = <1295		BoundedBTreeMap<1296			PropertyKey,1297			Value,1298			ConstU32<MAX_PROPERTIES_PER_ITEM>1299		> as IntoIterator1300	>::IntoIter;13011302	fn into_iter(self) -> Self::IntoIter {1303		self.0.into_iter()1304	}1305}13061307impl<Value> TrySetProperty for PropertiesMap<Value> {1308	type Value = Value;13091310	fn try_scoped_set(1311		&mut self,1312		scope: PropertyScope,1313		key: PropertyKey,1314		value: Self::Value,1315	) -> Result<Option<Self::Value>, PropertiesError> {1316		Self::check_property_key(&key)?;13171318		let key = scope.apply(key)?;1319		self.01320			.try_insert(key, value)1321			.map_err(|_| PropertiesError::PropertyLimitReached)1322	}1323}13241325/// Alias for property permissions map.1326pub type PropertiesPermissionMap = PropertiesMap<PropertyPermission>;13271328fn slice_size(data: &[u8]) -> u32 {1329	scoped_slice_size(PropertyScope::None, data)1330}1331fn scoped_slice_size(scope: PropertyScope, data: &[u8]) -> u32 {1332	use codec::Compact;1333	let prefix = scope.prefix();1334	<Compact<u32>>::encoded_size(&Compact(data.len() as u32 + prefix.len() as u32)) as u321335		+ data.len() as u321336		+ prefix.len() as u321337}13381339/// Wrapper for properties map with consumed space control.1340#[derive(Encode, Decode, TypeInfo, Clone, PartialEq)]1341pub struct Properties<const S: u32> {1342	map: PropertiesMap<PropertyValue>,1343	consumed_space: u32,1344	// May be not zero, previously served as a current S generic1345	_reserved: u32,1346}13471348impl<const S: u32> MaxEncodedLen for Properties<S> {1349	fn max_encoded_len() -> usize {1350		// len of map + len of consumed_space + len of space_limit1351		u32::max_encoded_len() * 3 + S as usize1352	}1353}13541355impl<const S: u32> Default for Properties<S> {1356	fn default() -> Self {1357		Self::new()1358	}1359}13601361impl<const S: u32> Properties<S> {1362	/// Create new properies container.1363	pub fn new() -> Self {1364		Self {1365			map: PropertiesMap::new(),1366			consumed_space: 0,1367			_reserved: 0,1368		}1369	}13701371	/// Remove propery with appropiate key.1372	pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<PropertyValue>, PropertiesError> {1373		let value = self.map.remove(key)?;13741375		if let Some(ref value) = value {1376			let kv_len = slice_size(key) + slice_size(value);1377			self.consumed_space = self.consumed_space.saturating_sub(kv_len);1378		}13791380		Ok(value)1381	}13821383	/// Get property with appropriate key.1384	pub fn get(&self, key: &PropertyKey) -> Option<&PropertyValue> {1385		self.map.get(key)1386	}13871388	/// Recomputes the consumed space for the current properties state.1389	/// Needed to repair a token due to a bug fixed in the [PR #733](https://github.com/UniqueNetwork/unique-chain/pull/773).1390	pub fn recompute_consumed_space(&mut self) {1391		self.consumed_space = self1392			.map1393			.iter()1394			.map(|(key, value)| slice_size(key) + slice_size(value))1395			.sum();1396	}1397}13981399impl<const S: u32> IntoIterator for Properties<S> {1400	type Item = (PropertyKey, PropertyValue);1401	type IntoIter = <PropertiesMap<PropertyValue> as IntoIterator>::IntoIter;14021403	fn into_iter(self) -> Self::IntoIter {1404		self.map.into_iter()1405	}1406}14071408impl<const S: u32> TrySetProperty for Properties<S> {1409	type Value = PropertyValue;14101411	fn try_scoped_set(1412		&mut self,1413		scope: PropertyScope,1414		key: PropertyKey,1415		value: Self::Value,1416	) -> Result<Option<Self::Value>, PropertiesError> {1417		let key_size = scoped_slice_size(scope, &key);1418		let value_size = slice_size(&value) as u32;14191420		if self.consumed_space + value_size + key_size > S && !cfg!(feature = "runtime-benchmarks")1421		{1422			return Err(PropertiesError::NoSpaceForProperty);1423		}14241425		let old_value = self.map.try_scoped_set(scope, key, value)?;14261427		if let Some(old_value) = old_value.as_ref() {1428			let old_value_size = slice_size(&old_value);1429			self.consumed_space = self.consumed_space.saturating_sub(old_value_size) + value_size;1430		} else {1431			self.consumed_space += key_size + value_size;1432		}14331434		Ok(old_value)1435	}1436}14371438pub type CollectionProperties = Properties<MAX_COLLECTION_PROPERTIES_SIZE>;1439pub type TokenProperties = Properties<MAX_TOKEN_PROPERTIES_SIZE>;14401441#[cfg(test)]1442mod tests {1443	use super::*;1444	use codec::IoReader;14451446	#[test]1447	fn rpc_collection_supports_decoding_old_versions() {1448		let encoded_rpc_collection: [u8; 1013] = [1449			0, 1, 250, 241, 137, 120, 188, 29, 94, 210, 193, 237, 186, 22, 203, 241, 52, 248, 167,1450			235, 241, 211, 236, 28, 138, 156, 59, 160, 156, 105, 39, 247, 207, 101, 0, 0, 48, 65,1451			0, 73, 0, 32, 0, 67, 0, 114, 0, 101, 0, 97, 0, 116, 0, 105, 0, 111, 0, 110, 0, 115, 0,1452			252, 65, 0, 32, 0, 112, 0, 105, 0, 101, 0, 99, 0, 101, 0, 32, 0, 111, 0, 102, 0, 32, 0,1453			97, 0, 32, 0, 109, 0, 97, 0, 99, 0, 104, 0, 105, 0, 110, 0, 101, 0, 32, 0, 109, 0, 105,1454			0, 110, 0, 100, 0, 46, 0, 32, 0, 69, 0, 118, 0, 101, 0, 114, 0, 121, 0, 32, 0, 78, 0,1455			70, 0, 84, 0, 32, 0, 105, 0, 115, 0, 32, 0, 109, 0, 97, 0, 100, 0, 101, 0, 32, 0, 101,1456			0, 120, 0, 99, 0, 108, 0, 117, 0, 115, 0, 105, 0, 118, 0, 101, 0, 108, 0, 121, 0, 32,1457			0, 98, 0, 121, 0, 32, 0, 65, 0, 73, 0, 46, 0, 12, 65, 73, 67, 0, 0, 1, 0, 0, 0, 0, 0,1458			0, 0, 0, 0, 0, 17, 1, 123, 34, 99, 111, 108, 108, 101, 99, 116, 105, 111, 110, 67, 111,1459			118, 101, 114, 34, 58, 34, 81, 109, 98, 52, 104, 122, 76, 101, 51, 49, 102, 98, 71, 74,1460			77, 89, 68, 82, 88, 84, 115, 107, 56, 49, 76, 103, 76, 97, 88, 76, 69, 112, 121, 97,1461			122, 102, 66, 85, 103, 111, 110, 118, 49, 118, 84, 85, 34, 125, 125, 11, 123, 34, 110,1462			101, 115, 116, 101, 100, 34, 58, 123, 34, 111, 110, 67, 104, 97, 105, 110, 77, 101,1463			116, 97, 68, 97, 116, 97, 34, 58, 123, 34, 110, 101, 115, 116, 101, 100, 34, 58, 123,1464			34, 78, 70, 84, 77, 101, 116, 97, 34, 58, 123, 34, 102, 105, 101, 108, 100, 115, 34,1465			58, 123, 34, 105, 112, 102, 115, 74, 115, 111, 110, 34, 58, 123, 34, 105, 100, 34, 58,1466			49, 44, 34, 114, 117, 108, 101, 34, 58, 34, 114, 101, 113, 117, 105, 114, 101, 100, 34,1467			44, 34, 116, 121, 112, 101, 34, 58, 34, 115, 116, 114, 105, 110, 103, 34, 125, 44, 34,1468			67, 111, 108, 111, 114, 34, 58, 123, 34, 105, 100, 34, 58, 50, 44, 34, 114, 117, 108,1469			101, 34, 58, 34, 114, 101, 113, 117, 105, 114, 101, 100, 34, 44, 34, 116, 121, 112,1470			101, 34, 58, 34, 67, 111, 108, 111, 114, 34, 125, 44, 34, 73, 110, 116, 101, 110, 115,1471			105, 111, 110, 115, 34, 58, 123, 34, 105, 100, 34, 58, 51, 44, 34, 114, 117, 108, 101,1472			34, 58, 34, 114, 101, 113, 117, 105, 114, 101, 100, 34, 44, 34, 116, 121, 112, 101, 34,1473			58, 34, 73, 110, 116, 101, 110, 115, 105, 111, 110, 115, 34, 125, 44, 34, 77, 111, 111,1474			100, 34, 58, 123, 34, 105, 100, 34, 58, 52, 44, 34, 114, 117, 108, 101, 34, 58, 34,1475			114, 101, 113, 117, 105, 114, 101, 100, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 77,1476			111, 111, 100, 34, 125, 125, 125, 44, 34, 67, 111, 108, 111, 114, 34, 58, 123, 34, 111,1477			112, 116, 105, 111, 110, 115, 34, 58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 34,1478			123, 92, 34, 101, 110, 92, 34, 58, 92, 34, 67, 111, 108, 111, 114, 101, 100, 92, 34,1479			125, 34, 44, 34, 102, 105, 101, 108, 100, 50, 34, 58, 34, 123, 92, 34, 101, 110, 92,1480			34, 58, 92, 34, 66, 108, 97, 99, 107, 38, 87, 104, 105, 116, 101, 92, 34, 125, 34, 125,1481			44, 34, 118, 97, 108, 117, 101, 115, 34, 58, 123, 34, 102, 105, 101, 108, 100, 49, 34,1482			58, 48, 44, 34, 102, 105, 101, 108, 100, 50, 34, 58, 49, 125, 125, 44, 34, 73, 110,1483			116, 101, 110, 115, 105, 111, 110, 115, 34, 58, 123, 34, 111, 112, 116, 105, 111, 110,1484			115, 34, 58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 34, 123, 92, 34, 101, 110,1485			92, 34, 58, 92, 34, 101, 118, 105, 108, 92, 34, 125, 34, 44, 34, 102, 105, 101, 108,1486			100, 50, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92, 34, 103, 111, 111, 100, 92,1487			34, 125, 34, 44, 34, 102, 105, 101, 108, 100, 51, 34, 58, 34, 123, 92, 34, 101, 110,1488			92, 34, 58, 92, 34, 110, 101, 117, 116, 114, 97, 108, 92, 34, 125, 34, 125, 44, 34,1489			118, 97, 108, 117, 101, 115, 34, 58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 48,1490			44, 34, 102, 105, 101, 108, 100, 50, 34, 58, 49, 44, 34, 102, 105, 101, 108, 100, 51,1491			34, 58, 50, 125, 125, 44, 34, 77, 111, 111, 100, 34, 58, 123, 34, 111, 112, 116, 105,1492			111, 110, 115, 34, 58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 34, 123, 92, 34,1493			101, 110, 92, 34, 58, 92, 34, 65, 98, 115, 116, 114, 97, 99, 116, 92, 34, 125, 34, 44,1494			34, 102, 105, 101, 108, 100, 50, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92, 34,1495			85, 110, 99, 97, 110, 110, 101, 121, 32, 118, 97, 108, 108, 101, 121, 92, 34, 125, 34,1496			44, 34, 102, 105, 101, 108, 100, 51, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92,1497			34, 83, 117, 114, 114, 101, 97, 108, 105, 115, 116, 92, 34, 125, 34, 125, 44, 34, 118,1498			97, 108, 117, 101, 115, 34, 58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 48, 44,1499			34, 102, 105, 101, 108, 100, 50, 34, 58, 49, 44, 34, 102, 105, 101, 108, 100, 51, 34,1500			58, 50, 125, 125, 125, 125, 125, 125, 0,1501		];1502		let mut bytes = IoReader(encoded_rpc_collection.as_slice());1503		CollectionVersion1::<[u8; 34]>::decode(&mut bytes).unwrap();1504	}15051506	#[test]1507	fn rpc_collection_supports_decoding_new_versions() {1508		let encoded_rpc_collection: [u8; 1576] = [1509			0, 1, 238, 236, 179, 149, 150, 47, 71, 194, 69, 174, 250, 116, 251, 148, 90, 15, 56,1510			220, 91, 79, 49, 79, 45, 197, 171, 98, 14, 171, 80, 23, 58, 92, 0, 96, 77, 0, 105, 0,1511			110, 0, 116, 0, 70, 0, 101, 0, 115, 0, 116, 0, 32, 0, 83, 0, 121, 0, 109, 0, 109, 0,1512			101, 0, 116, 0, 114, 0, 121, 0, 32, 0, 66, 0, 114, 0, 101, 0, 97, 0, 99, 0, 104, 0,1513			113, 3, 83, 0, 121, 0, 109, 0, 109, 0, 101, 0, 116, 0, 114, 0, 121, 0, 32, 0, 104, 0,1514			97, 0, 115, 0, 32, 0, 115, 0, 111, 0, 109, 0, 101, 0, 116, 0, 104, 0, 105, 0, 110, 0,1515			103, 0, 32, 0, 105, 0, 110, 0, 116, 0, 111, 0, 120, 0, 105, 0, 99, 0, 97, 0, 116, 0,1516			105, 0, 110, 0, 103, 0, 32, 0, 116, 0, 104, 0, 97, 0, 116, 0, 32, 0, 100, 0, 114, 0,1517			97, 0, 119, 0, 115, 0, 32, 0, 121, 0, 111, 0, 117, 0, 32, 0, 105, 0, 110, 0, 46, 0, 10,1518			0, 73, 0, 110, 0, 115, 0, 112, 0, 105, 0, 114, 0, 101, 0, 100, 0, 32, 0, 98, 0, 121, 0,1519			32, 0, 116, 0, 104, 0, 101, 0, 32, 0, 112, 0, 101, 0, 114, 0, 102, 0, 101, 0, 99, 0,1520			116, 0, 105, 0, 111, 0, 110, 0, 32, 0, 111, 0, 102, 0, 32, 0, 116, 0, 104, 0, 101, 0,1521			32, 0, 115, 0, 121, 0, 109, 0, 109, 0, 101, 0, 116, 0, 114, 0, 121, 0, 44, 0, 32, 0,1522			73, 0, 32, 0, 104, 0, 97, 0, 118, 0, 101, 0, 32, 0, 99, 0, 114, 0, 101, 0, 97, 0, 116,1523			0, 101, 0, 100, 0, 32, 0, 115, 0, 121, 0, 109, 0, 109, 0, 101, 0, 116, 0, 114, 0, 105,1524			0, 99, 0, 97, 0, 108, 0, 32, 0, 105, 0, 109, 0, 97, 0, 103, 0, 101, 0, 115, 0, 32, 0,1525			111, 0, 102, 0, 32, 0, 115, 0, 101, 0, 118, 0, 101, 0, 114, 0, 97, 0, 108, 0, 32, 0,1526			118, 0, 101, 0, 114, 0, 116, 0, 105, 0, 99, 0, 101, 0, 115, 0, 44, 0, 32, 0, 98, 0,1527			117, 0, 116, 0, 32, 0, 115, 0, 111, 0, 109, 0, 101, 0, 32, 0, 115, 0, 121, 0, 109, 0,1528			109, 0, 101, 0, 116, 0, 114, 0, 121, 0, 32, 0, 98, 0, 114, 0, 101, 0, 97, 0, 99, 0,1529			104, 0, 101, 0, 115, 0, 32, 0, 97, 0, 110, 0, 100, 0, 32, 0, 99, 0, 111, 0, 108, 0,1530			111, 0, 114, 0, 115, 0, 32, 0, 116, 0, 104, 0, 97, 0, 116, 0, 32, 0, 109, 0, 97, 0,1531			107, 0, 101, 0, 32, 0, 101, 0, 97, 0, 99, 0, 104, 0, 32, 0, 105, 0, 109, 0, 97, 0, 103,1532			0, 101, 0, 32, 0, 85, 0, 78, 0, 73, 0, 81, 0, 85, 0, 69, 0, 46, 0, 12, 83, 121, 66, 0,1533			0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 4, 56, 95, 111, 108, 100, 95, 99,1534			111, 110, 115, 116, 68, 97, 116, 97, 0, 1, 0, 12, 92, 95, 111, 108, 100, 95, 99, 111,1535			110, 115, 116, 79, 110, 67, 104, 97, 105, 110, 83, 99, 104, 101, 109, 97, 97, 13, 123,1536			34, 110, 101, 115, 116, 101, 100, 34, 58, 123, 34, 111, 110, 67, 104, 97, 105, 110, 77,1537			101, 116, 97, 68, 97, 116, 97, 34, 58, 123, 34, 110, 101, 115, 116, 101, 100, 34, 58,1538			123, 34, 78, 70, 84, 77, 101, 116, 97, 34, 58, 123, 34, 102, 105, 101, 108, 100, 115,1539			34, 58, 123, 34, 105, 112, 102, 115, 74, 115, 111, 110, 34, 58, 123, 34, 105, 100, 34,1540			58, 49, 44, 34, 114, 117, 108, 101, 34, 58, 34, 114, 101, 113, 117, 105, 114, 101, 100,1541			34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 115, 116, 114, 105, 110, 103, 34, 125, 44,1542			34, 67, 111, 108, 111, 114, 34, 58, 123, 34, 105, 100, 34, 58, 50, 44, 34, 114, 117,1543			108, 101, 34, 58, 34, 114, 101, 113, 117, 105, 114, 101, 100, 34, 44, 34, 116, 121,1544			112, 101, 34, 58, 34, 67, 111, 108, 111, 114, 34, 125, 44, 34, 83, 121, 109, 109, 101,1545			116, 114, 121, 32, 66, 114, 101, 97, 99, 104, 34, 58, 123, 34, 105, 100, 34, 58, 51,1546			44, 34, 114, 117, 108, 101, 34, 58, 34, 114, 101, 113, 117, 105, 114, 101, 100, 34, 44,1547			34, 116, 121, 112, 101, 34, 58, 34, 83, 121, 109, 109, 101, 116, 114, 121, 32, 66, 114,1548			101, 97, 99, 104, 34, 125, 44, 34, 86, 101, 114, 116, 105, 99, 101, 34, 58, 123, 34,1549			105, 100, 34, 58, 52, 44, 34, 114, 117, 108, 101, 34, 58, 34, 114, 101, 113, 117, 105,1550			114, 101, 100, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 86, 101, 114, 116, 105, 99,1551			101, 34, 125, 125, 125, 44, 34, 67, 111, 108, 111, 114, 34, 58, 123, 34, 111, 112, 116,1552			105, 111, 110, 115, 34, 58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 34, 123, 92,1553			34, 101, 110, 92, 34, 58, 92, 34, 49, 32, 32, 32, 92, 34, 125, 34, 44, 34, 102, 105,1554			101, 108, 100, 50, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92, 34, 50, 32, 92,1555			34, 125, 34, 44, 34, 102, 105, 101, 108, 100, 51, 34, 58, 34, 123, 92, 34, 101, 110,1556			92, 34, 58, 92, 34, 51, 92, 34, 125, 34, 125, 44, 34, 118, 97, 108, 117, 101, 115, 34,1557			58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 48, 44, 34, 102, 105, 101, 108, 100,1558			50, 34, 58, 49, 44, 34, 102, 105, 101, 108, 100, 51, 34, 58, 50, 125, 125, 44, 34, 83,1559			121, 109, 109, 101, 116, 114, 121, 32, 66, 114, 101, 97, 99, 104, 34, 58, 123, 34, 111,1560			112, 116, 105, 111, 110, 115, 34, 58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 34,1561			123, 92, 34, 101, 110, 92, 34, 58, 92, 34, 49, 92, 34, 125, 34, 44, 34, 102, 105, 101,1562			108, 100, 50, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92, 34, 50, 92, 34, 125,1563			34, 125, 44, 34, 118, 97, 108, 117, 101, 115, 34, 58, 123, 34, 102, 105, 101, 108, 100,1564			49, 34, 58, 48, 44, 34, 102, 105, 101, 108, 100, 50, 34, 58, 49, 125, 125, 44, 34, 86,1565			101, 114, 116, 105, 99, 101, 34, 58, 123, 34, 111, 112, 116, 105, 111, 110, 115, 34,1566			58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34,1567			58, 92, 34, 54, 92, 34, 125, 34, 44, 34, 102, 105, 101, 108, 100, 50, 34, 58, 34, 123,1568			92, 34, 101, 110, 92, 34, 58, 92, 34, 55, 92, 34, 125, 34, 44, 34, 102, 105, 101, 108,1569			100, 51, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92, 34, 56, 92, 34, 125, 34,1570			44, 34, 102, 105, 101, 108, 100, 52, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92,1571			34, 57, 92, 34, 125, 34, 44, 34, 102, 105, 101, 108, 100, 53, 34, 58, 34, 123, 92, 34,1572			101, 110, 92, 34, 58, 92, 34, 49, 48, 92, 34, 125, 34, 44, 34, 102, 105, 101, 108, 100,1573			54, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92, 34, 49, 49, 92, 34, 125, 34, 44,1574			34, 102, 105, 101, 108, 100, 55, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92, 34,1575			49, 50, 92, 34, 125, 34, 125, 44, 34, 118, 97, 108, 117, 101, 115, 34, 58, 123, 34,1576			102, 105, 101, 108, 100, 49, 34, 58, 48, 44, 34, 102, 105, 101, 108, 100, 50, 34, 58,1577			49, 44, 34, 102, 105, 101, 108, 100, 51, 34, 58, 50, 44, 34, 102, 105, 101, 108, 100,1578			52, 34, 58, 51, 44, 34, 102, 105, 101, 108, 100, 53, 34, 58, 52, 44, 34, 102, 105, 101,1579			108, 100, 54, 34, 58, 53, 44, 34, 102, 105, 101, 108, 100, 55, 34, 58, 54, 125, 125,1580			125, 125, 125, 125, 72, 95, 111, 108, 100, 95, 115, 99, 104, 101, 109, 97, 86, 101,1581			114, 115, 105, 111, 110, 24, 85, 110, 105, 113, 117, 101, 104, 95, 111, 108, 100, 95,1582			118, 97, 114, 105, 97, 98, 108, 101, 79, 110, 67, 104, 97, 105, 110, 83, 99, 104, 101,1583			109, 97, 17, 1, 123, 34, 99, 111, 108, 108, 101, 99, 116, 105, 111, 110, 67, 111, 118,1584			101, 114, 34, 58, 34, 81, 109, 82, 67, 77, 84, 109, 57, 118, 81, 107, 76, 89, 86, 65,1585			54, 54, 87, 80, 49, 75, 72, 57, 55, 106, 84, 76, 76, 115, 56, 74, 78, 86, 65, 114, 80,1586			66, 52, 56, 98, 106, 87, 84, 75, 74, 110, 34, 125, 0, 0, 0,1587		];1588		let mut bytes = IoReader(encoded_rpc_collection.as_slice());1589		RpcCollection::<[u8; 34]>::decode(&mut bytes).unwrap();1590	}15911592	#[test]1593	fn rpc_collection_supports_decoding_through_vec() {1594		let encoded_rpc_collection: [u8; 1576] = [1595			0, 1, 238, 236, 179, 149, 150, 47, 71, 194, 69, 174, 250, 116, 251, 148, 90, 15, 56,1596			220, 91, 79, 49, 79, 45, 197, 171, 98, 14, 171, 80, 23, 58, 92, 0, 96, 77, 0, 105, 0,1597			110, 0, 116, 0, 70, 0, 101, 0, 115, 0, 116, 0, 32, 0, 83, 0, 121, 0, 109, 0, 109, 0,1598			101, 0, 116, 0, 114, 0, 121, 0, 32, 0, 66, 0, 114, 0, 101, 0, 97, 0, 99, 0, 104, 0,1599			113, 3, 83, 0, 121, 0, 109, 0, 109, 0, 101, 0, 116, 0, 114, 0, 121, 0, 32, 0, 104, 0,1600			97, 0, 115, 0, 32, 0, 115, 0, 111, 0, 109, 0, 101, 0, 116, 0, 104, 0, 105, 0, 110, 0,1601			103, 0, 32, 0, 105, 0, 110, 0, 116, 0, 111, 0, 120, 0, 105, 0, 99, 0, 97, 0, 116, 0,1602			105, 0, 110, 0, 103, 0, 32, 0, 116, 0, 104, 0, 97, 0, 116, 0, 32, 0, 100, 0, 114, 0,1603			97, 0, 119, 0, 115, 0, 32, 0, 121, 0, 111, 0, 117, 0, 32, 0, 105, 0, 110, 0, 46, 0, 10,1604			0, 73, 0, 110, 0, 115, 0, 112, 0, 105, 0, 114, 0, 101, 0, 100, 0, 32, 0, 98, 0, 121, 0,1605			32, 0, 116, 0, 104, 0, 101, 0, 32, 0, 112, 0, 101, 0, 114, 0, 102, 0, 101, 0, 99, 0,1606			116, 0, 105, 0, 111, 0, 110, 0, 32, 0, 111, 0, 102, 0, 32, 0, 116, 0, 104, 0, 101, 0,1607			32, 0, 115, 0, 121, 0, 109, 0, 109, 0, 101, 0, 116, 0, 114, 0, 121, 0, 44, 0, 32, 0,1608			73, 0, 32, 0, 104, 0, 97, 0, 118, 0, 101, 0, 32, 0, 99, 0, 114, 0, 101, 0, 97, 0, 116,1609			0, 101, 0, 100, 0, 32, 0, 115, 0, 121, 0, 109, 0, 109, 0, 101, 0, 116, 0, 114, 0, 105,1610			0, 99, 0, 97, 0, 108, 0, 32, 0, 105, 0, 109, 0, 97, 0, 103, 0, 101, 0, 115, 0, 32, 0,1611			111, 0, 102, 0, 32, 0, 115, 0, 101, 0, 118, 0, 101, 0, 114, 0, 97, 0, 108, 0, 32, 0,1612			118, 0, 101, 0, 114, 0, 116, 0, 105, 0, 99, 0, 101, 0, 115, 0, 44, 0, 32, 0, 98, 0,1613			117, 0, 116, 0, 32, 0, 115, 0, 111, 0, 109, 0, 101, 0, 32, 0, 115, 0, 121, 0, 109, 0,1614			109, 0, 101, 0, 116, 0, 114, 0, 121, 0, 32, 0, 98, 0, 114, 0, 101, 0, 97, 0, 99, 0,1615			104, 0, 101, 0, 115, 0, 32, 0, 97, 0, 110, 0, 100, 0, 32, 0, 99, 0, 111, 0, 108, 0,1616			111, 0, 114, 0, 115, 0, 32, 0, 116, 0, 104, 0, 97, 0, 116, 0, 32, 0, 109, 0, 97, 0,1617			107, 0, 101, 0, 32, 0, 101, 0, 97, 0, 99, 0, 104, 0, 32, 0, 105, 0, 109, 0, 97, 0, 103,1618			0, 101, 0, 32, 0, 85, 0, 78, 0, 73, 0, 81, 0, 85, 0, 69, 0, 46, 0, 12, 83, 121, 66, 0,1619			0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 4, 56, 95, 111, 108, 100, 95, 99,1620			111, 110, 115, 116, 68, 97, 116, 97, 0, 1, 0, 12, 92, 95, 111, 108, 100, 95, 99, 111,1621			110, 115, 116, 79, 110, 67, 104, 97, 105, 110, 83, 99, 104, 101, 109, 97, 97, 13, 123,1622			34, 110, 101, 115, 116, 101, 100, 34, 58, 123, 34, 111, 110, 67, 104, 97, 105, 110, 77,1623			101, 116, 97, 68, 97, 116, 97, 34, 58, 123, 34, 110, 101, 115, 116, 101, 100, 34, 58,1624			123, 34, 78, 70, 84, 77, 101, 116, 97, 34, 58, 123, 34, 102, 105, 101, 108, 100, 115,1625			34, 58, 123, 34, 105, 112, 102, 115, 74, 115, 111, 110, 34, 58, 123, 34, 105, 100, 34,1626			58, 49, 44, 34, 114, 117, 108, 101, 34, 58, 34, 114, 101, 113, 117, 105, 114, 101, 100,1627			34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 115, 116, 114, 105, 110, 103, 34, 125, 44,1628			34, 67, 111, 108, 111, 114, 34, 58, 123, 34, 105, 100, 34, 58, 50, 44, 34, 114, 117,1629			108, 101, 34, 58, 34, 114, 101, 113, 117, 105, 114, 101, 100, 34, 44, 34, 116, 121,1630			112, 101, 34, 58, 34, 67, 111, 108, 111, 114, 34, 125, 44, 34, 83, 121, 109, 109, 101,1631			116, 114, 121, 32, 66, 114, 101, 97, 99, 104, 34, 58, 123, 34, 105, 100, 34, 58, 51,1632			44, 34, 114, 117, 108, 101, 34, 58, 34, 114, 101, 113, 117, 105, 114, 101, 100, 34, 44,1633			34, 116, 121, 112, 101, 34, 58, 34, 83, 121, 109, 109, 101, 116, 114, 121, 32, 66, 114,1634			101, 97, 99, 104, 34, 125, 44, 34, 86, 101, 114, 116, 105, 99, 101, 34, 58, 123, 34,1635			105, 100, 34, 58, 52, 44, 34, 114, 117, 108, 101, 34, 58, 34, 114, 101, 113, 117, 105,1636			114, 101, 100, 34, 44, 34, 116, 121, 112, 101, 34, 58, 34, 86, 101, 114, 116, 105, 99,1637			101, 34, 125, 125, 125, 44, 34, 67, 111, 108, 111, 114, 34, 58, 123, 34, 111, 112, 116,1638			105, 111, 110, 115, 34, 58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 34, 123, 92,1639			34, 101, 110, 92, 34, 58, 92, 34, 49, 32, 32, 32, 92, 34, 125, 34, 44, 34, 102, 105,1640			101, 108, 100, 50, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92, 34, 50, 32, 92,1641			34, 125, 34, 44, 34, 102, 105, 101, 108, 100, 51, 34, 58, 34, 123, 92, 34, 101, 110,1642			92, 34, 58, 92, 34, 51, 92, 34, 125, 34, 125, 44, 34, 118, 97, 108, 117, 101, 115, 34,1643			58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 48, 44, 34, 102, 105, 101, 108, 100,1644			50, 34, 58, 49, 44, 34, 102, 105, 101, 108, 100, 51, 34, 58, 50, 125, 125, 44, 34, 83,1645			121, 109, 109, 101, 116, 114, 121, 32, 66, 114, 101, 97, 99, 104, 34, 58, 123, 34, 111,1646			112, 116, 105, 111, 110, 115, 34, 58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 34,1647			123, 92, 34, 101, 110, 92, 34, 58, 92, 34, 49, 92, 34, 125, 34, 44, 34, 102, 105, 101,1648			108, 100, 50, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92, 34, 50, 92, 34, 125,1649			34, 125, 44, 34, 118, 97, 108, 117, 101, 115, 34, 58, 123, 34, 102, 105, 101, 108, 100,1650			49, 34, 58, 48, 44, 34, 102, 105, 101, 108, 100, 50, 34, 58, 49, 125, 125, 44, 34, 86,1651			101, 114, 116, 105, 99, 101, 34, 58, 123, 34, 111, 112, 116, 105, 111, 110, 115, 34,1652			58, 123, 34, 102, 105, 101, 108, 100, 49, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34,1653			58, 92, 34, 54, 92, 34, 125, 34, 44, 34, 102, 105, 101, 108, 100, 50, 34, 58, 34, 123,1654			92, 34, 101, 110, 92, 34, 58, 92, 34, 55, 92, 34, 125, 34, 44, 34, 102, 105, 101, 108,1655			100, 51, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92, 34, 56, 92, 34, 125, 34,1656			44, 34, 102, 105, 101, 108, 100, 52, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92,1657			34, 57, 92, 34, 125, 34, 44, 34, 102, 105, 101, 108, 100, 53, 34, 58, 34, 123, 92, 34,1658			101, 110, 92, 34, 58, 92, 34, 49, 48, 92, 34, 125, 34, 44, 34, 102, 105, 101, 108, 100,1659			54, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92, 34, 49, 49, 92, 34, 125, 34, 44,1660			34, 102, 105, 101, 108, 100, 55, 34, 58, 34, 123, 92, 34, 101, 110, 92, 34, 58, 92, 34,1661			49, 50, 92, 34, 125, 34, 125, 44, 34, 118, 97, 108, 117, 101, 115, 34, 58, 123, 34,1662			102, 105, 101, 108, 100, 49, 34, 58, 48, 44, 34, 102, 105, 101, 108, 100, 50, 34, 58,1663			49, 44, 34, 102, 105, 101, 108, 100, 51, 34, 58, 50, 44, 34, 102, 105, 101, 108, 100,1664			52, 34, 58, 51, 44, 34, 102, 105, 101, 108, 100, 53, 34, 58, 52, 44, 34, 102, 105, 101,1665			108, 100, 54, 34, 58, 53, 44, 34, 102, 105, 101, 108, 100, 55, 34, 58, 54, 125, 125,1666			125, 125, 125, 125, 72, 95, 111, 108, 100, 95, 115, 99, 104, 101, 109, 97, 86, 101,1667			114, 115, 105, 111, 110, 24, 85, 110, 105, 113, 117, 101, 104, 95, 111, 108, 100, 95,1668			118, 97, 114, 105, 97, 98, 108, 101, 79, 110, 67, 104, 97, 105, 110, 83, 99, 104, 101,1669			109, 97, 17, 1, 123, 34, 99, 111, 108, 108, 101, 99, 116, 105, 111, 110, 67, 111, 118,1670			101, 114, 34, 58, 34, 81, 109, 82, 67, 77, 84, 109, 57, 118, 81, 107, 76, 89, 86, 65,1671			54, 54, 87, 80, 49, 75, 72, 57, 55, 106, 84, 76, 76, 115, 56, 74, 78, 86, 65, 114, 80,1672			66, 52, 56, 98, 106, 87, 84, 75, 74, 110, 34, 125, 0, 0, 0,1673		];1674		let mut bytes = IoReader(encoded_rpc_collection.as_slice());1675		let vec = RawEncoded::decode(&mut bytes).unwrap();1676		let mut bytes = IoReader(vec.as_slice());1677		RpcCollection::<[u8; 34]>::decode(&mut bytes).unwrap();1678	}1679}
modifiedprimitives/rpc/src/lib.rsdiffbeforeafterboth
--- a/primitives/rpc/src/lib.rs
+++ b/primitives/rpc/src/lib.rs
@@ -19,7 +19,7 @@
 extern crate alloc;
 
 use up_data_structs::{
-	CollectionId, TokenId, RpcCollection, CollectionStats, CollectionLimits, Property,
+	CollectionId, TokenId, RawEncoded, RpcCollection, CollectionStats, CollectionLimits, Property,
 	PropertyKeyPermission, TokenData, TokenChild, TokenDataVersion1,
 };
 
@@ -117,7 +117,7 @@
 		fn collection_by_id(collection: CollectionId) -> Result<Option<RpcCollection<AccountId>>>;
 
 		#[changed_in(3)]
-		fn collection_by_id(collection: CollectionId) -> Result<Option<Vec<u8>>>;
+		fn collection_by_id(collection: CollectionId) -> Result<Option<RawEncoded>>;
 
 		/// Get collection stats.
 		fn collection_stats() -> Result<CollectionStats>;