difftreelog
Merge pull request #10 from usetech-llc/feature/NFTPAR-96
in: master
Feature/nftpar-96
3 files changed
pallets/nft/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/nft/src/benchmarking.rs
+++ b/pallets/nft/src/benchmarking.rs
@@ -165,7 +165,7 @@
let token_prefix1: Vec<u8> = b"token_prefix1".to_vec();
let mode: CollectionMode = CollectionMode::NFT;
let caller: T::AccountId = T::AccountId::from(whitelisted_caller());
- let nft_data = CreateNftData {
+ let mut nft_data = CreateNftData {
const_data: vec![],
variable_data: vec![]
};
@@ -173,7 +173,7 @@
nft_data.const_data.push(10);
nft_data.variable_data.push(10);
}
- let mut data = CreateItemData::NFT(nft_data);
+ let data = CreateItemData::NFT(nft_data);
Nft::<T>::create_collection(RawOrigin::Signed(caller.clone()).into(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), mode.clone())?;
}: 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.rsdiffbeforeafterboth--- a/pallets/nft/src/tests.rs
+++ b/pallets/nft/src/tests.rs
@@ -87,6 +87,32 @@
});
}
+// Use cases tests region
+// #region
+#[test]
+fn create_nft_multiple_items() {
+ new_test_ext().execute_with(|| {
+ default_limits();
+
+ create_test_collection(&CollectionMode::NFT, 1);
+
+ let origin1 = Origin::signed(1);
+
+ let items_data = vec![default_nft_data(), default_nft_data(), default_nft_data()];
+
+ assert_ok!(TemplateModule::create_multiple_items(
+ origin1.clone(),
+ 1,
+ 1,
+ items_data.clone().into_iter().map(|d| { d.into() }).collect()
+ ));
+ for (index, data) in items_data.iter().enumerate() {
+ assert_eq!(TemplateModule::nft_item_id(1, (index + 1) as u64).const_data.to_vec(), data.const_data);
+ assert_eq!(TemplateModule::nft_item_id(1, (index + 1) as u64).variable_data.to_vec(), data.variable_data);
+ }
+ });
+}
+
#[test]
fn create_refungible_item() {
new_test_ext().execute_with(|| {
@@ -114,6 +140,39 @@
}
#[test]
+fn create_multiple_refungible_items() {
+ new_test_ext().execute_with(|| {
+ default_limits();
+
+ create_test_collection(&CollectionMode::ReFungible(3), 1);
+
+ let origin1 = Origin::signed(1);
+
+ let items_data = vec![default_re_fungible_data(), default_re_fungible_data(), default_re_fungible_data()];
+
+ assert_ok!(TemplateModule::create_multiple_items(
+ origin1.clone(),
+ 1,
+ 1,
+ items_data.clone().into_iter().map(|d| { d.into() }).collect()
+ ));
+ for (index, data) in items_data.iter().enumerate() {
+
+ let item = TemplateModule::refungible_item_id(1, (index + 1) as u64);
+ assert_eq!(item.const_data.to_vec(), data.const_data);
+ assert_eq!(item.variable_data.to_vec(), data.variable_data);
+ assert_eq!(
+ item.owner[0],
+ Ownership {
+ owner: 1,
+ fraction: 1000
+ }
+ );
+ }
+ });
+}
+
+#[test]
fn create_fungible_item() {
new_test_ext().execute_with(|| {
default_limits();
@@ -124,12 +183,36 @@
create_test_item(collection_id, &data.into());
assert_eq!(TemplateModule::fungible_item_id(collection_id, 1).owner, 1);
- assert_eq!(TemplateModule::balance_count(1, 1), 1000);
- assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
});
}
#[test]
+fn create_multiple_fungible_items() {
+ new_test_ext().execute_with(|| {
+ default_limits();
+
+ create_test_collection(&CollectionMode::Fungible(3), 1);
+
+ let origin1 = Origin::signed(1);
+
+ let items_data = vec![default_fungible_data(), default_fungible_data(), default_fungible_data()];
+
+ assert_ok!(TemplateModule::create_multiple_items(
+ origin1.clone(),
+ 1,
+ 1,
+ items_data.clone().into_iter().map(|d| { d.into() }).collect()
+ ));
+
+ for (index, _) in items_data.iter().enumerate() {
+ assert_eq!(TemplateModule::fungible_item_id(1, (index + 1) as u64).owner, 1);
+ }
+ assert_eq!(TemplateModule::balance_count(1, 1), 3000);
+ assert_eq!(TemplateModule::address_tokens(1, 1), [1, 2, 3]);
+ });
+}
+
+#[test]
fn transfer_fungible_item() {
new_test_ext().execute_with(|| {
default_limits();
@@ -1333,7 +1416,7 @@
assert_noop!(
TemplateModule::create_item(origin2.clone(), 1, 2, default_nft_data().into()),
- "Public minting is not allowed for this collection."
+ "Public minting is not allowed for this collection"
);
});
}
@@ -1362,7 +1445,7 @@
assert_noop!(
TemplateModule::create_item(origin2.clone(), 1, 2, default_nft_data().into()),
- "Public minting is not allowed for this collection."
+ "Public minting is not allowed for this collection"
);
});
}