difftreelog
feat allow more fields to be set on collection creation
in: master
7 files changed
pallets/common/src/lib.rsdiffbeforeafterboth14 COLLECTION_NUMBER_LIMIT, Collection, CollectionId, CreateItemData, ExistenceRequirement,14 COLLECTION_NUMBER_LIMIT, Collection, CollectionId, CreateItemData, ExistenceRequirement,15 MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_COLLECTION_NAME_LENGTH, MAX_TOKEN_PREFIX_LENGTH,15 MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_COLLECTION_NAME_LENGTH, MAX_TOKEN_PREFIX_LENGTH,16 COLLECTION_ADMINS_LIMIT, MetaUpdatePermission, Pays, PostDispatchInfo, TokenId, Weight,16 COLLECTION_ADMINS_LIMIT, MetaUpdatePermission, Pays, PostDispatchInfo, TokenId, Weight,17 WithdrawReasons, CollectionStats,17 WithdrawReasons, CollectionStats, MAX_TOKEN_OWNERSHIP, CollectionMode,18 NFT_SPONSOR_TRANSFER_TIMEOUT, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,19 REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MAX_SPONSOR_TIMEOUT, CUSTOM_DATA_LIMIT, CollectionLimits,20 CreateCollectionData, SponsorshipState,18};21};19pub use pallet::*;22pub use pallet::*;20use sp_core::H160;23use sp_core::H160;282 TokenVariableDataLimitExceeded,285 TokenVariableDataLimitExceeded,283 /// Exceeded max admin count286 /// Exceeded max admin count284 CollectionAdminCountExceeded,287 CollectionAdminCountExceeded,288 /// Collection limit bounds per collection exceeded289 CollectionLimitBoundsExceeded,290 /// Tried to enable permissions which are only permitted to be disabled291 OwnerPermissionsCantBeReverted,285292286 /// Collection settings not allowing items transferring293 /// Collection settings not allowing items transferring287 TransferNotAllowed,294 TransferNotAllowed,392}399}393400394impl<T: Config> Pallet<T> {401impl<T: Config> Pallet<T> {395 pub fn init_collection(data: Collection<T::AccountId>) -> Result<CollectionId, DispatchError> {402 pub fn init_collection(403 owner: T::AccountId,404 data: CreateCollectionData<T::AccountId>,405 ) -> Result<CollectionId, DispatchError> {396 {406 {397 ensure!(407 ensure!(423433424 // =========434 // =========435436 let collection = Collection {437 owner: owner.clone(),438 name: data.name,439 mode: data.mode.clone(),440 mint_mode: false,441 access: data.access.unwrap_or_default(),442 description: data.description,443 token_prefix: data.token_prefix,444 offchain_schema: data.offchain_schema,445 schema_version: data.schema_version.unwrap_or_default(),446 sponsorship: data447 .pending_sponsor448 .map(SponsorshipState::Unconfirmed)449 .unwrap_or_default(),450 variable_on_chain_schema: data.variable_on_chain_schema,451 const_on_chain_schema: data.const_on_chain_schema,452 limits: data453 .limits454 .map(|limits| Self::clamp_limits(data.mode.clone(), &Default::default(), limits))455 .unwrap_or_else(|| Ok(CollectionLimits::default()))?,456 meta_update_permission: data.meta_update_permission.unwrap_or_default(),457 };425458426 // Take a (non-refundable) deposit of collection creation459 // Take a (non-refundable) deposit of collection creation427 {460 {434 ),467 ),435 );468 );436 <T as Config>::Currency::settle(469 <T as Config>::Currency::settle(437 &data.owner,470 &owner,438 imbalance,471 imbalance,439 WithdrawReasons::TRANSFER,472 WithdrawReasons::TRANSFER,440 ExistenceRequirement::KeepAlive,473 ExistenceRequirement::KeepAlive,446 <Pallet<T>>::deposit_event(Event::CollectionCreated(479 <Pallet<T>>::deposit_event(Event::CollectionCreated(id, data.mode.id(), owner.clone()));447 id,448 data.mode.id(),449 data.owner.clone(),450 ));451 <CollectionById<T>>::insert(id, data);480 <CollectionById<T>>::insert(id, collection);452 Ok(id)481 Ok(id)453 }482 }454483533 Ok(())562 Ok(())534 }563 }564565 pub fn clamp_limits(566 mode: CollectionMode,567 old_limit: &CollectionLimits,568 mut new_limit: CollectionLimits,569 ) -> Result<CollectionLimits, DispatchError> {570 macro_rules! limit_default {571 ($old:ident, $new:ident, $($field:ident $(($arg:expr))? => $check:expr),* $(,)?) => {{572 $(573 if let Some($new) = $new.$field {574 let $old = $old.$field($($arg)?);575 let _ = $new;576 let _ = $old;577 $check578 } else {579 $new.$field = $old.$field580 }581 )*582 }};583 }584585 limit_default!(old_limit, new_limit,586 account_token_ownership_limit => ensure!(587 new_limit <= MAX_TOKEN_OWNERSHIP,588 <Error<T>>::CollectionLimitBoundsExceeded,589 ),590 sponsor_transfer_timeout(match mode {591 CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,592 CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,593 CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,594 }) => ensure!(595 new_limit <= MAX_SPONSOR_TIMEOUT,596 <Error<T>>::CollectionLimitBoundsExceeded,597 ),598 sponsored_data_size => ensure!(599 new_limit <= CUSTOM_DATA_LIMIT,600 <Error<T>>::CollectionLimitBoundsExceeded,601 ),602 token_limit => ensure!(603 old_limit >= new_limit && new_limit > 0,604 <Error<T>>::CollectionTokenLimitExceeded605 ),606 owner_can_transfer => ensure!(607 old_limit || !new_limit,608 <Error<T>>::OwnerPermissionsCantBeReverted,609 ),610 owner_can_destroy => ensure!(611 old_limit || !new_limit,612 <Error<T>>::OwnerPermissionsCantBeReverted,613 ),614 sponsored_data_rate_limit => {},615 transfers_enabled => {},616 );617 Ok(new_limit)618 }535}619}536620537#[macro_export]621#[macro_export]pallets/fungible/src/lib.rsdiffbeforeafterboth223use core::ops::Deref;3use core::ops::Deref;4use frame_support::{ensure};4use frame_support::{ensure};5use up_data_structs::{AccessMode, Collection, CollectionId, TokenId};5use up_data_structs::{AccessMode, Collection, CollectionId, TokenId, CreateCollectionData};6use pallet_common::{6use pallet_common::{7 Error as CommonError, Event as CommonEvent, Pallet as PalletCommon, account::CrossAccountId,7 Error as CommonError, Event as CommonEvent, Pallet as PalletCommon, account::CrossAccountId,8};8};100}100}101101102impl<T: Config> Pallet<T> {102impl<T: Config> Pallet<T> {103 pub fn init_collection(data: Collection<T::AccountId>) -> Result<CollectionId, DispatchError> {103 pub fn init_collection(104 owner: T::AccountId,105 data: CreateCollectionData<T::AccountId>,106 ) -> Result<CollectionId, DispatchError> {104 <PalletCommon<T>>::init_collection(data)107 <PalletCommon<T>>::init_collection(owner, data)105 }108 }106 pub fn destroy_collection(109 pub fn destroy_collection(107 collection: FungibleHandle<T>,110 collection: FungibleHandle<T>,pallets/nonfungible/src/lib.rsdiffbeforeafterboth4use frame_support::{BoundedVec, ensure};4use frame_support::{BoundedVec, ensure};5use up_data_structs::{5use up_data_structs::{6 AccessMode, CUSTOM_DATA_LIMIT, Collection, CollectionId, CustomDataLimit, TokenId,6 AccessMode, CUSTOM_DATA_LIMIT, Collection, CollectionId, CustomDataLimit, TokenId,7 CreateCollectionData,7};8};8use pallet_common::{9use pallet_common::{9 Error as CommonError, Pallet as PalletCommon, Event as CommonEvent, account::CrossAccountId,10 Error as CommonError, Pallet as PalletCommon, Event as CommonEvent, account::CrossAccountId,142143143// unchecked calls skips any permission checks144// unchecked calls skips any permission checks144impl<T: Config> Pallet<T> {145impl<T: Config> Pallet<T> {145 pub fn init_collection(data: Collection<T::AccountId>) -> Result<CollectionId, DispatchError> {146 pub fn init_collection(147 owner: T::AccountId,148 data: CreateCollectionData<T::AccountId>,149 ) -> Result<CollectionId, DispatchError> {146 <PalletCommon<T>>::init_collection(data)150 <PalletCommon<T>>::init_collection(owner, data)147 }151 }148 pub fn destroy_collection(152 pub fn destroy_collection(149 collection: NonfungibleHandle<T>,153 collection: NonfungibleHandle<T>,pallets/refungible/src/lib.rsdiffbeforeafterboth3use frame_support::{ensure, BoundedVec};3use frame_support::{ensure, BoundedVec};4use up_data_structs::{4use up_data_structs::{5 AccessMode, CUSTOM_DATA_LIMIT, Collection, CollectionId, CustomDataLimit,5 AccessMode, CUSTOM_DATA_LIMIT, Collection, CollectionId, CustomDataLimit,6 MAX_REFUNGIBLE_PIECES, TokenId,6 MAX_REFUNGIBLE_PIECES, TokenId, CreateCollectionData,7};7};8use pallet_common::{8use pallet_common::{9 Error as CommonError, Event as CommonEvent, Pallet as PalletCommon, account::CrossAccountId,9 Error as CommonError, Event as CommonEvent, Pallet as PalletCommon, account::CrossAccountId,156156157// unchecked calls skips any permission checks157// unchecked calls skips any permission checks158impl<T: Config> Pallet<T> {158impl<T: Config> Pallet<T> {159 pub fn init_collection(data: Collection<T::AccountId>) -> Result<CollectionId, DispatchError> {159 pub fn init_collection(160 owner: T::AccountId,161 data: CreateCollectionData<T::AccountId>,162 ) -> Result<CollectionId, DispatchError> {160 <PalletCommon<T>>::init_collection(data)163 <PalletCommon<T>>::init_collection(owner, data)161 }164 }162 pub fn destroy_collection(165 pub fn destroy_collection(163 collection: RefungibleHandle<T>,166 collection: RefungibleHandle<T>,pallets/unique/src/lib.rsdiffbeforeafterboth35use frame_system::{self as system, ensure_signed};35use frame_system::{self as system, ensure_signed};36use sp_runtime::{sp_std::prelude::Vec};36use sp_runtime::{sp_std::prelude::Vec};37use up_data_structs::{37use up_data_structs::{38 MAX_DECIMAL_POINTS, MAX_SPONSOR_TIMEOUT, MAX_TOKEN_OWNERSHIP, CUSTOM_DATA_LIMIT,38 MAX_DECIMAL_POINTS, VARIABLE_ON_CHAIN_SCHEMA_LIMIT, CONST_ON_CHAIN_SCHEMA_LIMIT,39 VARIABLE_ON_CHAIN_SCHEMA_LIMIT, CONST_ON_CHAIN_SCHEMA_LIMIT, OFFCHAIN_SCHEMA_LIMIT,39 OFFCHAIN_SCHEMA_LIMIT, AccessMode, CreateItemData, CollectionLimits, CollectionId,40 FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,41 NFT_SPONSOR_TRANSFER_TIMEOUT, AccessMode, Collection, CreateItemData, CollectionLimits,42 CollectionId, CollectionMode, TokenId, SchemaVersion, SponsorshipState, MetaUpdatePermission,40 CollectionMode, TokenId, SchemaVersion, SponsorshipState, MetaUpdatePermission,41 CreateCollectionData,43};42};44use pallet_common::{43use pallet_common::{45 account::CrossAccountId, CollectionHandle, Pallet as PalletCommon, Error as CommonError,44 account::CrossAccountId, CollectionHandle, Pallet as PalletCommon, Error as CommonError,81 ConfirmUnsetSponsorFail,80 ConfirmUnsetSponsorFail,82 /// Length of items properties must be greater than 0.81 /// Length of items properties must be greater than 0.83 EmptyArgument,82 EmptyArgument,84 /// Collection limit bounds per collection exceeded85 CollectionLimitBoundsExceeded,86 /// Tried to enable permissions which are only permitted to be disabled87 OwnerPermissionsCantBeReverted,88 }83 }89}84}9085318 // returns collection ID313 // returns collection ID319 #[weight = <SelfWeightOf<T>>::create_collection()]314 #[weight = <SelfWeightOf<T>>::create_collection()]320 #[transactional]315 #[transactional]316 #[deprecated]321 pub fn create_collection(origin,317 pub fn create_collection(origin,322 collection_name: Vec<u16>,318 collection_name: Vec<u16>,323 collection_description: Vec<u16>,319 collection_description: Vec<u16>,324 token_prefix: Vec<u8>,320 token_prefix: Vec<u8>,325 mode: CollectionMode) -> DispatchResult {321 mode: CollectionMode) -> DispatchResult {326327 // Anyone can create a collection328 let who = ensure_signed(origin)?;322 Self::create_collection_ex(origin, CreateCollectionData {329330 // Create new collection331 let new_collection = Collection {332 owner: who,333 name: collection_name,323 name: collection_name,334 mode: mode.clone(),335 mint_mode: false,336 access: AccessMode::Normal,337 description: collection_description,324 description: collection_description,338 token_prefix,325 token_prefix,339 offchain_schema: Vec::new(),326 mode,340 schema_version: SchemaVersion::ImageURL,327 ..Default::default()341 sponsorship: SponsorshipState::Disabled,328 })342 variable_on_chain_schema: Vec::new(),329 }330331 /// This method creates a collection332 ///333 /// Prefer it to deprecated [`created_collection`] method343 const_on_chain_schema: Vec::new(),334 #[weight = <SelfWeightOf<T>>::create_collection()]335 #[transactional]344 limits: Default::default(),336 pub fn create_collection_ex(origin, data: CreateCollectionData<T::AccountId>) -> DispatchResult {345 meta_update_permission: Default::default(),337 let owner = ensure_signed(origin)?;346 };347338348 let _id = match mode {339 let _id = match data.mode {349 CollectionMode::NFT => {<PalletNonfungible<T>>::init_collection(new_collection)?},340 CollectionMode::NFT => {<PalletNonfungible<T>>::init_collection(owner, data)?},350 CollectionMode::Fungible(decimal_points) => {341 CollectionMode::Fungible(decimal_points) => {351 // check params342 // check params352 ensure!(decimal_points <= MAX_DECIMAL_POINTS, Error::<T>::CollectionDecimalPointLimitExceeded);343 ensure!(decimal_points <= MAX_DECIMAL_POINTS, Error::<T>::CollectionDecimalPointLimitExceeded);353 <PalletFungible<T>>::init_collection(new_collection)?344 <PalletFungible<T>>::init_collection(owner, data)?354 }345 }355 CollectionMode::ReFungible => {346 CollectionMode::ReFungible => {356 <PalletRefungible<T>>::init_collection(new_collection)?347 <PalletRefungible<T>>::init_collection(owner, data)?357 }348 }358 };349 };359350360 Ok(())351 Ok(())361 }352 }362353363 /// **DANGEROUS**: Destroys collection and all NFTs within this collection. Users irrecoverably lose their assets and may lose real money.354 /// **DANGEROUS**: Destroys collection and all NFTs within this collection. Users irrecoverably lose their assets and may lose real money.364 ///355 ///1099 collection_id: CollectionId,1090 collection_id: CollectionId,1100 new_limit: CollectionLimits,1091 new_limit: CollectionLimits,1101 ) -> DispatchResult {1092 ) -> DispatchResult {1102 let mut new_limit = new_limit;1103 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1093 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1104 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1094 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1105 target_collection.check_is_owner(&sender)?;1095 target_collection.check_is_owner(&sender)?;1106 let old_limit = &target_collection.limits;1096 let old_limit = &target_collection.limits;110710971108 macro_rules! limit_default {1109 ($old:ident, $new:ident, $($field:ident $(($arg:expr))? => $check:expr),* $(,)?) => {{1110 $(1111 if let Some($new) = $new.$field {1098 target_collection.limits = <PalletCommon<T>>::clamp_limits(target_collection.mode.clone(), &old_limit, new_limit)?;1112 let $old = $old.$field($($arg)?);1113 let _ = $new;1114 let _ = $old;1115 $check1116 } else {1117 $new.$field = $old.$field1118 }1119 )*1120 }};1121 }11221123 limit_default!(old_limit, new_limit,1124 account_token_ownership_limit => ensure!(1125 new_limit <= MAX_TOKEN_OWNERSHIP,1126 <Error<T>>::CollectionLimitBoundsExceeded,1127 ),1128 sponsor_transfer_timeout(match target_collection.mode {1129 CollectionMode::NFT => NFT_SPONSOR_TRANSFER_TIMEOUT,1130 CollectionMode::Fungible(_) => FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,1131 CollectionMode::ReFungible => REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,1132 }) => ensure!(1133 new_limit <= MAX_SPONSOR_TIMEOUT,1134 <Error<T>>::CollectionLimitBoundsExceeded,1135 ),1136 sponsored_data_size => ensure!(1137 new_limit <= CUSTOM_DATA_LIMIT,1138 <Error<T>>::CollectionLimitBoundsExceeded,1139 ),1140 token_limit => ensure!(1141 old_limit >= new_limit && new_limit > 0,1142 <CommonError<T>>::CollectionTokenLimitExceeded1143 ),1144 owner_can_transfer => ensure!(1145 old_limit || !new_limit,1146 <Error<T>>::OwnerPermissionsCantBeReverted,1147 ),1148 owner_can_destroy => ensure!(1149 old_limit || !new_limit,1150 <Error<T>>::OwnerPermissionsCantBeReverted,1151 ),1152 sponsored_data_rate_limit => {},1153 transfers_enabled => {},1154 );11551156 target_collection.limits = new_limit;115710991158 <Pallet<T>>::deposit_event(Event::<T>::CollectionLimitSet(1100 <Pallet<T>>::deposit_event(Event::<T>::CollectionLimitSet(1159 collection_id1101 collection_idpallets/unique/src/tests.rsdiffbeforeafterboth5use up_data_structs::{5use up_data_structs::{6 COLLECTION_NUMBER_LIMIT, CollectionId, CreateItemData, CreateFungibleData, CreateNftData,6 COLLECTION_NUMBER_LIMIT, CollectionId, CreateItemData, CreateFungibleData, CreateNftData,7 CreateReFungibleData, MAX_DECIMAL_POINTS, COLLECTION_ADMINS_LIMIT, MetaUpdatePermission,7 CreateReFungibleData, MAX_DECIMAL_POINTS, COLLECTION_ADMINS_LIMIT, MetaUpdatePermission,8 TokenId,8 TokenId, MAX_TOKEN_OWNERSHIP,9};9};10use frame_support::{assert_noop, assert_ok};10use frame_support::{assert_noop, assert_ok};11use sp_std::convert::TryInto;11use sp_std::convert::TryInto;primitives/data-structs/src/lib.rsdiffbeforeafterboth230 pub meta_update_permission: MetaUpdatePermission,230 pub meta_update_permission: MetaUpdatePermission,231}231}232233#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, Debug, Derivative)]234#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]235#[derivative(Default)]236pub struct CreateCollectionData<AccountId> {237 #[derivative(Default(value = "CollectionMode::NFT"))]238 pub mode: CollectionMode,239 pub access: Option<AccessMode>,240 pub name: Vec<u16>,241 pub description: Vec<u16>,242 pub token_prefix: Vec<u8>,243 pub offchain_schema: Vec<u8>,244 pub schema_version: Option<SchemaVersion>,245 pub pending_sponsor: Option<AccountId>,246 pub limits: Option<CollectionLimits>,247 pub variable_on_chain_schema: Vec<u8>,248 pub const_on_chain_schema: Vec<u8>,249 pub meta_update_permission: Option<MetaUpdatePermission>,250}232251233#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]252#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo)]234#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]253#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]