difftreelog
Merge pull request #10 from usetech-llc/feature/NFTPAR-96
in: master
Feature/nftpar-96
3 files changed
pallets/nft/src/benchmarking.rsdiffbeforeafterboth165 let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();165 let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();166 let mode: CollectionMode = CollectionMode::NFT;166 let mode: CollectionMode = CollectionMode::NFT;167 let caller: T::AccountId = T::AccountId::from(whitelisted_caller());167 let caller: T::AccountId = T::AccountId::from(whitelisted_caller());168 let nft_data = CreateNftData {168 let mut nft_data = CreateNftData {169 const_data: vec![],169 const_data: vec![],170 variable_data: vec![]170 variable_data: vec![]171 };171 };172 for i in 0..1998 {172 for i in 0..1998 {173 nft_data.const_data.push(10);173 nft_data.const_data.push(10);174 nft_data.variable_data.push(10);174 nft_data.variable_data.push(10);175 }175 }176 let mut data = CreateItemData::NFT(nft_data);176 let data = CreateItemData::NFT(nft_data);177 Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;177 Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;178178179 }: create_item(RawOrigin::Signed(caller.clone()), 2, caller.clone(), data)179 }: create_item(RawOrigin::Signed(caller.clone()), 2, caller.clone(), data)pallets/nft/src/lib.rsdiffbeforeafterboth10pub use frame_support::{10pub use frame_support::{11 construct_runtime, decl_event, decl_module, decl_storage,11 construct_runtime, decl_event, decl_module, decl_storage,12 dispatch::DispatchResult,12 dispatch::DispatchResult,13 ensure, parameter_types, fail,13 ensure, fail, parameter_types,14 traits::{14 traits::{15 Currency, ExistenceRequirement, Get, Imbalance, KeyOwnerProofSystem, OnUnbalanced,15 Currency, ExistenceRequirement, Get, Imbalance, KeyOwnerProofSystem, OnUnbalanced,16 Randomness, WithdrawReason,16 Randomness, WithdrawReason,22 },22 },23 IsSubType, StorageValue,23 IsSubType, StorageValue,24};24};25// use frame_support::weights::{Weight, constants::RocksDbWeight as DbWeight};262527use frame_system::{self as system, ensure_signed, ensure_root};26use frame_system::{self as system, ensure_signed, ensure_root};28use sp_runtime::sp_std::prelude::Vec;27use sp_runtime::sp_std::prelude::Vec;489 }488 }490489491 /// **DANGEROUS**: Destroys collection and all NFTs within this collection. Users irrecoverably lose their assets and may lose real money.490 /// **DANGEROUS**: Destroys collection and all NFTs within this collection. Users irrecoverably lose their assets and may lose real money.492 /// 491 /// 493 /// # Permissions492 /// # Permissions494 /// 493 /// 495 /// * Collection Owner.494 /// * Collection Owner.829 // .saturating_add(RocksDbWeight::get().writes(8 as Weight))]828 // .saturating_add(RocksDbWeight::get().writes(8 as Weight))]830829831 #[weight = T::WeightInfo::create_item(data.len())]830 #[weight = T::WeightInfo::create_item(data.len())]832 pub fn create_item(origin, collection_id: u64, owner: T::AccountId, data: CreateItemData) -> DispatchResult {831 pub fn create_item(origin, collection_id: u64, owner: T::AccountId, data: CreateItemData) -> DispatchResult {833832834 let sender = ensure_signed(origin)?;833 let sender = ensure_signed(origin)?;834835 Self::collection_exists(collection_id)?;835 Self::collection_exists(collection_id)?;836836 let target_collection = <Collection<T>>::get(collection_id);837 let target_collection = <Collection<T>>::get(collection_id);837838838 if !Self::is_owner_or_admin_permissions(collection_id, sender.clone()) {839 Self::can_create_items_in_collection(collection_id, &target_collection, &sender, &owner)?;839 ensure!(target_collection.mint_mode == true, "Public minting is not allowed for this collection.");840 Self::check_white_list(collection_id, &owner)?;840 Self::validate_create_item_args(&target_collection, &data)?;841 Self::check_white_list(collection_id, &sender)?;841 Self::create_item_no_validation(collection_id, &target_collection, owner, data)?;842 }842843843 Ok(())844 match target_collection.mode844 }845 {845846 /// This method creates multiple instances of NFT Collection created with CreateCollection method.847 /// 848 /// # Permissions849 /// 850 /// * Collection Owner.851 /// * Collection Admin.852 /// * Anyone if853 /// * White List is enabled, and854 /// * Address is added to white list, and855 /// * MintPermission is enabled (see SetMintPermission method)856 /// 857 /// # Arguments858 /// 859 /// * collection_id: ID of the collection.860 /// 861 /// * itemsData: Array items properties. Each property is an array of bytes itself, see [create_item].862 /// 863 /// * owner: Address, initial owner of the NFT.846 CollectionMode::NFT => {864 #[weight = T::WeightInfo::create_item(items_data.into_iter()847 if let CreateItemData::NFT(data) = data {865 .map(|data| { data.len() })848 // check sizes849 ensure!(ChainLimit::get().custom_data_limit >= data.const_data.len() as u32, "const_data exceeded data limit.");850 ensure!(ChainLimit::get().custom_data_limit >= data.variable_data.len() as u32, "variable_data exceeded data limit.");866 .sum())]851 852 // Create nft item853 let item = NftItemType {854 collection: collection_id,867 pub fn create_multiple_items(origin, collection_id: u64, owner: T::AccountId, items_data: Vec<CreateItemData>) -> DispatchResult {855 owner: owner,868856 const_data: data.const_data.clone(),869 ensure!(items_data.len() > 0, "Length of items properties must be greater than 0.");857 variable_data: data.variable_data.clone() 858 };859 860 Self::add_nft_item(item)?;861 862 } else {863 fail!("Not NFT item data used to mint in NFT collection.");864 }865 },866 CollectionMode::Fungible(_) => {867 if let CreateItemData::Fungible(_) = data {870 let sender = ensure_signed(origin)?;868 871869 let item = FungibleItemType {870 collection: collection_id,871 owner: owner,872 value: (10 as u128).pow(target_collection.decimal_points)873 };874 875 Self::add_fungible_item(item)?;872 Self::collection_exists(collection_id)?;876 } else {877 fail!("Not Fungible item data used to mint in Fungible collection.");878 }879 },880 CollectionMode::ReFungible(_) => {881 if let CreateItemData::ReFungible(data) = data {873 let target_collection = <Collection<T>>::get(collection_id);882 874883 // check sizes884 ensure!(ChainLimit::get().custom_data_limit >= data.const_data.len() as u32, "const_data exceeded data limit.");885 ensure!(ChainLimit::get().custom_data_limit >= data.variable_data.len() as u32, "variable_data exceeded data limit.");875 Self::can_create_items_in_collection(collection_id, &target_collection, &sender, &owner)?;886 876877 for data in &items_data {887 let mut owner_list = Vec::new();878 Self::validate_create_item_args(&target_collection, data)?;888 let value = (10 as u128).pow(target_collection.decimal_points);879 }889 owner_list.push(Ownership {owner: owner.clone(), fraction: value});880 for data in &items_data {890 891 let item = ReFungibleItemType {892 collection: collection_id,881 Self::create_item_no_validation(collection_id, &target_collection, owner.clone(), data.clone())?;893 owner: owner_list,882 }894 const_data: data.const_data.clone(),895 variable_data: data.variable_data.clone() 896 };897 898 Self::add_refungible_item(item)?;899 } else {900 fail!("Not Re Fungible item data used to mint in Re Fungible collection.");901 }902 },903 _ => { ensure!(1 == 0,"Unexpected collection type."); }904 };905906 // call event907 Self::deposit_event(RawEvent::ItemCreated(collection_id, <ItemListIndex>::get(collection_id)));908883909 Ok(())884 Ok(())910 }885 }911886912 /// Destroys a concrete instance of NFT.887 /// Destroys a concrete instance of NFT.913 /// 888 /// 130612811307impl<T: Trait> Module<T> {1282impl<T: Trait> Module<T> {12831284 fn can_create_items_in_collection(collection_id: u64, collection: &CollectionType<T::AccountId>, sender: &T::AccountId, owner: &T::AccountId) -> DispatchResult {12851286 if !Self::is_owner_or_admin_permissions(collection_id, sender.clone()) {1287 ensure!(collection.mint_mode == true, "Public minting is not allowed for this collection");1288 Self::check_white_list(collection_id, owner)?;1289 Self::check_white_list(collection_id, sender)?;1290 }12911292 Ok(())1293 }12941295 fn validate_create_item_args(target_collection: &CollectionType<T::AccountId>, data: &CreateItemData) -> DispatchResult {1296 match target_collection.mode1297 {1298 CollectionMode::NFT => {1299 if let CreateItemData::NFT(data) = data {1300 // check sizes1301 ensure!(ChainLimit::get().custom_data_limit >= data.const_data.len() as u32, "const_data exceeded data limit.");1302 ensure!(ChainLimit::get().custom_data_limit >= data.variable_data.len() as u32, "variable_data exceeded data limit.");1303 } else {1304 fail!("Not NFT item data used to mint in NFT collection.");1305 }1306 },1307 CollectionMode::Fungible(_) => {1308 if let CreateItemData::Fungible(_) = data {1309 } else {1310 fail!("Not Fungible item data used to mint in Fungible collection.");1311 }1312 },1313 CollectionMode::ReFungible(_) => {1314 if let CreateItemData::ReFungible(data) = data {13151316 // check sizes1317 ensure!(ChainLimit::get().custom_data_limit >= data.const_data.len() as u32, "const_data exceeded data limit.");1318 ensure!(ChainLimit::get().custom_data_limit >= data.variable_data.len() as u32, "variable_data exceeded data limit.");1319 } else {1320 fail!("Not Re Fungible item data used to mint in Re Fungible collection.");1321 }1322 },1323 _ => { fail!("Unexpected collection type."); }1324 };13251326 Ok(())1327 }13281329 fn create_item_no_validation(collection_id: u64, collection: &CollectionType<T::AccountId>, owner: T::AccountId, data: CreateItemData) -> DispatchResult {1330 match data1331 {1332 CreateItemData::NFT(data) => {1333 let item = NftItemType {1334 collection: collection_id,1335 owner,1336 const_data: data.const_data,1337 variable_data: data.variable_data1338 };13391340 Self::add_nft_item(item)?;1341 },1342 CreateItemData::Fungible(_) => {1343 let item = FungibleItemType {1344 collection: collection_id,1345 owner,1346 value: (10 as u128).pow(collection.decimal_points)1347 };13481349 Self::add_fungible_item(item)?;1350 },1351 CreateItemData::ReFungible(data) => {1352 let mut owner_list = Vec::new();1353 let value = (10 as u128).pow(collection.decimal_points);1354 owner_list.push(Ownership {owner: owner.clone(), fraction: value});13551356 let item = ReFungibleItemType {1357 collection: collection_id,1358 owner: owner_list,1359 const_data: data.const_data,1360 variable_data: data.variable_data1361 };13621363 Self::add_refungible_item(item)?;1364 }1365 };136613671368 // call event1369 Self::deposit_event(RawEvent::ItemCreated(collection_id, <ItemListIndex>::get(collection_id)));13701371 Ok(())1372 }13731308 fn add_fungible_item(item: FungibleItemType<T::AccountId>) -> DispatchResult {1374 fn add_fungible_item(item: FungibleItemType<T::AccountId>) -> DispatchResult {1309 let current_index = <ItemListIndex>::get(item.collection)1375 let current_index = <ItemListIndex>::get(item.collection)pallets/nft/src/tests.rsdiffbeforeafterboth87 });87 });88}88}8990// Use cases tests region91// #region92#[test]93fn create_nft_multiple_items() {94 new_test_ext().execute_with(|| {95 default_limits();96 97 create_test_collection(&CollectionMode::NFT, 1);9899 let origin1 = Origin::signed(1);100101 let items_data = vec![default_nft_data(), default_nft_data(), default_nft_data()];102103 assert_ok!(TemplateModule::create_multiple_items(104 origin1.clone(),105 1,106 1,107 items_data.clone().into_iter().map(|d| { d.into() }).collect()108 ));109 for (index, data) in items_data.iter().enumerate() {110 assert_eq!(TemplateModule::nft_item_id(1, (index + 1) as u64).const_data.to_vec(), data.const_data);111 assert_eq!(TemplateModule::nft_item_id(1, (index + 1) as u64).variable_data.to_vec(), data.variable_data);112 }113 });114}8911590#[test]116#[test]91fn create_refungible_item() {117fn create_refungible_item() {114}140}115141116#[test]142#[test]117fn create_fungible_item() {143fn create_multiple_refungible_items() {144 new_test_ext().execute_with(|| {145 default_limits();146 147 create_test_collection(&CollectionMode::ReFungible(3), 1);148149 let origin1 = Origin::signed(1);150151 let items_data = vec![default_re_fungible_data(), default_re_fungible_data(), default_re_fungible_data()];152153 assert_ok!(TemplateModule::create_multiple_items(154 origin1.clone(),155 1,156 1,157 items_data.clone().into_iter().map(|d| { d.into() }).collect()158 ));159 for (index, data) in items_data.iter().enumerate() {160161 let item = TemplateModule::refungible_item_id(1, (index + 1) as u64);162 assert_eq!(item.const_data.to_vec(), data.const_data);163 assert_eq!(item.variable_data.to_vec(), data.variable_data);164 assert_eq!(165 item.owner[0],166 Ownership {167 owner: 1,168 fraction: 1000169 }170 );171 }172 });173}174175#[test]176fn create_fungible_item() {177 new_test_ext().execute_with(|| {178 default_limits();179 180 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);181182 let data = default_fungible_data();183 create_test_item(collection_id, &data.into());184185 assert_eq!(TemplateModule::fungible_item_id(collection_id, 1).owner, 1);186 });187}188189#[test]190fn create_multiple_fungible_items() {118 new_test_ext().execute_with(|| {191 new_test_ext().execute_with(|| {119 default_limits();192 default_limits();120 193121 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);194 create_test_collection(&CollectionMode::Fungible(3), 1);195196 let origin1 = Origin::signed(1);122197123 let data = default_fungible_data();198 let items_data = vec![default_fungible_data(), default_fungible_data(), default_fungible_data()];199124 create_test_item(collection_id, &data.into());200 assert_ok!(TemplateModule::create_multiple_items(125201 origin1.clone(),202 1,203 1,204 items_data.clone().into_iter().map(|d| { d.into() }).collect()205 ));206 207 for (index, _) in items_data.iter().enumerate() {126 assert_eq!(TemplateModule::fungible_item_id(collection_id, 1).owner, 1);208 assert_eq!(TemplateModule::fungible_item_id(1, (index + 1) as u64).owner, 1);209 }127 assert_eq!(TemplateModule::balance_count(1, 1), 1000);210 assert_eq!(TemplateModule::balance_count(1, 1), 3000);128 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);211 assert_eq!(TemplateModule::address_tokens(1, 1), [1, 2, 3]);129 });212 });130}213}131214133314161334 assert_noop!(1417 assert_noop!(1335 TemplateModule::create_item(origin2.clone(), 1, 2, default_nft_data().into()),1418 TemplateModule::create_item(origin2.clone(), 1, 2, default_nft_data().into()),1336 "Public minting is not allowed for this collection."1419 "Public minting is not allowed for this collection"1337 );1420 );1338 });1421 });1339}1422}136214451363 assert_noop!(1446 assert_noop!(1364 TemplateModule::create_item(origin2.clone(), 1, 2, default_nft_data().into()),1447 TemplateModule::create_item(origin2.clone(), 1, 2, default_nft_data().into()),1365 "Public minting is not allowed for this collection."1448 "Public minting is not allowed for this collection"1366 );1449 );1367 });1450 });1368}1451}