git.delta.rocks / unique-network / refs/commits / 73335ba4b181

difftreelog

Merge pull request #10 from usetech-llc/feature/NFTPAR-96

Greg Zaitsev2020-11-26parents: #38074f1 #5f15b48.patch.diff
in: master
Feature/nftpar-96

3 files changed

modifiedpallets/nft/src/benchmarking.rsdiffbeforeafterboth
165 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())?;
178178
179 }: create_item(RawOrigin::Signed(caller.clone()), 2, caller.clone(), data)179 }: create_item(RawOrigin::Signed(caller.clone()), 2, caller.clone(), data)
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
10pub 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};
2625
27use 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 }
490489
491 /// **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 /// # Permissions
494 /// 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))]
830829
831 #[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 {
833832
834 let sender = ensure_signed(origin)?;833 let sender = ensure_signed(origin)?;
834
835 Self::collection_exists(collection_id)?;835 Self::collection_exists(collection_id)?;
836
836 let target_collection = <Collection<T>>::get(collection_id);837 let target_collection = <Collection<T>>::get(collection_id);
837838
838 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 }842
843843 Ok(())
844 match target_collection.mode844 }
845 {845
846 /// This method creates multiple instances of NFT Collection created with CreateCollection method.
847 ///
848 /// # Permissions
849 ///
850 /// * Collection Owner.
851 /// * Collection Admin.
852 /// * Anyone if
853 /// * White List is enabled, and
854 /// * Address is added to white list, and
855 /// * MintPermission is enabled (see SetMintPermission method)
856 ///
857 /// # Arguments
858 ///
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 sizes
849 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 item
853 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,868
856 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 871
869 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 874
883 // check sizes
884 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 876
877 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 };
905
906 // call event
907 Self::deposit_event(RawEvent::ItemCreated(collection_id, <ItemListIndex>::get(collection_id)));
908883
909 Ok(())884 Ok(())
910 }885 }
911886
912 /// Destroys a concrete instance of NFT.887 /// Destroys a concrete instance of NFT.
913 /// 888 ///
13061281
1307impl<T: Trait> Module<T> {1282impl<T: Trait> Module<T> {
1283
1284 fn can_create_items_in_collection(collection_id: u64, collection: &CollectionType<T::AccountId>, sender: &T::AccountId, owner: &T::AccountId) -> DispatchResult {
1285
1286 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 }
1291
1292 Ok(())
1293 }
1294
1295 fn validate_create_item_args(target_collection: &CollectionType<T::AccountId>, data: &CreateItemData) -> DispatchResult {
1296 match target_collection.mode
1297 {
1298 CollectionMode::NFT => {
1299 if let CreateItemData::NFT(data) = data {
1300 // check sizes
1301 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 {
1315
1316 // check sizes
1317 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 };
1325
1326 Ok(())
1327 }
1328
1329 fn create_item_no_validation(collection_id: u64, collection: &CollectionType<T::AccountId>, owner: T::AccountId, data: CreateItemData) -> DispatchResult {
1330 match data
1331 {
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_data
1338 };
1339
1340 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 };
1348
1349 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});
1355
1356 let item = ReFungibleItemType {
1357 collection: collection_id,
1358 owner: owner_list,
1359 const_data: data.const_data,
1360 variable_data: data.variable_data
1361 };
1362
1363 Self::add_refungible_item(item)?;
1364 }
1365 };
1366
1367
1368 // call event
1369 Self::deposit_event(RawEvent::ItemCreated(collection_id, <ItemListIndex>::get(collection_id)));
1370
1371 Ok(())
1372 }
1373
1308 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)
modifiedpallets/nft/src/tests.rsdiffbeforeafterboth
87 });87 });
88}88}
89
90// Use cases tests region
91// #region
92#[test]
93fn create_nft_multiple_items() {
94 new_test_ext().execute_with(|| {
95 default_limits();
96
97 create_test_collection(&CollectionMode::NFT, 1);
98
99 let origin1 = Origin::signed(1);
100
101 let items_data = vec![default_nft_data(), default_nft_data(), default_nft_data()];
102
103 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}
89115
90#[test]116#[test]
91fn create_refungible_item() {117fn create_refungible_item() {
114}140}
115141
116#[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);
148
149 let origin1 = Origin::signed(1);
150
151 let items_data = vec![default_re_fungible_data(), default_re_fungible_data(), default_re_fungible_data()];
152
153 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() {
160
161 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: 1000
169 }
170 );
171 }
172 });
173}
174
175#[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);
181
182 let data = default_fungible_data();
183 create_test_item(collection_id, &data.into());
184
185 assert_eq!(TemplateModule::fungible_item_id(collection_id, 1).owner, 1);
186 });
187}
188
189#[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 193
121 let collection_id = create_test_collection(&CollectionMode::Fungible(3), 1);194 create_test_collection(&CollectionMode::Fungible(3), 1);
195
196 let origin1 = Origin::signed(1);
122197
123 let data = default_fungible_data();198 let items_data = vec![default_fungible_data(), default_fungible_data(), default_fungible_data()];
199
124 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}
131214
13331416
1334 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}
13621445
1363 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}