difftreelog
NFTPAR-96: Batch Minting.
in: master
2 files changed
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,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,744 /// 744 /// 745 /// * owner: Address, initial owner of the NFT.745 /// * owner: Address, initial owner of the NFT.746 #[weight = 0]746 #[weight = 0]747 pub fn create_item(origin, collection_id: u64, properties: Vec<u8>, owner: T::AccountId) -> DispatchResult {747 pub fn create_item(origin, collection_id: u64, properties: Vec<u8>, owner: T::AccountId) -> DispatchResult {748748749 let sender = ensure_signed(origin)?;749 let sender = ensure_signed(origin)?;750750 Self::collection_exists(collection_id)?;751 Self::collection_exists(collection_id)?;752751 let target_collection = <Collection<T>>::get(collection_id);753 let target_collection = <Collection<T>>::get(collection_id);752754753 if !Self::is_owner_or_admin_permissions(collection_id, sender.clone()) {755 Self::can_create_items_in_collection(collection_id, &target_collection, &sender, &owner)?;754 ensure!(target_collection.mint_mode == true, "Public minting is not allowed for this collection");755 Self::check_white_list(collection_id, &owner)?;756 Self::validate_create_item_args(&target_collection, &properties)?;756 Self::check_white_list(collection_id, &sender)?;757 Self::create_item_no_validation(collection_id, &target_collection, &properties, &owner)?;757 }758758759 match target_collection.mode760 {761 CollectionMode::NFT(_) => {762763 // check size764 ensure!(target_collection.custom_data_size >= properties.len() as u32, "Size of item is too large");759 Ok(())765760 }766 // Create nft item761762 /// This method creates multiple instances of NFT Collection created with CreateCollection method.763 /// 764 /// # Permissions765 /// 766 /// * Collection Owner.767 /// * Collection Admin.768 /// * Anyone if769 /// * White List is enabled, and770 /// * Address is added to white list, and771 /// * MintPermission is enabled (see SetMintPermission method)772 /// 773 /// # Arguments774 /// 775 /// * collection_id: ID of the collection.776 /// 777 /// * properties: Array items properties. Each property is an array of bytes itself, see [create_item].778 /// 779 /// * owner: Address, initial owner of the NFT.767 let item = NftItemType {780 #[weight = 0]768 collection: collection_id,781 pub fn create_multiple_items(origin, collection_id: u64, properties: Vec<Vec<u8>>, owner: T::AccountId) -> DispatchResult {769 owner: owner,782770 data: properties.clone(),771 };772773 Self::add_nft_item(item)?;774775 },776 CollectionMode::Fungible(_) => {777778 // check size779 ensure!(properties.len() as u32 == 0, "Size of item must be 0 with fungible type");783 ensure!(properties.len() > 0, "Length of items properties must be greater than 0.");780781 let item = FungibleItemType {784 let sender = ensure_signed(origin)?;782 collection: collection_id,783 owner: owner,784 value: (10 as u128).pow(target_collection.decimal_points)785 };786785787 Self::add_fungible_item(item)?;786 Self::collection_exists(collection_id)?;788 },789 CollectionMode::ReFungible(_, _) => {790791 // check size792 ensure!(target_collection.custom_data_size >= properties.len() as u32, "Size of item is too large");793794 let mut owner_list = Vec::new();787 let target_collection = <Collection<T>>::get(collection_id);788795 let value = (10 as u128).pow(target_collection.decimal_points);789 Self::can_create_items_in_collection(collection_id, &target_collection, &sender, &owner)?;796 owner_list.push(Ownership {owner: owner.clone(), fraction: value});790797798 let item = ReFungibleItemType {799 collection: collection_id,800 owner: owner_list,801 data: properties.clone()791 for prop in &properties {802 };803804 Self::add_refungible_item(item)?;792 Self::validate_create_item_args(&target_collection, prop)?;805 },793 }806 _ => { ensure!(1 == 0,"just error"); }794 for prop in &properties {807808 };809810 // call event811 Self::deposit_event(RawEvent::ItemCreated(collection_id, <ItemListIndex>::get(collection_id)));795 Self::create_item_no_validation(collection_id, &target_collection, prop, &owner)?;796 }812797813 Ok(())798 Ok(())814 }799 }815800816 /// Destroys a concrete instance of NFT.801 /// Destroys a concrete instance of NFT.817 /// 802 /// 107910641080impl<T: Trait> Module<T> {1065impl<T: Trait> Module<T> {10661067 fn can_create_items_in_collection(collection_id: u64, collection: &CollectionType<T::AccountId>, sender: &T::AccountId, owner: &T::AccountId) -> DispatchResult {10681069 if !Self::is_owner_or_admin_permissions(collection_id, sender.clone()) {1070 ensure!(collection.mint_mode == true, "Public minting is not allowed for this collection");1071 Self::check_white_list(collection_id, owner)?;1072 Self::check_white_list(collection_id, sender)?;1073 }10741075 Ok(())1076 }10771078 fn validate_create_item_args(collection: &CollectionType<T::AccountId>, properties: &Vec<u8>) -> DispatchResult {10791080 match collection.mode1081 {1082 CollectionMode::NFT(_) => {10831084 // check size1085 ensure!(collection.custom_data_size >= properties.len() as u32, "Size of item is too large")1086 },1087 CollectionMode::Fungible(_) => {10881089 // check size1090 ensure!(properties.len() as u32 == 0, "Size of item must be 0 with fungible type")1091 },1092 CollectionMode::ReFungible(_, _) => {10931094 // check size1095 ensure!(collection.custom_data_size >= properties.len() as u32, "Size of item is too large")1096 },1097 _ => {1098 fail!("Unexpected collection mode")1099 }1100 }11011102 Ok(())1103 }11041105 fn create_item_no_validation(collection_id: u64, collection: &CollectionType<T::AccountId>, properties: &Vec<u8>, owner: &T::AccountId) -> DispatchResult {1106 match collection.mode1107 {1108 CollectionMode::NFT(_) => {11091110 // Create nft item1111 let item = NftItemType {1112 collection: collection_id,1113 owner: owner.clone(),1114 data: properties.clone(),1115 };11161117 Self::add_nft_item(item)?;11181119 },1120 CollectionMode::Fungible(_) => {11211122 let item = FungibleItemType {1123 collection: collection_id,1124 owner: owner.clone(),1125 value: (10 as u128).pow(collection.decimal_points)1126 };11271128 Self::add_fungible_item(item)?;1129 },1130 CollectionMode::ReFungible(_, _) => {11311132 let mut owner_list = Vec::new();1133 let value = (10 as u128).pow(collection.decimal_points);1134 owner_list.push(Ownership {owner: owner.clone(), fraction: value});11351136 let item = ReFungibleItemType {1137 collection: collection_id,1138 owner: owner_list,1139 data: properties.clone()1140 };11411142 Self::add_refungible_item(item)?;1143 },1144 _ => { ensure!(1 == 0,"just error"); }11451146 };11471148 // call event1149 Self::deposit_event(RawEvent::ItemCreated(collection_id, <ItemListIndex>::get(collection_id)));11501151 Ok(())1152 }11531081 fn add_fungible_item(item: FungibleItemType<T::AccountId>) -> DispatchResult {1154 fn add_fungible_item(item: FungibleItemType<T::AccountId>) -> DispatchResult {1082 let current_index = <ItemListIndex>::get(item.collection)1155 let current_index = <ItemListIndex>::get(item.collection)pallets/nft/src/tests.rsdiffbeforeafterboth--- a/pallets/nft/src/tests.rs
+++ b/pallets/nft/src/tests.rs
@@ -44,7 +44,51 @@
});
}
+// Use cases tests region
+// #region
#[test]
+fn create_nft_multiple_items() {
+ new_test_ext().execute_with(|| {
+ let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
+ let mode: CollectionMode = CollectionMode::NFT(2000);
+
+ assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits {
+ collection_numbers_limit: 10,
+ account_token_ownership_limit: 10,
+ collections_admins_limit: 5,
+ custom_data_limit: 2048,
+ nft_sponsor_transfer_timeout: 15,
+ fungible_sponsor_transfer_timeout: 15,
+ refungible_sponsor_transfer_timeout: 15,
+ }));
+
+ let origin1 = Origin::signed(1);
+ assert_ok!(TemplateModule::create_collection(
+ origin1.clone(),
+ col_name1.clone(),
+ col_desc1.clone(),
+ token_prefix1.clone(),
+ mode
+ ));
+ assert_eq!(TemplateModule::collection(1).owner, 1);
+
+ let properties = [[1, 2, 3].to_vec(), [3, 2, 1].to_vec(), [3, 3, 3].to_vec()].to_vec();
+
+ assert_ok!(TemplateModule::create_multiple_items(
+ origin1.clone(),
+ 1,
+ properties.clone(),
+ 1
+ ));
+ for (index, data) in properties.iter().enumerate() {
+ assert_eq!(TemplateModule::nft_item_id(1, (index + 1) as u64).data, *data);
+ }
+ });
+}
+
+#[test]
fn create_refungible_item() {
new_test_ext().execute_with(|| {
let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
@@ -93,6 +137,57 @@
}
#[test]
+fn create_multiple_refungible_items() {
+ new_test_ext().execute_with(|| {
+ let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
+ let mode: CollectionMode = CollectionMode::ReFungible(2000, 3);
+
+ assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits {
+ collection_numbers_limit: 10,
+ account_token_ownership_limit: 10,
+ collections_admins_limit: 5,
+ custom_data_limit: 2048,
+ nft_sponsor_transfer_timeout: 15,
+ fungible_sponsor_transfer_timeout: 15,
+ refungible_sponsor_transfer_timeout: 15,
+ }));
+
+ let origin1 = Origin::signed(1);
+ assert_ok!(TemplateModule::create_collection(
+ origin1.clone(),
+ col_name1.clone(),
+ col_desc1.clone(),
+ token_prefix1.clone(),
+ mode
+ ));
+ assert_eq!(TemplateModule::collection(1).owner, 1);
+
+ let properties = [[1, 2, 3].to_vec(), [3, 2, 1].to_vec(), [3, 3, 3].to_vec()].to_vec();
+
+ assert_ok!(TemplateModule::create_multiple_items(
+ origin1.clone(),
+ 1,
+ properties.clone(),
+ 1
+ ));
+ for (index, data) in properties.iter().enumerate() {
+
+ let item = TemplateModule::refungible_item_id(1, (index + 1) as u64);
+ assert_eq!(item.data, *data);
+ assert_eq!(
+ item.owner[0],
+ Ownership {
+ owner: 1,
+ fraction: 1000
+ }
+ );
+ }
+ });
+}
+
+#[test]
fn create_fungible_item() {
new_test_ext().execute_with(|| {
let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
@@ -127,12 +222,55 @@
1
));
assert_eq!(TemplateModule::fungible_item_id(1, 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(|| {
+ let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
+ let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
+ let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
+ let mode: CollectionMode = CollectionMode::Fungible(3);
+
+ assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits {
+ collection_numbers_limit: 10,
+ account_token_ownership_limit: 10,
+ collections_admins_limit: 5,
+ custom_data_limit: 2048,
+ nft_sponsor_transfer_timeout: 15,
+ fungible_sponsor_transfer_timeout: 15,
+ refungible_sponsor_transfer_timeout: 15,
+ }));
+
+ let origin1 = Origin::signed(1);
+ assert_ok!(TemplateModule::create_collection(
+ origin1.clone(),
+ col_name1.clone(),
+ col_desc1.clone(),
+ token_prefix1.clone(),
+ mode
+ ));
+ assert_eq!(TemplateModule::collection(1).owner, 1);
+
+ let properties = [[].to_vec(), [].to_vec(), [].to_vec()].to_vec();
+
+ assert_ok!(TemplateModule::create_multiple_items(
+ origin1.clone(),
+ 1,
+ properties.clone(),
+ 1
+ ));
+
+ for (index, _) in properties.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(|| {
let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();