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.rsdiffbeforeafterboth44 });44 });45}45}4647// Use cases tests region48// #region49#[test]50fn create_nft_multiple_items() {51 new_test_ext().execute_with(|| {52 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();53 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();54 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();55 let mode: CollectionMode = CollectionMode::NFT(2000);5657 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 58 collection_numbers_limit: 10,59 account_token_ownership_limit: 10,60 collections_admins_limit: 5,61 custom_data_limit: 2048,62 nft_sponsor_transfer_timeout: 15,63 fungible_sponsor_transfer_timeout: 15,64 refungible_sponsor_transfer_timeout: 15, 65 }));6667 let origin1 = Origin::signed(1);68 assert_ok!(TemplateModule::create_collection(69 origin1.clone(),70 col_name1.clone(),71 col_desc1.clone(),72 token_prefix1.clone(),73 mode74 ));75 assert_eq!(TemplateModule::collection(1).owner, 1);7677 let properties = [[1, 2, 3].to_vec(), [3, 2, 1].to_vec(), [3, 3, 3].to_vec()].to_vec();7879 assert_ok!(TemplateModule::create_multiple_items(80 origin1.clone(),81 1,82 properties.clone(),83 184 ));85 for (index, data) in properties.iter().enumerate() {86 assert_eq!(TemplateModule::nft_item_id(1, (index + 1) as u64).data, *data);87 }88 });89}469047#[test]91#[test]48fn create_refungible_item() {92fn create_refungible_item() {93}137}9413895#[test]139#[test]96fn create_fungible_item() {140fn create_multiple_refungible_items() {141 new_test_ext().execute_with(|| {142 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();143 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();144 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();145 let mode: CollectionMode = CollectionMode::ReFungible(2000, 3);146147 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 148 collection_numbers_limit: 10,149 account_token_ownership_limit: 10,150 collections_admins_limit: 5,151 custom_data_limit: 2048,152 nft_sponsor_transfer_timeout: 15,153 fungible_sponsor_transfer_timeout: 15,154 refungible_sponsor_transfer_timeout: 15, 155 }));156157 let origin1 = Origin::signed(1);158 assert_ok!(TemplateModule::create_collection(159 origin1.clone(),160 col_name1.clone(),161 col_desc1.clone(),162 token_prefix1.clone(),163 mode164 ));165 assert_eq!(TemplateModule::collection(1).owner, 1);166167 let properties = [[1, 2, 3].to_vec(), [3, 2, 1].to_vec(), [3, 3, 3].to_vec()].to_vec();168169 assert_ok!(TemplateModule::create_multiple_items(170 origin1.clone(),171 1,172 properties.clone(),173 1174 ));175 for (index, data) in properties.iter().enumerate() {176177 let item = TemplateModule::refungible_item_id(1, (index + 1) as u64);178 assert_eq!(item.data, *data);179 assert_eq!(180 item.owner[0],181 Ownership {182 owner: 1,183 fraction: 1000184 }185 );186 }187 });188}189190#[test]191fn create_fungible_item() {192 new_test_ext().execute_with(|| {193 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();194 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();195 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();196 let mode: CollectionMode = CollectionMode::Fungible(3);197198 assert_ok!(TemplateModule::set_chain_limits(RawOrigin::Root.into(), ChainLimits { 199 collection_numbers_limit: 10,200 account_token_ownership_limit: 10,201 collections_admins_limit: 5,202 custom_data_limit: 2048,203 nft_sponsor_transfer_timeout: 15,204 fungible_sponsor_transfer_timeout: 15,205 refungible_sponsor_transfer_timeout: 15, 206 }));207208 let origin1 = Origin::signed(1);209 assert_ok!(TemplateModule::create_collection(210 origin1.clone(),211 col_name1.clone(),212 col_desc1.clone(),213 token_prefix1.clone(),214 mode215 ));216 assert_eq!(TemplateModule::collection(1).owner, 1);217218 assert_ok!(TemplateModule::create_item(219 origin1.clone(),220 1,221 [].to_vec(),222 1223 ));224 assert_eq!(TemplateModule::fungible_item_id(1, 1).owner, 1);225 });226}227228#[test]229fn create_multiple_fungible_items() {97 new_test_ext().execute_with(|| {230 new_test_ext().execute_with(|| {98 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();231 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();99 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();232 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();120 ));253 ));121 assert_eq!(TemplateModule::collection(1).owner, 1);254 assert_eq!(TemplateModule::collection(1).owner, 1);255256 let properties = [[].to_vec(), [].to_vec(), [].to_vec()].to_vec();122257123 assert_ok!(TemplateModule::create_item(258 assert_ok!(TemplateModule::create_multiple_items(124 origin1.clone(),259 origin1.clone(),125 1,260 1,126 [].to_vec(),261 properties.clone(),127 1262 1128 ));263 ));264 265 for (index, _) in properties.iter().enumerate() {129 assert_eq!(TemplateModule::fungible_item_id(1, 1).owner, 1);266 assert_eq!(TemplateModule::fungible_item_id(1, (index + 1) as u64).owner, 1);267 }130 assert_eq!(TemplateModule::balance_count(1, 1), 1000);268 assert_eq!(TemplateModule::balance_count(1, 1), 3000);131 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);269 assert_eq!(TemplateModule::address_tokens(1, 1), [1, 2, 3]);132 });270 });133}271}134272