difftreelog
Merge pull request #683 from UniqueNetwork/fix/collection-rpc-runtime-versioning
in: master
3 files changed
client/rpc/src/lib.rsdiffbeforeafterboth--- a/client/rpc/src/lib.rs
+++ b/client/rpc/src/lib.rs
@@ -557,7 +557,10 @@
pass_method!(allowlist(collection: CollectionId) -> Vec<CrossAccountId>, unique_api);
pass_method!(allowed(collection: CollectionId, user: CrossAccountId) -> bool, unique_api);
pass_method!(last_token_id(collection: CollectionId) -> TokenId, unique_api);
- pass_method!(collection_by_id(collection: CollectionId) -> Option<RpcCollection<AccountId>>, unique_api);
+ pass_method!(
+ collection_by_id(collection: CollectionId) -> Option<RpcCollection<AccountId>>, unique_api;
+ changed_in 3, collection_by_id_before_version_3(collection) => |value| value.map(|coll| coll.into())
+ );
pass_method!(collection_stats() -> CollectionStats, unique_api);
pass_method!(next_sponsored(collection: CollectionId, account: CrossAccountId, token: TokenId) -> Option<u64>, unique_api);
pass_method!(effective_collection_limits(collection_id: CollectionId) -> Option<CollectionLimits>, unique_api);
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::{28 storage::{bounded_btree_map::BoundedBTreeMap, bounded_btree_set::BoundedBTreeSet},29 traits::Get,30 parameter_types,31};3233#[cfg(feature = "serde")]34use serde::{Serialize, Deserialize};3536use sp_core::U256;37use sp_runtime::{ArithmeticError, sp_std::prelude::Vec, Permill};38use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};39use bondrewd::Bitfields;40use frame_support::{BoundedVec, traits::ConstU32};41use derivative::Derivative;42use scale_info::TypeInfo;4344// RMRK45use rmrk_traits::{46 CollectionInfo, NftInfo, ResourceInfo, PropertyInfo, BaseInfo, PartType, Theme, ThemeProperty,47 ResourceTypes, BasicResource, ComposableResource, SlotResource, EquippableList,48};49pub use rmrk_traits::{50 primitives::{51 CollectionId as RmrkCollectionId, NftId as RmrkNftId, BaseId as RmrkBaseId,52 SlotId as RmrkSlotId, PartId as RmrkPartId, ResourceId as RmrkResourceId,53 },54 NftChild as RmrkNftChild, AccountIdOrCollectionNftTuple as RmrkAccountIdOrCollectionNftTuple,55 FixedPart as RmrkFixedPart, SlotPart as RmrkSlotPart,56};5758mod bondrewd_codec;59mod bounded;60pub mod budget;61pub mod mapping;62mod migration;6364/// Maximum of decimal points.65pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;6667/// Maximum pieces for refungible token.68pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;69pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;7071/// Maximum tokens for user.72pub const MAX_TOKEN_OWNERSHIP: u32 = if cfg!(not(feature = "limit-testing")) {73 100_00074} else {75 1076};7778/// Maximum for collections can be created.79pub const COLLECTION_NUMBER_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {80 100_00081} else {82 1083};8485/// Maximum for various custom data of token.86pub const CUSTOM_DATA_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {87 204888} else {89 1090};9192/// Maximum admins per collection.93pub const COLLECTION_ADMINS_LIMIT: u32 = 5;9495/// Maximum tokens per collection.96pub const COLLECTION_TOKEN_LIMIT: u32 = u32::MAX;9798/// Maximum tokens per account.99pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {100 1_000_000101} else {102 10103};104105/// Default timeout for transfer sponsoring NFT item.106pub const NFT_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;107/// Default timeout for transfer sponsoring fungible item.108pub const FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;109/// Default timeout for transfer sponsoring refungible item.110pub const REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;111112/// Default timeout for sponsored approving.113pub const SPONSOR_APPROVE_TIMEOUT: u32 = 5;114115// Schema limits116pub const OFFCHAIN_SCHEMA_LIMIT: u32 = 8192;117pub const VARIABLE_ON_CHAIN_SCHEMA_LIMIT: u32 = 8192;118pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 32768;119120// TODO: not used. Delete?121pub const COLLECTION_FIELD_LIMIT: u32 = CONST_ON_CHAIN_SCHEMA_LIMIT;122123/// Maximum length for collection name.124pub const MAX_COLLECTION_NAME_LENGTH: u32 = 64;125126/// Maximum length for collection description.127pub const MAX_COLLECTION_DESCRIPTION_LENGTH: u32 = 256;128129/// Maximal token prefix length.130pub const MAX_TOKEN_PREFIX_LENGTH: u32 = 16;131132/// Maximal lenght of property key.133pub const MAX_PROPERTY_KEY_LENGTH: u32 = 256;134135/// Maximal lenght of property value.136pub const MAX_PROPERTY_VALUE_LENGTH: u32 = 32768;137138/// Maximum properties that can be assigned to token.139pub const MAX_PROPERTIES_PER_ITEM: u32 = 64;140141/// Maximal lenght of extended property value.142pub const MAX_AUX_PROPERTY_VALUE_LENGTH: u32 = 2048;143144/// Maximum size for all collection properties.145pub const MAX_COLLECTION_PROPERTIES_SIZE: u32 = 40960;146147/// Maximum size for all token properties.148pub const MAX_TOKEN_PROPERTIES_SIZE: u32 = 32768;149150/// How much items can be created per single151/// create_many call.152pub const MAX_ITEMS_PER_BATCH: u32 = 200;153154/// Used for limit bounded types of token custom data.155pub type CustomDataLimit = ConstU32<CUSTOM_DATA_LIMIT>;156157/// Collection id.158#[derive(159 Encode,160 Decode,161 PartialEq,162 Eq,163 PartialOrd,164 Ord,165 Clone,166 Copy,167 Debug,168 Default,169 TypeInfo,170 MaxEncodedLen,171)]172#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]173pub struct CollectionId(pub u32);174impl EncodeLike<u32> for CollectionId {}175impl EncodeLike<CollectionId> for u32 {}176177/// Token id.178#[derive(179 Encode,180 Decode,181 PartialEq,182 Eq,183 PartialOrd,184 Ord,185 Clone,186 Copy,187 Debug,188 Default,189 TypeInfo,190 MaxEncodedLen,191)]192#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]193pub struct TokenId(pub u32);194impl EncodeLike<u32> for TokenId {}195impl EncodeLike<TokenId> for u32 {}196197impl TokenId {198 /// Try to get next token id.199 ///200 /// If next id cause overflow, then [`ArithmeticError::Overflow`] returned.201 pub fn try_next(self) -> Result<TokenId, ArithmeticError> {202 self.0203 .checked_add(1)204 .ok_or(ArithmeticError::Overflow)205 .map(Self)206 }207}208209impl From<TokenId> for U256 {210 fn from(t: TokenId) -> Self {211 t.0.into()212 }213}214215impl TryFrom<U256> for TokenId {216 type Error = &'static str;217218 fn try_from(value: U256) -> Result<Self, Self::Error> {219 Ok(TokenId(value.try_into().map_err(|_| "too large token id")?))220 }221}222223/// Token data.224#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]225#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]226pub struct TokenData<CrossAccountId> {227 /// Properties of token.228 pub properties: Vec<Property>,229230 /// Token owner.231 pub owner: Option<CrossAccountId>,232233 /// Token pieces.234 pub pieces: u128,235}236237// TODO: unused type238pub struct OverflowError;239impl From<OverflowError> for &'static str {240 fn from(_: OverflowError) -> Self {241 "overflow occured"242 }243}244245/// Alias for decimal points type.246pub type DecimalPoints = u8;247248/// Collection mode.249///250/// Collection can represent various types of tokens.251/// Each collection can contain only one type of tokens at a time.252/// This type helps to understand which tokens the collection contains.253#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]254#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]255pub enum CollectionMode {256 /// Non fungible tokens.257 NFT,258 /// Fungible tokens.259 Fungible(DecimalPoints),260 /// Refungible tokens.261 ReFungible,262}263264impl CollectionMode {265 /// Get collection mod as number.266 pub fn id(&self) -> u8 {267 match self {268 CollectionMode::NFT => 1,269 CollectionMode::Fungible(_) => 2,270 CollectionMode::ReFungible => 3,271 }272 }273}274275// TODO: unused trait276pub trait SponsoringResolve<AccountId, Call> {277 fn resolve(who: &AccountId, call: &Call) -> Option<AccountId>;278}279280/// Access mode for some token operations.281#[derive(Encode, Decode, Eq, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]282#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]283pub enum AccessMode {284 /// Access grant for owner and admins. Used as default.285 Normal,286 /// Like a [`Normal`](AccessMode::Normal) but also users in allow list.287 AllowList,288}289impl Default for AccessMode {290 fn default() -> Self {291 Self::Normal292 }293}294295// TODO: remove in future.296#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]297#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]298pub enum SchemaVersion {299 ImageURL,300 Unique,301}302impl Default for SchemaVersion {303 fn default() -> Self {304 Self::ImageURL305 }306}307308// TODO: unused type309#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, TypeInfo)]310#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]311pub struct Ownership<AccountId> {312 pub owner: AccountId,313 pub fraction: u128,314}315316/// The state of collection sponsorship.317#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]318#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]319pub enum SponsorshipState<AccountId> {320 /// The fees are applied to the transaction sender.321 Disabled,322 /// The sponsor is under consideration. Until the sponsor gives his consent,323 /// the fee will still be charged to sender.324 Unconfirmed(AccountId),325 /// Transactions are sponsored by specified account.326 Confirmed(AccountId),327}328329impl<AccountId> SponsorshipState<AccountId> {330 /// Get a sponsor of the collection who has confirmed his status.331 pub fn sponsor(&self) -> Option<&AccountId> {332 match self {333 Self::Confirmed(sponsor) => Some(sponsor),334 _ => None,335 }336 }337338 /// Get a sponsor of the collection who has pending or confirmed status.339 pub fn pending_sponsor(&self) -> Option<&AccountId> {340 match self {341 Self::Unconfirmed(sponsor) | Self::Confirmed(sponsor) => Some(sponsor),342 _ => None,343 }344 }345346 /// Whether the sponsorship is confirmed.347 pub fn confirmed(&self) -> bool {348 matches!(self, Self::Confirmed(_))349 }350}351352impl<T> Default for SponsorshipState<T> {353 fn default() -> Self {354 Self::Disabled355 }356}357358pub type CollectionName = BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>;359pub type CollectionDescription = BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>;360pub type CollectionTokenPrefix = BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>;361362#[derive(Bitfields, Clone, Copy, PartialEq, Eq, Debug, Default)]363#[bondrewd(enforce_bytes = 1)]364pub struct CollectionFlags {365 /// Tokens in foreign collections can be transferred, but not burnt366 #[bondrewd(bits = "0..1")]367 pub foreign: bool,368 /// Supports ERC721Metadata369 #[bondrewd(bits = "1..2")]370 pub erc721metadata: bool,371 /// External collections can't be managed using `unique` api372 #[bondrewd(bits = "7..8")]373 pub external: bool,374375 #[bondrewd(reserve, bits = "2..7")]376 pub reserved: u8,377}378bondrewd_codec!(CollectionFlags);379380/// Base structure for represent collection.381///382/// Used to provide basic functionality for all types of collections.383///384/// #### Note385/// Collection parameters, used in storage (see [`RpcCollection`] for the RPC version).386#[struct_versioning::versioned(version = 2, upper)]387#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen)]388pub struct Collection<AccountId> {389 /// Collection owner account.390 pub owner: AccountId,391392 /// Collection mode.393 pub mode: CollectionMode,394395 /// Access mode.396 #[version(..2)]397 pub access: AccessMode,398399 /// Collection name.400 pub name: CollectionName,401402 /// Collection description.403 pub description: CollectionDescription,404405 /// Token prefix.406 pub token_prefix: CollectionTokenPrefix,407408 #[version(..2)]409 pub mint_mode: bool,410411 #[version(..2)]412 pub offchain_schema: BoundedVec<u8, ConstU32<OFFCHAIN_SCHEMA_LIMIT>>,413414 #[version(..2)]415 pub schema_version: SchemaVersion,416417 /// The state of sponsorship of the collection.418 pub sponsorship: SponsorshipState<AccountId>,419420 /// Collection limits.421 pub limits: CollectionLimits,422423 /// Collection permissions.424 #[version(2.., upper(Default::default()))]425 pub permissions: CollectionPermissions,426427 #[version(2.., upper(Default::default()))]428 pub flags: CollectionFlags,429430 #[version(..2)]431 pub variable_on_chain_schema: BoundedVec<u8, ConstU32<VARIABLE_ON_CHAIN_SCHEMA_LIMIT>>,432433 #[version(..2)]434 pub const_on_chain_schema: BoundedVec<u8, ConstU32<CONST_ON_CHAIN_SCHEMA_LIMIT>>,435436 #[version(..2)]437 pub meta_update_permission: MetaUpdatePermission,438}439440#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]441#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]442pub struct RpcCollectionFlags {443 /// Is collection is foreign.444 pub foreign: bool,445 /// Collection supports ERC721Metadata.446 pub erc721metadata: bool,447}448449/// Collection parameters, used in RPC calls (see [`Collection`] for the storage version).450#[struct_versioning::versioned(version = 2, upper)]451#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]452#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]453pub struct RpcCollection<AccountId> {454 /// Collection owner account.455 pub owner: AccountId,456457 /// Collection mode.458 pub mode: CollectionMode,459460 /// Collection name.461 pub name: Vec<u16>,462463 /// Collection description.464 pub description: Vec<u16>,465466 /// Token prefix.467 pub token_prefix: Vec<u8>,468469 /// The state of sponsorship of the collection.470 pub sponsorship: SponsorshipState<AccountId>,471472 /// Collection limits.473 pub limits: CollectionLimits,474475 /// Collection permissions.476 pub permissions: CollectionPermissions,477478 /// Token property permissions.479 pub token_property_permissions: Vec<PropertyKeyPermission>,480481 /// Collection properties.482 pub properties: Vec<Property>,483484 /// Is collection read only.485 pub read_only: bool,486487 /// Extra collection flags488 #[version(2.., upper(RpcCollectionFlags {foreign: false, erc721metadata: false}))]489 pub flags: RpcCollectionFlags,490}491492/// Data used for create collection.493///494/// All fields are wrapped in [`Option`], where `None` means chain default.495#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, Derivative, MaxEncodedLen)]496#[derivative(Debug, Default(bound = ""))]497pub struct CreateCollectionData<AccountId> {498 /// Collection mode.499 #[derivative(Default(value = "CollectionMode::NFT"))]500 pub mode: CollectionMode,501502 /// Access mode.503 pub access: Option<AccessMode>,504505 /// Collection name.506 pub name: CollectionName,507508 /// Collection description.509 pub description: CollectionDescription,510511 /// Token prefix.512 pub token_prefix: CollectionTokenPrefix,513514 /// Pending collection sponsor.515 pub pending_sponsor: Option<AccountId>,516517 /// Collection limits.518 pub limits: Option<CollectionLimits>,519520 /// Collection permissions.521 pub permissions: Option<CollectionPermissions>,522523 /// Token property permissions.524 pub token_property_permissions: CollectionPropertiesPermissionsVec,525526 /// Collection properties.527 pub properties: CollectionPropertiesVec,528}529530/// Bounded vector of properties permissions. Max length is [`MAX_PROPERTIES_PER_ITEM`].531// TODO: maybe rename to PropertiesPermissionsVec532pub type CollectionPropertiesPermissionsVec =533 BoundedVec<PropertyKeyPermission, ConstU32<MAX_PROPERTIES_PER_ITEM>>;534535/// Bounded vector of properties. Max length is [`MAX_PROPERTIES_PER_ITEM`].536pub type CollectionPropertiesVec = BoundedVec<Property, ConstU32<MAX_PROPERTIES_PER_ITEM>>;537538/// Limits and restrictions of a collection.539///540/// All fields are wrapped in [`Option`], where `None` means chain default.541///542/// Update with `pallet_common::Pallet::clamp_limits`.543// IMPORTANT: When adding/removing fields from this struct - don't forget to also544#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]545#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]546// When adding/removing fields from this struct - don't forget to also update with `pallet_common::Pallet::clamp_limits`.547// TODO: move `pallet_common::Pallet::clamp_limits` into `impl CollectionLimits`.548// TODO: may be remove [`Option`] and **pub** from fields and create struct with default values.549pub struct CollectionLimits {550 /// How many tokens can a user have on one account.551 /// * Default - [`ACCOUNT_TOKEN_OWNERSHIP_LIMIT`].552 /// * Limit - [`MAX_TOKEN_OWNERSHIP`].553 pub account_token_ownership_limit: Option<u32>,554555 /// How many bytes of data are available for sponsorship.556 /// * Default - [`CUSTOM_DATA_LIMIT`].557 /// * Limit - [`CUSTOM_DATA_LIMIT`].558 pub sponsored_data_size: Option<u32>,559560 // FIXME should we delete this or repurpose it?561 /// Times in how many blocks we sponsor data.562 ///563 /// If is `Some(v)` then **setVariableMetadata** is sponsored if there is `v` block between transactions.564 ///565 /// * Default - [`SponsoringDisabled`](SponsoringRateLimit::SponsoringDisabled).566 /// * Limit - [`MAX_SPONSOR_TIMEOUT`].567 ///568 /// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]569 pub sponsored_data_rate_limit: Option<SponsoringRateLimit>,570 /// Maximum amount of tokens inside the collection. Chain default: [`COLLECTION_TOKEN_LIMIT`]571572 /// How many tokens can be mined into this collection.573 ///574 /// * Default - [`COLLECTION_TOKEN_LIMIT`].575 /// * Limit - [`COLLECTION_TOKEN_LIMIT`].576 pub token_limit: Option<u32>,577578 /// Timeouts for transfer sponsoring.579 ///580 /// * Default581 /// - **Fungible** - [`FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT`]582 /// - **NFT** - [`NFT_SPONSOR_TRANSFER_TIMEOUT`]583 /// - **Refungible** - [`REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT`]584 /// * Limit - [`MAX_SPONSOR_TIMEOUT`].585 pub sponsor_transfer_timeout: Option<u32>,586587 /// Timeout for sponsoring an approval in passed blocks.588 ///589 /// * Default - [`SPONSOR_APPROVE_TIMEOUT`].590 /// * Limit - [`MAX_SPONSOR_TIMEOUT`].591 pub sponsor_approve_timeout: Option<u32>,592593 /// Whether the collection owner of the collection can send tokens (which belong to other users).594 ///595 /// * Default - **false**.596 pub owner_can_transfer: Option<bool>,597598 /// Can the collection owner burn other people's tokens.599 ///600 /// * Default - **true**.601 pub owner_can_destroy: Option<bool>,602603 /// Is it possible to send tokens from this collection between users.604 ///605 /// * Default - **true**.606 pub transfers_enabled: Option<bool>,607}608609impl CollectionLimits {610 /// Get effective value for [`account_token_ownership_limit`](self.account_token_ownership_limit).611 pub fn account_token_ownership_limit(&self) -> u32 {612 self.account_token_ownership_limit613 .unwrap_or(ACCOUNT_TOKEN_OWNERSHIP_LIMIT)614 .min(MAX_TOKEN_OWNERSHIP)615 }616617 /// Get effective value for [`sponsored_data_size`](self.sponsored_data_size).618 pub fn sponsored_data_size(&self) -> u32 {619 self.sponsored_data_size620 .unwrap_or(CUSTOM_DATA_LIMIT)621 .min(CUSTOM_DATA_LIMIT)622 }623624 /// Get effective value for [`token_limit`](self.token_limit).625 pub fn token_limit(&self) -> u32 {626 self.token_limit627 .unwrap_or(COLLECTION_TOKEN_LIMIT)628 .min(COLLECTION_TOKEN_LIMIT)629 }630631 // TODO: may be replace u32 to mode?632 /// Get effective value for [`sponsor_transfer_timeout`](self.sponsor_transfer_timeout).633 pub fn sponsor_transfer_timeout(&self, default: u32) -> u32 {634 self.sponsor_transfer_timeout635 .unwrap_or(default)636 .min(MAX_SPONSOR_TIMEOUT)637 }638639 /// Get effective value for [`sponsor_approve_timeout`](self.sponsor_approve_timeout).640 pub fn sponsor_approve_timeout(&self) -> u32 {641 self.sponsor_approve_timeout642 .unwrap_or(SPONSOR_APPROVE_TIMEOUT)643 .min(MAX_SPONSOR_TIMEOUT)644 }645646 /// Get effective value for [`owner_can_transfer`](self.owner_can_transfer).647 pub fn owner_can_transfer(&self) -> bool {648 self.owner_can_transfer.unwrap_or(false)649 }650651 /// Get effective value for [`owner_can_transfer_instaled`](self.owner_can_transfer_instaled).652 pub fn owner_can_transfer_instaled(&self) -> bool {653 self.owner_can_transfer.is_some()654 }655656 /// Get effective value for [`owner_can_destroy`](self.owner_can_destroy).657 pub fn owner_can_destroy(&self) -> bool {658 self.owner_can_destroy.unwrap_or(true)659 }660661 /// Get effective value for [`transfers_enabled`](self.transfers_enabled).662 pub fn transfers_enabled(&self) -> bool {663 self.transfers_enabled.unwrap_or(true)664 }665666 /// Get effective value for [`sponsored_data_rate_limit`](self.sponsored_data_rate_limit).667 pub fn sponsored_data_rate_limit(&self) -> Option<u32> {668 match self669 .sponsored_data_rate_limit670 .unwrap_or(SponsoringRateLimit::SponsoringDisabled)671 {672 SponsoringRateLimit::SponsoringDisabled => None,673 SponsoringRateLimit::Blocks(v) => Some(v.min(MAX_SPONSOR_TIMEOUT)),674 }675 }676}677678/// Permissions on certain operations within a collection.679///680/// Some fields are wrapped in [`Option`], where `None` means chain default.681///682/// Update with `pallet_common::Pallet::clamp_permissions`.683#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]684#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]685// When adding/removing fields from this struct - don't forget to also update `pallet_common::Pallet::clamp_permissions`.686// TODO: move `pallet_common::Pallet::clamp_permissions` into `impl CollectionPermissions`.687pub struct CollectionPermissions {688 /// Access mode.689 ///690 /// * Default - [`AccessMode::Normal`].691 pub access: Option<AccessMode>,692693 /// Minting allowance.694 ///695 /// * Default - **false**.696 pub mint_mode: Option<bool>,697698 /// Permissions for nesting.699 ///700 /// * Default701 /// - `token_owner` - **false**702 /// - `collection_admin` - **false**703 /// - `restricted` - **None**704 pub nesting: Option<NestingPermissions>,705}706707impl CollectionPermissions {708 /// Get effective value for [`access`](self.access).709 pub fn access(&self) -> AccessMode {710 self.access.unwrap_or(AccessMode::Normal)711 }712713 /// Get effective value for [`mint_mode`](self.mint_mode).714 pub fn mint_mode(&self) -> bool {715 self.mint_mode.unwrap_or(false)716 }717718 /// Get effective value for [`nesting`](self.nesting).719 pub fn nesting(&self) -> &NestingPermissions {720 static DEFAULT: NestingPermissions = NestingPermissions {721 token_owner: false,722 collection_admin: false,723 restricted: None,724 #[cfg(feature = "runtime-benchmarks")]725 permissive: false,726 };727 self.nesting.as_ref().unwrap_or(&DEFAULT)728 }729}730731/// Inner set for collections allowed to nest.732type OwnerRestrictedSetInner = BoundedBTreeSet<CollectionId, ConstU32<16>>;733734/// Wraper for collections set allowing nest.735#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]736#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]737#[derivative(Debug)]738pub struct OwnerRestrictedSet(739 #[cfg_attr(feature = "serde1", serde(with = "bounded::set_serde"))]740 #[derivative(Debug(format_with = "bounded::set_debug"))]741 pub OwnerRestrictedSetInner,742);743744impl OwnerRestrictedSet {745 /// Create new set.746 pub fn new() -> Self {747 Self(Default::default())748 }749}750impl core::ops::Deref for OwnerRestrictedSet {751 type Target = OwnerRestrictedSetInner;752 fn deref(&self) -> &Self::Target {753 &self.0754 }755}756impl core::ops::DerefMut for OwnerRestrictedSet {757 fn deref_mut(&mut self) -> &mut Self::Target {758 &mut self.0759 }760}761762/// Part of collection permissions, if set, defines who is able to nest tokens into other tokens.763#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]764#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]765#[derivative(Debug)]766pub struct NestingPermissions {767 /// Owner of token can nest tokens under it.768 pub token_owner: bool,769 /// Admin of token collection can nest tokens under token.770 pub collection_admin: bool,771 /// If set - only tokens from specified collections can be nested.772 pub restricted: Option<OwnerRestrictedSet>,773774 #[cfg(feature = "runtime-benchmarks")]775 /// Anyone can nest tokens, mutually exclusive with `token_owner`, `admin`.776 pub permissive: bool,777}778779/// Enum denominating how often can sponsoring occur if it is enabled.780///781/// Used for [`collection limits`](CollectionLimits).782#[derive(Encode, Decode, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]783#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]784pub enum SponsoringRateLimit {785 /// Sponsoring is disabled, and the collection sponsor will not pay for transactions786 SponsoringDisabled,787 /// Once per how many blocks can sponsorship of a transaction type occur788 Blocks(u32),789}790791/// Data used to describe an NFT at creation.792#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]793#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]794#[derivative(Debug)]795pub struct CreateNftData {796 /// Key-value pairs used to describe the token as metadata797 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]798 #[derivative(Debug(format_with = "bounded::vec_debug"))]799 /// Properties that wil be assignet to created item.800 pub properties: CollectionPropertiesVec,801}802803/// Data used to describe a Fungible token at creation.804#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq, TypeInfo)]805#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]806pub struct CreateFungibleData {807 /// Number of fungible coins minted808 pub value: u128,809}810811/// Data used to describe a Refungible token at creation.812#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]813#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]814#[derivative(Debug)]815pub struct CreateReFungibleData {816 /// Number of pieces the RFT is split into817 pub pieces: u128,818819 /// Key-value pairs used to describe the token as metadata820 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]821 #[derivative(Debug(format_with = "bounded::vec_debug"))]822 pub properties: CollectionPropertiesVec,823}824825// TODO: remove this.826#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]827#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]828pub enum MetaUpdatePermission {829 ItemOwner,830 Admin,831 None,832}833834/// Enum holding data used for creation of all three item types.835/// Unified data for create item.836#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]837#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]838pub enum CreateItemData {839 /// Data for create NFT.840 NFT(CreateNftData),841 /// Data for create Fungible item.842 Fungible(CreateFungibleData),843 /// Data for create ReFungible item.844 ReFungible(CreateReFungibleData),845}846847/// Extended data for create NFT.848#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]849#[derivative(Debug)]850pub struct CreateNftExData<CrossAccountId> {851 /// Properties that wil be assignet to created item.852 #[derivative(Debug(format_with = "bounded::vec_debug"))]853 pub properties: CollectionPropertiesVec,854855 /// Owner of creating item.856 pub owner: CrossAccountId,857}858859/// Extended data for create ReFungible item.860#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]861#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]862pub struct CreateRefungibleExMultipleOwners<CrossAccountId> {863 #[derivative(Debug(format_with = "bounded::map_debug"))]864 pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,865 #[derivative(Debug(format_with = "bounded::vec_debug"))]866 pub properties: CollectionPropertiesVec,867}868869/// Extended data for create ReFungible item.870#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]871#[derivative(Debug(bound = "CrossAccountId: fmt::Debug"))]872pub struct CreateRefungibleExSingleOwner<CrossAccountId> {873 pub user: CrossAccountId,874 pub pieces: u128,875 #[derivative(Debug(format_with = "bounded::vec_debug"))]876 pub properties: CollectionPropertiesVec,877}878879/// Unified extended data for creating item.880#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]881#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]882pub enum CreateItemExData<CrossAccountId> {883 /// Extended data for create NFT.884 NFT(885 #[derivative(Debug(format_with = "bounded::vec_debug"))]886 BoundedVec<CreateNftExData<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,887 ),888889 /// Extended data for create Fungible item.890 Fungible(891 #[derivative(Debug(format_with = "bounded::map_debug"))]892 BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,893 ),894895 /// Extended data for create ReFungible item in case of896 /// many tokens, each may have only one owner897 RefungibleMultipleItems(898 #[derivative(Debug(format_with = "bounded::vec_debug"))]899 BoundedVec<CreateRefungibleExSingleOwner<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,900 ),901902 /// Extended data for create ReFungible item in case of903 /// single token, which may have many owners904 RefungibleMultipleOwners(CreateRefungibleExMultipleOwners<CrossAccountId>),905}906907impl From<CreateNftData> for CreateItemData {908 fn from(item: CreateNftData) -> Self {909 CreateItemData::NFT(item)910 }911}912913impl From<CreateReFungibleData> for CreateItemData {914 fn from(item: CreateReFungibleData) -> Self {915 CreateItemData::ReFungible(item)916 }917}918919impl From<CreateFungibleData> for CreateItemData {920 fn from(item: CreateFungibleData) -> Self {921 CreateItemData::Fungible(item)922 }923}924925/// Token's address, dictated by its collection and token IDs.926#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]927#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]928// todo possibly rename to be used generally as an address pair929pub struct TokenChild {930 /// Token id.931 pub token: TokenId,932933 /// Collection id.934 pub collection: CollectionId,935}936937/// Collection statistics.938#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]939#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]940pub struct CollectionStats {941 /// Number of created items.942 pub created: u32,943944 /// Number of burned items.945 pub destroyed: u32,946947 /// Number of current items.948 pub alive: u32,949}950951/// This type works like [`PhantomData`] but supports generating _scale-info_ descriptions to generate node metadata.952#[derive(Encode, Decode, Clone, Debug)]953#[cfg_attr(feature = "std", derive(PartialEq))]954pub struct PhantomType<T>(core::marker::PhantomData<T>);955956impl<T: TypeInfo + 'static> TypeInfo for PhantomType<T> {957 type Identity = PhantomType<T>;958959 fn type_info() -> scale_info::Type {960 use scale_info::{961 Type, Path,962 build::{FieldsBuilder, UnnamedFields},963 type_params,964 };965 Type::builder()966 .path(Path::new("up_data_structs", "PhantomType"))967 .type_params(type_params!(T))968 .composite(<FieldsBuilder<UnnamedFields>>::default().field(|b| b.ty::<[T; 0]>()))969 }970}971impl<T> MaxEncodedLen for PhantomType<T> {972 fn max_encoded_len() -> usize {973 0974 }975}976977/// Bounded vector of bytes.978pub type BoundedBytes<S> = BoundedVec<u8, S>;979980/// Extra properties for external collections.981pub type AuxPropertyValue = BoundedBytes<ConstU32<MAX_AUX_PROPERTY_VALUE_LENGTH>>;982983/// Property key.984pub type PropertyKey = BoundedBytes<ConstU32<MAX_PROPERTY_KEY_LENGTH>>;985986/// Property value.987pub type PropertyValue = BoundedBytes<ConstU32<MAX_PROPERTY_VALUE_LENGTH>>;988989/// Property permission.990#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone)]991#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]992pub struct PropertyPermission {993 /// Permission to change the property and property permission.994 ///995 /// If it **false** then you can not change corresponding property even if [`collection_admin`] and [`token_owner`] are **true**.996 pub mutable: bool,997998 /// Change permission for the collection administrator.999 pub collection_admin: bool,10001001 /// Permission to change the property for the owner of the token.1002 pub token_owner: bool,1003}10041005impl PropertyPermission {1006 /// Creates mutable property permission but changes restricted for collection admin and token owner.1007 pub fn none() -> Self {1008 Self {1009 mutable: true,1010 collection_admin: false,1011 token_owner: false,1012 }1013 }1014}10151016/// Property is simpl key-value record.1017#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, MaxEncodedLen)]1018#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1019pub struct Property {1020 /// Property key.1021 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1022 pub key: PropertyKey,10231024 /// Property value.1025 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1026 pub value: PropertyValue,1027}10281029impl Into<(PropertyKey, PropertyValue)> for Property {1030 fn into(self) -> (PropertyKey, PropertyValue) {1031 (self.key, self.value)1032 }1033}10341035/// Record for proprty key permission.1036#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone)]1037#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1038pub struct PropertyKeyPermission {1039 /// Key.1040 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1041 pub key: PropertyKey,10421043 /// Permission.1044 pub permission: PropertyPermission,1045}10461047impl Into<(PropertyKey, PropertyPermission)> for PropertyKeyPermission {1048 fn into(self) -> (PropertyKey, PropertyPermission) {1049 (self.key, self.permission)1050 }1051}10521053/// Errors for properties actions.1054#[derive(Debug)]1055pub enum PropertiesError {1056 /// The space allocated for properties has run out.1057 ///1058 /// * Limit for colection - [`MAX_COLLECTION_PROPERTIES_SIZE`].1059 /// * Limit for token - [`MAX_TOKEN_PROPERTIES_SIZE`].1060 NoSpaceForProperty,10611062 /// The property limit has been reached.1063 ///1064 /// * Limit - [`MAX_PROPERTIES_PER_ITEM`].1065 PropertyLimitReached,10661067 /// Property key contains not allowed character.1068 InvalidCharacterInPropertyKey,10691070 /// Property key length is too long.1071 ///1072 /// * Limit - [`MAX_PROPERTY_KEY_LENGTH`].1073 PropertyKeyIsTooLong,10741075 /// Property key is empty.1076 EmptyPropertyKey,1077}10781079/// Marker for scope of property.1080///1081/// Scoped property can't be changed by user. Used for external collections.1082#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Clone, Copy)]1083pub enum PropertyScope {1084 None,1085 Rmrk,1086}10871088impl PropertyScope {1089 /// Apply scope to property key.1090 pub fn apply(self, key: PropertyKey) -> Result<PropertyKey, PropertiesError> {1091 let scope_str: &[u8] = match self {1092 Self::None => return Ok(key),1093 Self::Rmrk => b"rmrk",1094 };10951096 [scope_str, b":", key.as_slice()]1097 .concat()1098 .try_into()1099 .map_err(|_| PropertiesError::PropertyKeyIsTooLong)1100 }1101}11021103/// Trait for operate with properties.1104pub trait TrySetProperty: Sized {1105 type Value;11061107 /// Try to set property with scope.1108 fn try_scoped_set(1109 &mut self,1110 scope: PropertyScope,1111 key: PropertyKey,1112 value: Self::Value,1113 ) -> Result<(), PropertiesError>;11141115 /// Try to set property with scope from iterator.1116 fn try_scoped_set_from_iter<I, KV>(1117 &mut self,1118 scope: PropertyScope,1119 iter: I,1120 ) -> Result<(), PropertiesError>1121 where1122 I: Iterator<Item = KV>,1123 KV: Into<(PropertyKey, Self::Value)>,1124 {1125 for kv in iter {1126 let (key, value) = kv.into();1127 self.try_scoped_set(scope, key, value)?;1128 }11291130 Ok(())1131 }11321133 /// Try to set property.1134 fn try_set(&mut self, key: PropertyKey, value: Self::Value) -> Result<(), PropertiesError> {1135 self.try_scoped_set(PropertyScope::None, key, value)1136 }11371138 /// Try to set property from iterator.1139 fn try_set_from_iter<I, KV>(&mut self, iter: I) -> Result<(), PropertiesError>1140 where1141 I: Iterator<Item = KV>,1142 KV: Into<(PropertyKey, Self::Value)>,1143 {1144 self.try_scoped_set_from_iter(PropertyScope::None, iter)1145 }1146}11471148/// Wrapped map for storing properties.1149#[derive(Encode, Decode, TypeInfo, Derivative, Clone, PartialEq, MaxEncodedLen)]1150#[derivative(Default(bound = ""))]1151pub struct PropertiesMap<Value>(1152 BoundedBTreeMap<PropertyKey, Value, ConstU32<MAX_PROPERTIES_PER_ITEM>>,1153);11541155impl<Value> PropertiesMap<Value> {1156 /// Create new property map.1157 pub fn new() -> Self {1158 Self(BoundedBTreeMap::new())1159 }11601161 /// Remove property from map.1162 pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<Value>, PropertiesError> {1163 Self::check_property_key(key)?;11641165 Ok(self.0.remove(key))1166 }11671168 /// Get property with appropriate key from map.1169 pub fn get(&self, key: &PropertyKey) -> Option<&Value> {1170 self.0.get(key)1171 }11721173 /// Check if map contains key.1174 pub fn contains_key(&self, key: &PropertyKey) -> bool {1175 self.0.contains_key(key)1176 }11771178 /// Check if map contains key with key validation.1179 fn check_property_key(key: &PropertyKey) -> Result<(), PropertiesError> {1180 if key.is_empty() {1181 return Err(PropertiesError::EmptyPropertyKey);1182 }11831184 for byte in key.as_slice().iter() {1185 let byte = *byte;11861187 if !byte.is_ascii_alphanumeric() && byte != b'_' && byte != b'-' && byte != b'.' {1188 return Err(PropertiesError::InvalidCharacterInPropertyKey);1189 }1190 }11911192 Ok(())1193 }1194}11951196impl<Value> IntoIterator for PropertiesMap<Value> {1197 type Item = (PropertyKey, Value);1198 type IntoIter = <1199 BoundedBTreeMap<1200 PropertyKey,1201 Value,1202 ConstU32<MAX_PROPERTIES_PER_ITEM>1203 > as IntoIterator1204 >::IntoIter;12051206 fn into_iter(self) -> Self::IntoIter {1207 self.0.into_iter()1208 }1209}12101211impl<Value> TrySetProperty for PropertiesMap<Value> {1212 type Value = Value;12131214 fn try_scoped_set(1215 &mut self,1216 scope: PropertyScope,1217 key: PropertyKey,1218 value: Self::Value,1219 ) -> Result<(), PropertiesError> {1220 Self::check_property_key(&key)?;12211222 let key = scope.apply(key)?;1223 self.01224 .try_insert(key, value)1225 .map_err(|_| PropertiesError::PropertyLimitReached)?;12261227 Ok(())1228 }1229}12301231/// Alias for property permissions map.1232pub type PropertiesPermissionMap = PropertiesMap<PropertyPermission>;12331234/// Wrapper for properties map with consumed space control.1235#[derive(Encode, Decode, TypeInfo, Clone, PartialEq, MaxEncodedLen)]1236pub struct Properties {1237 map: PropertiesMap<PropertyValue>,1238 consumed_space: u32,1239 space_limit: u32,1240}12411242impl Properties {1243 /// Create new properies container.1244 pub fn new(space_limit: u32) -> Self {1245 Self {1246 map: PropertiesMap::new(),1247 consumed_space: 0,1248 space_limit,1249 }1250 }12511252 /// Remove propery with appropiate key.1253 pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<PropertyValue>, PropertiesError> {1254 let value = self.map.remove(key)?;12551256 if let Some(ref value) = value {1257 let value_len = value.len() as u32;1258 self.consumed_space -= value_len;1259 }12601261 Ok(value)1262 }12631264 /// Get property with appropriate key.1265 pub fn get(&self, key: &PropertyKey) -> Option<&PropertyValue> {1266 self.map.get(key)1267 }1268}12691270impl IntoIterator for Properties {1271 type Item = (PropertyKey, PropertyValue);1272 type IntoIter = <PropertiesMap<PropertyValue> as IntoIterator>::IntoIter;12731274 fn into_iter(self) -> Self::IntoIter {1275 self.map.into_iter()1276 }1277}12781279impl TrySetProperty for Properties {1280 type Value = PropertyValue;12811282 fn try_scoped_set(1283 &mut self,1284 scope: PropertyScope,1285 key: PropertyKey,1286 value: Self::Value,1287 ) -> Result<(), PropertiesError> {1288 let value_len = value.len();12891290 if self.consumed_space as usize + value_len > self.space_limit as usize1291 && !cfg!(feature = "runtime-benchmarks")1292 {1293 return Err(PropertiesError::NoSpaceForProperty);1294 }12951296 self.map.try_scoped_set(scope, key, value)?;12971298 self.consumed_space += value_len as u32;12991300 Ok(())1301 }1302}13031304/// Utility struct for using in `StorageMap`.1305pub struct CollectionProperties;13061307impl Get<Properties> for CollectionProperties {1308 fn get() -> Properties {1309 Properties::new(MAX_COLLECTION_PROPERTIES_SIZE)1310 }1311}13121313/// Utility struct for using in `StorageMap`.1314pub struct TokenProperties;13151316impl Get<Properties> for TokenProperties {1317 fn get() -> Properties {1318 Properties::new(MAX_TOKEN_PROPERTIES_SIZE)1319 }1320}13211322// RMRK1323// todo document?1324parameter_types! {1325 #[derive(PartialEq, TypeInfo)]1326 pub const RmrkStringLimit: u32 = 128;1327 #[derive(PartialEq)]1328 pub const RmrkCollectionSymbolLimit: u32 = MAX_TOKEN_PREFIX_LENGTH;1329 #[derive(PartialEq)]1330 pub const RmrkResourceSymbolLimit: u32 = 10;1331 #[derive(PartialEq)]1332 pub const RmrkBaseSymbolLimit: u32 = MAX_TOKEN_PREFIX_LENGTH;1333 #[derive(PartialEq)]1334 pub const RmrkKeyLimit: u32 = 32;1335 #[derive(PartialEq)]1336 pub const RmrkValueLimit: u32 = 256;1337 #[derive(PartialEq)]1338 pub const RmrkMaxCollectionsEquippablePerPart: u32 = 100;1339 #[derive(PartialEq)]1340 pub const MaxPropertiesPerTheme: u32 = 5;1341 #[derive(PartialEq)]1342 pub const RmrkPartsLimit: u32 = 25;1343 #[derive(PartialEq)]1344 pub const RmrkMaxPriorities: u32 = 25;1345 #[derive(PartialEq)]1346 pub const MaxResourcesOnMint: u32 = 100;1347}13481349impl From<RmrkCollectionId> for CollectionId {1350 fn from(id: RmrkCollectionId) -> Self {1351 Self(id)1352 }1353}13541355impl From<RmrkNftId> for TokenId {1356 fn from(id: RmrkNftId) -> Self {1357 Self(id)1358 }1359}13601361pub type RmrkCollectionInfo<AccountId> =1362 CollectionInfo<RmrkString, RmrkCollectionSymbol, AccountId>;1363pub type RmrkInstanceInfo<AccountId> = NftInfo<AccountId, Permill, RmrkString>;1364pub type RmrkResourceInfo = ResourceInfo<RmrkString, RmrkBoundedParts>;1365pub type RmrkPropertyInfo = PropertyInfo<RmrkKeyString, RmrkValueString>;1366pub type RmrkBaseInfo<AccountId> = BaseInfo<AccountId, RmrkString>;1367pub type BoundedEquippableCollectionIds =1368 BoundedVec<RmrkCollectionId, RmrkMaxCollectionsEquippablePerPart>;1369pub type RmrkPartType = PartType<RmrkString, BoundedEquippableCollectionIds>;1370pub type RmrkEquippableList = EquippableList<BoundedEquippableCollectionIds>;1371pub type RmrkThemeProperty = ThemeProperty<RmrkString>;1372pub type RmrkTheme = Theme<RmrkString, Vec<RmrkThemeProperty>>;1373pub type RmrkBoundedTheme = Theme<RmrkString, BoundedVec<RmrkThemeProperty, MaxPropertiesPerTheme>>;1374pub type RmrkResourceTypes = ResourceTypes<RmrkString, RmrkBoundedParts>;13751376pub type RmrkBasicResource = BasicResource<RmrkString>;1377pub type RmrkComposableResource = ComposableResource<RmrkString, RmrkBoundedParts>;1378pub type RmrkSlotResource = SlotResource<RmrkString>;13791380pub type RmrkString = BoundedVec<u8, RmrkStringLimit>;1381pub type RmrkCollectionSymbol = BoundedVec<u8, RmrkCollectionSymbolLimit>;1382pub type RmrkBaseSymbol = BoundedVec<u8, RmrkBaseSymbolLimit>;1383pub type RmrkKeyString = BoundedVec<u8, RmrkKeyLimit>;1384pub type RmrkValueString = BoundedVec<u8, RmrkValueLimit>;1385pub type RmrkBoundedResource = BoundedVec<u8, RmrkResourceSymbolLimit>;1386pub type RmrkBoundedParts = BoundedVec<RmrkPartId, RmrkPartsLimit>; // todo make sure it is needed13871388pub type RmrkRpcString = Vec<u8>;1389pub type RmrkThemeName = RmrkRpcString;1390pub type RmrkPropertyKey = RmrkRpcString;primitives/rpc/src/lib.rsdiffbeforeafterboth--- a/primitives/rpc/src/lib.rs
+++ b/primitives/rpc/src/lib.rs
@@ -16,9 +16,11 @@
#![cfg_attr(not(feature = "std"), no_std)]
+extern crate alloc;
+
use up_data_structs::{
CollectionId, TokenId, RpcCollection, CollectionStats, CollectionLimits, Property,
- PropertyKeyPermission, TokenData, TokenChild,
+ PropertyKeyPermission, TokenData, TokenChild, RpcCollectionVersion1,
};
use sp_std::vec::Vec;
@@ -28,15 +30,12 @@
type Result<T> = core::result::Result<T, DispatchError>;
sp_api::decl_runtime_apis! {
- #[api_version(2)]
+ #[api_version(3)]
/// Trait for generate rpc.
pub trait UniqueApi<CrossAccountId, AccountId> where
AccountId: Decode,
CrossAccountId: pallet_evm::account::CrossAccountId<AccountId>,
{
- #[changed_in(2)]
- fn token_owner(collection: CollectionId, token: TokenId) -> Result<CrossAccountId>;
-
/// Get number of tokens in collection owned by account.
fn account_tokens(collection: CollectionId, account: CrossAccountId) -> Result<Vec<TokenId>>;
@@ -110,6 +109,9 @@
/// Get collection by id.
fn collection_by_id(collection: CollectionId) -> Result<Option<RpcCollection<AccountId>>>;
+ #[changed_in(3)]
+ fn collection_by_id(collection: CollectionId) -> Result<Option<RpcCollectionVersion1<AccountId>>>;
+
/// Get collection stats.
fn collection_stats() -> Result<CollectionStats>;