difftreelog
replace `Vec` with `RawEncoded`
in: master
2 files changed
primitives/data-structs/src/lib.rsdiffbeforeafterboth1// 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}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}primitives/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>;