--- a/README.md +++ b/README.md @@ -117,6 +117,20 @@ "ReFungible": "(u32, u32)" } }, + "Ownership": { + "Owner": "AccountId", + "Fraction": "u128" + }, + "FungibleItemType": { + "Collection": "u64", + "Owner": "AccountId", + "Value": "u128" + }, + "ReFungibleItemType": { + "Collection": "u64", + "Owner": "Vec", + "Data": "Vec" + }, "NftItemType": { "Collection": "u64", "Owner": "AccountId", --- a/pallets/nft/src/lib.rs +++ b/pallets/nft/src/lib.rs @@ -122,6 +122,13 @@ pub data: Vec, } +#[derive(Encode, Decode, Default, Clone, PartialEq)] +#[cfg_attr(feature = "std", derive(Debug))] +pub struct ApprovePermissions { + pub approved: AccountId, + pub amount: u64 +} + pub trait Trait: system::Trait { type Event: From> + Into<::Event>; @@ -138,11 +145,13 @@ pub AdminList get(fn admin_list_collection): map hasher(identity) u64 => Vec; pub WhiteList get(fn white_list): map hasher(identity) u64 => Vec; - // Balance owner per collection map + /// Balance owner per collection map pub Balance get(fn balance_count): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) T::AccountId => u64; - pub ApprovedList get(fn approved): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => Vec; - // Item collections + /// second parameter: item id + owner account id + pub ApprovedList get(fn approved): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) (u64, T::AccountId) => Vec>; + + /// Item collections pub NftItemList get(fn nft_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => NftItemType; pub FungibleItemList get(fn fungible_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => FungibleItemType; pub ReFungibleItemList get(fn refungible_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => ReFungibleItemType; @@ -248,6 +257,7 @@ let sender = ensure_signed(origin)?; Self::check_owner_permissions(collection_id, sender)?; + // TODO Items remove >::remove_prefix(collection_id); >::remove_prefix(collection_id); >::remove_prefix(collection_id); @@ -356,18 +366,18 @@ pub fn create_item(origin, collection_id: u64, properties: Vec, owner: T::AccountId) -> DispatchResult { let sender = ensure_signed(origin)?; - - // check size let target_collection = >::get(collection_id); - ensure!(target_collection.custom_data_size >= properties.len() as u32, "Size of item is too large"); - Self::check_owner_or_admin_permissions(collection_id, sender.clone())?; // TODO: implement other modes match target_collection.mode { CollectionMode::NFT(_) => { - // Create nft item + + // check size + ensure!(target_collection.custom_data_size >= properties.len() as u32, "Size of item is too large"); + + // Create nft item let item = NftItemType { collection: collection_id, owner: owner, @@ -377,7 +387,24 @@ Self::add_nft_item(item)?; }, + CollectionMode::Fungible(_) => { + + // check size + ensure!(properties.len() as u32 == 0, "Size of item must be 0 with fungible type"); + + let item = FungibleItemType { + collection: collection_id, + owner: owner, + value: (10 as u128).pow(target_collection.decimal_points) + }; + + Self::add_fungible_item(item)?; + }, CollectionMode::ReFungible(_, _) => { + + // check size + ensure!(target_collection.custom_data_size >= properties.len() as u32, "Size of item is too large"); + let mut owner_list = Vec::new(); let value = (10 as u128).pow(target_collection.decimal_points); owner_list.push(Ownership {owner: owner, fraction: value}); @@ -413,6 +440,7 @@ match target_collection.mode { CollectionMode::NFT(_) => Self::burn_nft_item(collection_id, item_id)?, + CollectionMode::Fungible(_) => Self::burn_fungible_item(collection_id, item_id)?, CollectionMode::ReFungible(_, _) => Self::burn_refungible_item(collection_id, item_id, sender.clone())?, _ => () }; @@ -435,6 +463,7 @@ match target_collection.mode { CollectionMode::NFT(_) => Self::transfer_nft(collection_id, item_id, sender.clone(), recipient)?, + CollectionMode::Fungible(_) => Self::transfer_fungible(collection_id, item_id, value, sender.clone(), recipient)?, CollectionMode::ReFungible(_, _) => Self::transfer_refungible(collection_id, item_id, value, sender.clone(), recipient)?, _ => () }; @@ -447,26 +476,26 @@ let sender = ensure_signed(origin)?; - let item_owner = Self::is_item_owner(sender.clone(), collection_id, item_id); - if !item_owner - { - Self::check_owner_or_admin_permissions(collection_id, sender.clone())?; - } + // amount param stub + let amount = 100000000; - let list_exists = >::contains_key(collection_id, item_id); + ensure!(Self::is_item_owner(sender.clone(), collection_id, item_id), "Only item owner can call transfer method"); + + let list_exists = >::contains_key(collection_id, (item_id, sender.clone())); if list_exists { - let mut list = >::get(collection_id, item_id); - let item_contains = list.contains(&approved.clone()); + let mut list = >::get(collection_id, (item_id, sender.clone())); + let item_contains = list.iter().any(|i| i.approved == approved); if !item_contains { - list.push(approved.clone()); + list.push(ApprovePermissions { approved: approved.clone(), amount: amount }); + >::insert(collection_id, (item_id, sender.clone()), list); } } else { - let mut itm = Vec::new(); - itm.push(approved.clone()); - >::insert(collection_id, item_id, itm); + let mut list = Vec::new(); + list.push(ApprovePermissions { approved: approved.clone(), amount: amount }); + >::insert(collection_id, (item_id, sender.clone()), list); } Ok(()) @@ -475,16 +504,21 @@ #[weight = 0] pub fn transfer_from(origin, from: T::AccountId, recipient: T::AccountId, collection_id: u64, item_id: u64, value: u64 ) -> DispatchResult { - let mut approved: bool = false; let sender = ensure_signed(origin)?; - let approved_list_exists = >::contains_key(collection_id, item_id); + let approved_list_exists = >::contains_key(collection_id, (item_id, from.clone())); if approved_list_exists { - let list_itm = >::get(collection_id, item_id); - approved = list_itm.contains(&recipient.clone()); - } + let list_itm = >::get(collection_id, (item_id, from.clone())); + let opt_item = list_itm.iter().find(|i| i.approved == sender.clone()); + ensure!(opt_item.is_some(), "No approve found"); + ensure!(opt_item.unwrap().amount >= value, "Requested value more than approved"); - if !approved + // remove approve + let approve_list: Vec> = >::get(collection_id, (item_id, from.clone())) + .into_iter().filter(|i| i.approved != sender.clone()).collect(); + >::insert(collection_id, (item_id, from.clone()), approve_list); + } + else { Self::check_owner_or_admin_permissions(collection_id, sender)?; } @@ -494,8 +528,8 @@ match target_collection.mode { CollectionMode::NFT(_) => Self::transfer_nft(collection_id, item_id, from, recipient)?, - CollectionMode::ReFungible(_, _) => Self::transfer_refungible(collection_id, item_id, value, from, recipient)?, - // TODO: implement other modes + CollectionMode::Fungible(_) => Self::transfer_fungible(collection_id, item_id, value, from.clone(), recipient)?, + CollectionMode::ReFungible(_, _) => Self::transfer_refungible(collection_id, item_id, value, from.clone(), recipient)?, _ => () }; @@ -537,6 +571,121 @@ impl Module { + fn add_fungible_item(item: FungibleItemType) -> DispatchResult { + + let current_index = ::get(item.collection) + .checked_add(1) + .expect("Item list index id error"); + let itemcopy = item.clone(); + let owner = item.owner.clone(); + let value = item.value as u64; + + Self::add_token_index(item.collection, current_index, owner.clone())?; + + ::insert(item.collection, current_index); + >::insert(item.collection, current_index, itemcopy); + + // Update balance + let new_balance = >::get(item.collection, owner.clone()).checked_add(value).unwrap(); + >::insert(item.collection, owner.clone(), new_balance); + + Ok(()) + } + + fn add_refungible_item(item: ReFungibleItemType) -> DispatchResult { + + let current_index = ::get(item.collection) + .checked_add(1) + .expect("Item list index id error"); + let itemcopy = item.clone(); + + let value = item.owner.first().unwrap().fraction as u64; + let owner = item.owner.first().unwrap().owner.clone(); + + Self::add_token_index(item.collection, current_index, owner.clone())?; + + ::insert(item.collection, current_index); + >::insert(item.collection, current_index, itemcopy); + + // Update balance + let new_balance = >::get(item.collection, owner.clone()).checked_add(value).unwrap(); + >::insert(item.collection, owner.clone(), new_balance); + + Ok(()) + } + + fn add_nft_item(item: NftItemType) -> DispatchResult { + + let current_index = ::get(item.collection) + .checked_add(1) + .expect("Item list index id error"); + + let item_owner = item.owner.clone(); + let collection_id = item.collection.clone(); + Self::add_token_index(collection_id, current_index, item.owner.clone())?; + + ::insert(collection_id, current_index); + >::insert(collection_id, current_index, item); + + // Update balance + let new_balance = >::get(collection_id, item_owner.clone()).checked_add(1).unwrap(); + >::insert(collection_id, item_owner.clone(), new_balance); + + Ok(()) + } + + fn burn_refungible_item(collection_id: u64, item_id: u64, owner: T::AccountId) -> DispatchResult { + + let collection = >::get(collection_id, item_id); + let item = collection.owner.iter().filter(|&i| i.owner == owner).next().unwrap(); + Self::remove_token_index(collection_id, item_id, owner.clone())?; + + // remove approve list + >::remove(collection_id, (item_id, owner.clone())); + + // update balance + let new_balance = >::get(collection_id, item.owner.clone()).checked_sub(item.fraction as u64).unwrap(); + >::insert(collection_id, item.owner.clone(), new_balance); + + + >::remove(collection_id, item_id); + + Ok(()) + } + + fn burn_nft_item(collection_id: u64, item_id: u64) -> DispatchResult { + + let item = >::get(collection_id, item_id); + Self::remove_token_index(collection_id, item_id, item.owner.clone())?; + + // remove approve list + >::remove(collection_id, (item_id, item.owner.clone())); + + // update balance + let new_balance = >::get(collection_id, item.owner.clone()).checked_sub(1).unwrap(); + >::insert(collection_id, item.owner.clone(), new_balance); + >::remove(collection_id, item_id); + + Ok(()) + } + + fn burn_fungible_item(collection_id: u64, item_id: u64) -> DispatchResult { + + let item = >::get(collection_id, item_id); + Self::remove_token_index(collection_id, item_id, item.owner.clone())?; + + // remove approve list + >::remove(collection_id, (item_id, item.owner.clone())); + + // update balance + let new_balance = >::get(collection_id, item.owner.clone()).checked_sub(item.value as u64).unwrap(); + >::insert(collection_id, item.owner.clone(), new_balance); + + >::remove(collection_id, item_id); + + Ok(()) + } + fn collection_exists(collection_id: u64) -> DispatchResult{ ensure!(>::contains_key(collection_id), "This collection does not exist"); Ok(()) @@ -582,50 +731,90 @@ } } - fn add_refungible_item(item: ReFungibleItemType) -> DispatchResult { + fn transfer_fungible(collection_id: u64, item_id: u64, value: u64, owner: T::AccountId, new_owner: T::AccountId) -> DispatchResult { + let full_item = >::get(collection_id, item_id); + let amount = full_item.value; + + ensure!(amount >= value.into(),"Item balance not enouth"); + + // update balance + let balance_old_owner = >::get(collection_id, owner.clone()).checked_sub(value).unwrap(); + >::insert(collection_id, owner.clone(), balance_old_owner); + + let mut new_owner_account_id = 0; + let new_owner_items = >::get(collection_id, new_owner.clone()); + if new_owner_items.len() > 0 { + new_owner_account_id = new_owner_items[0]; + } + + let val64 = value.into(); - let current_index = ::get(item.collection) - .checked_add(1) - .expect("Item list index id error"); + // transfer + if amount == val64 && new_owner_account_id == 0 + { + // change owner + // new owner do not have account + let mut new_full_item = full_item.clone(); + new_full_item.owner = new_owner.clone(); + >::insert(collection_id, item_id, new_full_item); - let value = item.owner.first().unwrap().fraction as u64; - let owner = item.owner.first().unwrap().owner.clone(); + // update balance + let balance_new_owner = >::get(collection_id, new_owner.clone()).checked_add(value).unwrap(); + >::insert(collection_id, new_owner.clone(), balance_new_owner); - Self::add_token_index(item.collection, current_index, owner.clone())?; + // update index collection + Self::move_token_index(collection_id, item_id, owner.clone(), new_owner.clone())?; + } + else + { + let mut new_full_item = full_item.clone(); + new_full_item.value -= val64; - ::insert(item.collection, current_index); - >::insert(item.collection, current_index, item); - - // Update balance - let new_balance = >::get(item.collection, owner.clone()).checked_add(value).unwrap(); - >::insert(item.collection, owner.clone(), new_balance); + // separate amount + if new_owner_account_id > 0 { + + // new owner has account + let mut item = >::get(collection_id, new_owner_account_id); + item.value += val64; + + // update balance + let balance_new_owner = >::get(collection_id, new_owner.clone()).checked_add(value).unwrap(); + >::insert(collection_id, new_owner.clone(), balance_new_owner); - Ok(()) - } + >::insert(collection_id, new_owner_account_id, item); + } + else + { + // new owner do not have account + let item = FungibleItemType { + collection: collection_id, + owner: new_owner.clone(), + value: val64 + }; - fn burn_refungible_item(collection_id: u64, item_id: u64, owner: T::AccountId) -> DispatchResult { - - let collection = >::get(collection_id, item_id); - let item = collection.owner.iter().filter(|&i| i.owner == owner).next().unwrap(); - Self::remove_token_index(collection_id, item_id, owner)?; + Self::add_fungible_item(item)?; + } - // update balance - let new_balance = >::get(collection_id, item.owner.clone()).checked_sub(item.fraction as u64).unwrap(); - >::insert(collection_id, item.owner.clone(), new_balance); + if amount == val64{ + Self::remove_token_index(collection_id, item_id, full_item.owner.clone())?; + + // remove approve list + >::remove(collection_id, (item_id, full_item.owner.clone())); + >::remove(collection_id, item_id); + } - // TODO - >::remove(collection_id, item_id); + >::insert(collection_id, item_id, new_full_item); + } Ok(()) } fn transfer_refungible(collection_id: u64, item_id: u64, value: u64, owner: T::AccountId, new_owner: T::AccountId) -> DispatchResult { - let full_item = >::get(collection_id, item_id); let item = full_item.owner.iter().filter(|i| i.owner == owner).next().unwrap(); let amount = item.fraction; - ensure!(amount < value.into(),"Item balance not enouth"); + ensure!(amount >= value.into(),"Item balance not enouth"); // update balance let balance_old_owner = >::get(collection_id, item.owner.clone()).checked_sub(value).unwrap(); @@ -636,9 +825,10 @@ let old_owner = item.owner.clone(); let new_owner_has_account = full_item.owner.iter().any(|i| i.owner == new_owner); + let val64 = value.into(); // transfer - if amount == value.into() && !new_owner_has_account + if amount == val64 && !new_owner_has_account { // change owner // new owner do not have account @@ -652,17 +842,17 @@ else { let mut new_full_item = full_item.clone(); - new_full_item.owner.iter_mut().find(|i| i.owner == owner).unwrap().fraction -= amount; + new_full_item.owner.iter_mut().find(|i| i.owner == owner).unwrap().fraction -= val64; // separate amount if new_owner_has_account { // new owner has account - new_full_item.owner.iter_mut().find(|i| i.owner == new_owner).unwrap().fraction += amount; + new_full_item.owner.iter_mut().find(|i| i.owner == new_owner).unwrap().fraction += val64; } else { // new owner do not have account - new_full_item.owner.push(Ownership { owner: new_owner.clone(), fraction: amount}); + new_full_item.owner.push(Ownership { owner: new_owner.clone(), fraction: val64}); Self::add_token_index(collection_id, item_id, new_owner.clone())?; } @@ -671,38 +861,7 @@ Ok(()) } - - fn add_nft_item(item: NftItemType) -> DispatchResult { - - let current_index = ::get(item.collection) - .checked_add(1) - .expect("Item list index id error"); - - Self::add_token_index(item.collection, current_index, item.owner.clone())?; - - ::insert(item.collection, current_index); - >::insert(item.collection, current_index, item); - // Update balance - let new_balance = >::get(item.collection, item.owner.clone()).checked_add(1).unwrap(); - >::insert(item.collection_id, item.owner.clone(), new_balance); - - Ok(()) - } - - fn burn_nft_item(collection_id: u64, item_id: u64) -> DispatchResult { - - let item = >::get(collection_id, item_id); - Self::remove_token_index(collection_id, item_id, item.owner.clone())?; - - // update balance - let new_balance = >::get(collection_id, item.owner.clone()).checked_sub(1).unwrap(); - >::insert(collection_id, item.owner.clone(), new_balance); - >::remove(collection_id, item_id); - - Ok(()) - } - fn transfer_nft(collection_id: u64, item_id: u64, sender: T::AccountId, new_owner: T::AccountId) -> DispatchResult { let mut item = >::get(collection_id, item_id); @@ -722,12 +881,10 @@ >::insert(collection_id, item_id, item); // update index collection - Self::move_token_index(collection_id, item_id, old_owner, new_owner.clone())?; + Self::move_token_index(collection_id, item_id, old_owner.clone(), new_owner.clone())?; // reset approved list - let itm: Vec = Vec::new(); - >::insert(collection_id, item_id, itm); - + >::remove(collection_id, (item_id, old_owner)); Ok(()) } --- a/pallets/nft/src/tests.rs +++ b/pallets/nft/src/tests.rs @@ -1,566 +1,943 @@ // Tests to be written here use crate::mock::*; +use crate::{CollectionMode, Ownership, ApprovePermissions}; use frame_support::{assert_noop, assert_ok}; #[test] -fn create_collection_test() { +fn create_nft_item() { new_test_ext().execute_with(|| { let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + let mode: CollectionMode = CollectionMode::NFT(2000); - let size = 1024; let origin1 = Origin::signed(1); assert_ok!(TemplateModule::create_collection( origin1.clone(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), - size + mode )); assert_eq!(TemplateModule::collection(1).owner, 1); - }); -} -#[test] -fn change_collection_owner() { - new_test_ext().execute_with(|| { - let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); - let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); - let token_prefix1: Vec = b"token_prefix1\0".to_vec(); - let size = 1024; - let origin1 = Origin::signed(1); - - assert_ok!(TemplateModule::create_collection( - origin1.clone(), - col_name1.clone(), - col_desc1.clone(), - token_prefix1.clone(), - size - )); - assert_ok!(TemplateModule::change_collection_owner( - origin1.clone(), - 1, - 2 - )); - assert_eq!(TemplateModule::collection(1).owner, 2); + assert_ok!(TemplateModule::create_item(origin1.clone(), 1, [1,2,3].to_vec(), 1)); + assert_eq!(TemplateModule::nft_item_id(1,1).data, [1,2,3].to_vec()); }); } #[test] -fn destroy_collection() { +fn create_refungible_item() { new_test_ext().execute_with(|| { let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + let mode: CollectionMode = CollectionMode::ReFungible(2000, 3); - let size = 1024; let origin1 = Origin::signed(1); - assert_ok!(TemplateModule::create_collection( origin1.clone(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), - size + mode )); - assert_ok!(TemplateModule::destroy_collection(origin1.clone(), 1)); + assert_eq!(TemplateModule::collection(1).owner, 1); + + + assert_ok!(TemplateModule::create_item(origin1.clone(), 1, [1,2,3].to_vec(), 1)); + assert_eq!(TemplateModule::refungible_item_id(1,1).data, [1,2,3].to_vec()); + assert_eq!(TemplateModule::refungible_item_id(1,1).owner[0], Ownership { owner: 1, fraction: 1000 }); }); } #[test] -fn create_item() { +fn create_fungible_item() { new_test_ext().execute_with(|| { let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + let mode: CollectionMode = CollectionMode::Fungible(3); - let size = 1024; let origin1 = Origin::signed(1); - let origin2 = Origin::signed(2); - assert_ok!(TemplateModule::create_collection( origin1.clone(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), - size - )); - assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2)); - assert_ok!(TemplateModule::create_item( - origin2.clone(), - 1, - [1, 1, 1].to_vec() + mode )); + assert_eq!(TemplateModule::collection(1).owner, 1); - // check balance (collection with id = 1, user id = 2) - assert_eq!(TemplateModule::balance_count((1, 2)), 1); + assert_ok!(TemplateModule::create_item(origin1.clone(), 1, [].to_vec(), 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 burn_item() { +fn transfer_fungible_item() { new_test_ext().execute_with(|| { let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + let mode: CollectionMode = CollectionMode::Fungible(3); - let size = 1024; let origin1 = Origin::signed(1); let origin2 = Origin::signed(2); - assert_ok!(TemplateModule::create_collection( origin1.clone(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), - size + mode )); - assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2)); - assert_ok!(TemplateModule::create_item( - origin2.clone(), - 1, - [1, 1, 1].to_vec() - )); + assert_eq!(TemplateModule::collection(1).owner, 1); - // check balance (collection with id = 1, user id = 2) - assert_eq!(TemplateModule::balance_count((1, 2)), 1); + assert_ok!(TemplateModule::create_item(origin1.clone(), 1, [].to_vec(), 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]); - // burn item - assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1)); - assert_noop!( - TemplateModule::burn_item(origin1.clone(), 1, 1), - "Item does not exists" - ); + // change owner scenario + assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1000)); + assert_eq!(TemplateModule::fungible_item_id(1,1).owner, 2); + assert_eq!(TemplateModule::fungible_item_id(1,1).value, 1000); + assert_eq!(TemplateModule::balance_count(1,1), 0); + assert_eq!(TemplateModule::balance_count(1,2), 1000); + assert_eq!(TemplateModule::address_tokens(1,1), []); + assert_eq!(TemplateModule::address_tokens(1,2), [1]); + + // split item scenario + assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 500)); + assert_eq!(TemplateModule::fungible_item_id(1,1).owner, 2); + assert_eq!(TemplateModule::fungible_item_id(1,2).owner, 3); + assert_eq!(TemplateModule::balance_count(1,2), 500); + assert_eq!(TemplateModule::balance_count(1,3), 500); + assert_eq!(TemplateModule::address_tokens(1,2), [1]); + assert_eq!(TemplateModule::address_tokens(1,3), [2]); - assert_eq!(TemplateModule::balance_count((1, 1)), 0); + // split item and new owner has account scenario + assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 200)); + assert_eq!(TemplateModule::fungible_item_id(1,1).value, 300); + assert_eq!(TemplateModule::fungible_item_id(1,2).value, 700); + assert_eq!(TemplateModule::balance_count(1,2), 300); + assert_eq!(TemplateModule::balance_count(1,3), 700); + assert_eq!(TemplateModule::address_tokens(1,2), [1]); + assert_eq!(TemplateModule::address_tokens(1,3), [2]); }); } #[test] -fn add_collection_admin() { +fn transfer_refungible_item() { new_test_ext().execute_with(|| { let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + let mode: CollectionMode = CollectionMode::ReFungible(2000, 3); - let size = 1024; let origin1 = Origin::signed(1); let origin2 = Origin::signed(2); - let origin3 = Origin::signed(3); - assert_ok!(TemplateModule::create_collection( origin1.clone(), - col_name1.clone(), - col_desc1.clone(), - token_prefix1.clone(), - size - )); - assert_ok!(TemplateModule::create_collection( - origin2.clone(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), - size - )); - assert_ok!(TemplateModule::create_collection( - origin3.clone(), - col_name1.clone(), - col_desc1.clone(), - token_prefix1.clone(), - size + mode )); - assert_eq!(TemplateModule::collection(1).owner, 1); - assert_eq!(TemplateModule::collection(2).owner, 2); - assert_eq!(TemplateModule::collection(3).owner, 3); - // collection admin - assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2)); - assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 3)); + assert_ok!(TemplateModule::create_item(origin1.clone(), 1, [1,2,3].to_vec(), 1)); + assert_eq!(TemplateModule::refungible_item_id(1,1).data, [1,2,3].to_vec()); + assert_eq!(TemplateModule::refungible_item_id(1,1).owner[0], Ownership { owner: 1, fraction: 1000 }); + assert_eq!(TemplateModule::balance_count(1,1), 1000); + assert_eq!(TemplateModule::address_tokens(1,1), [1]); - assert_eq!(TemplateModule::admin_list_collection(1).contains(&2), true); - assert_eq!(TemplateModule::admin_list_collection(1).contains(&3), true); + // change owner scenario + assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1000)); + assert_eq!(TemplateModule::refungible_item_id(1,1).owner[0], Ownership { owner: 2, fraction: 1000 }); + assert_eq!(TemplateModule::balance_count(1,1), 0); + assert_eq!(TemplateModule::balance_count(1,2), 1000); + assert_eq!(TemplateModule::address_tokens(1,1), []); + assert_eq!(TemplateModule::address_tokens(1,2), [1]); + + // split item scenario + assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 500)); + assert_eq!(TemplateModule::refungible_item_id(1,1).owner[0], Ownership { owner: 2, fraction: 500 }); + assert_eq!(TemplateModule::refungible_item_id(1,1).owner[1], Ownership { owner: 3, fraction: 500 }); + assert_eq!(TemplateModule::balance_count(1,2), 500); + assert_eq!(TemplateModule::balance_count(1,3), 500); + assert_eq!(TemplateModule::address_tokens(1,2), [1]); + assert_eq!(TemplateModule::address_tokens(1,3), [1]); + + // split item and new owner has account scenario + assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 200)); + assert_eq!(TemplateModule::refungible_item_id(1,1).owner[0], Ownership { owner: 2, fraction: 300 }); + assert_eq!(TemplateModule::refungible_item_id(1,1).owner[1], Ownership { owner: 3, fraction: 700 }); + assert_eq!(TemplateModule::balance_count(1,2), 300); + assert_eq!(TemplateModule::balance_count(1,3), 700); + assert_eq!(TemplateModule::address_tokens(1,2), [1]); + assert_eq!(TemplateModule::address_tokens(1,3), [1]); }); } + #[test] -fn remove_collection_admin() { +fn transfer_nft_item() { new_test_ext().execute_with(|| { let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + let mode: CollectionMode = CollectionMode::NFT(2000); - let size = 1024; let origin1 = Origin::signed(1); - let origin2 = Origin::signed(2); - let origin3 = Origin::signed(3); - assert_ok!(TemplateModule::create_collection( origin1.clone(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), - size - )); - assert_ok!(TemplateModule::create_collection( - origin2.clone(), - col_name1.clone(), - col_desc1.clone(), - token_prefix1.clone(), - size - )); - assert_ok!(TemplateModule::create_collection( - origin3.clone(), - col_name1.clone(), - col_desc1.clone(), - token_prefix1.clone(), - size + mode )); - assert_eq!(TemplateModule::collection(1).owner, 1); - assert_eq!(TemplateModule::collection(2).owner, 2); - assert_eq!(TemplateModule::collection(3).owner, 3); - // collection admin - assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2)); - assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 3)); - assert_eq!(TemplateModule::admin_list_collection(1).contains(&2), true); - assert_eq!(TemplateModule::admin_list_collection(1).contains(&3), true); + assert_ok!(TemplateModule::create_item(origin1.clone(), 1, [1,2,3].to_vec(), 1)); + assert_eq!(TemplateModule::nft_item_id(1,1).data, [1,2,3].to_vec()); + assert_eq!(TemplateModule::balance_count(1,1), 1); + assert_eq!(TemplateModule::address_tokens(1,1), [1]); - // remove admin - assert_ok!(TemplateModule::remove_collection_admin( - origin2.clone(), - 1, - 3 - )); - assert_eq!(TemplateModule::admin_list_collection(1).contains(&3), false); + // default scenario + assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1000)); + assert_eq!(TemplateModule::nft_item_id(1,1).owner, 2); + assert_eq!(TemplateModule::balance_count(1,1), 0); + assert_eq!(TemplateModule::balance_count(1,2), 1); + assert_eq!(TemplateModule::address_tokens(1,1), []); + assert_eq!(TemplateModule::address_tokens(1,2), [1]); }); } #[test] -fn balance_of() { +fn nft_approve_and_transfer_from() { new_test_ext().execute_with(|| { let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + let mode: CollectionMode = CollectionMode::NFT(2000); - let size = 1024; let origin1 = Origin::signed(1); let origin2 = Origin::signed(2); - let origin3 = Origin::signed(3); - assert_ok!(TemplateModule::create_collection( origin1.clone(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), - size - )); - assert_ok!(TemplateModule::create_collection( - origin2.clone(), - col_name1.clone(), - col_desc1.clone(), - token_prefix1.clone(), - size + mode )); - assert_ok!(TemplateModule::create_collection( - origin3.clone(), - col_name1.clone(), - col_desc1.clone(), - token_prefix1.clone(), - size - )); + assert_eq!(TemplateModule::collection(1).owner, 1); - assert_eq!(TemplateModule::collection(1).owner, 1); - assert_eq!(TemplateModule::collection(2).owner, 2); - assert_eq!(TemplateModule::collection(3).owner, 3); - // check balance before - assert_eq!(TemplateModule::balance_count((1, 1)), 0); + assert_ok!(TemplateModule::create_item(origin1.clone(), 1, [1,2,3].to_vec(), 1)); + assert_eq!(TemplateModule::nft_item_id(1,1).data, [1,2,3].to_vec()); + assert_eq!(TemplateModule::balance_count(1,1), 1); + assert_eq!(TemplateModule::address_tokens(1,1), [1]); - // create item - assert_ok!(TemplateModule::create_item( - origin1.clone(), - 1, - [1, 1, 1].to_vec() - )); + assert_noop!( + TemplateModule::transfer_from(origin2.clone(), 1, 3, 1, 1, 1), + "You do not have permissions to modify this collection" + ); - // check balance (collection with id = 1, user id = 2) - assert_eq!(TemplateModule::balance_count((1, 1)), 1); - assert_eq!(TemplateModule::item_id((1, 1)).owner, 1); + // do approve + assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1)); + assert_eq!(TemplateModule::approved(1,(1,1)).len(), 1); + assert_ok!(TemplateModule::approve(origin1.clone(), 10, 1, 1)); + assert_eq!(TemplateModule::approved(1,(1,1)).len(), 2); + assert_eq!(TemplateModule::approved(1,(1,1))[0], ApprovePermissions { approved: 2, amount: 100000000}); + + assert_ok!(TemplateModule::transfer_from(origin2.clone(), 1, 3, 1, 1, 1)); + assert_eq!(TemplateModule::approved(1,(1,1)).len(), 0); }); } #[test] -fn transfer() { +fn refungible_approve_and_transfer_from() { new_test_ext().execute_with(|| { let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + let mode: CollectionMode = CollectionMode::ReFungible(2000, 3); - let size = 1024; let origin1 = Origin::signed(1); let origin2 = Origin::signed(2); - let origin3 = Origin::signed(3); - assert_ok!(TemplateModule::create_collection( origin1.clone(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), - size - )); - assert_ok!(TemplateModule::create_collection( - origin2.clone(), - col_name1.clone(), - col_desc1.clone(), - token_prefix1.clone(), - size - )); - assert_ok!(TemplateModule::create_collection( - origin3.clone(), - col_name1.clone(), - col_desc1.clone(), - token_prefix1.clone(), - size + mode )); + assert_eq!(TemplateModule::collection(1).owner, 1); - assert_eq!(TemplateModule::collection(1).owner, 1); - assert_eq!(TemplateModule::collection(2).owner, 2); - assert_eq!(TemplateModule::collection(3).owner, 3); + assert_ok!(TemplateModule::create_item(origin1.clone(), 1, [1,2,3].to_vec(), 1)); + assert_eq!(TemplateModule::refungible_item_id(1,1).data, [1,2,3].to_vec()); + assert_eq!(TemplateModule::refungible_item_id(1,1).owner[0], Ownership { owner: 1, fraction: 1000 }); + assert_eq!(TemplateModule::balance_count(1,1), 1000); + assert_eq!(TemplateModule::address_tokens(1,1), [1]); + + assert_noop!( + TemplateModule::transfer_from(origin2.clone(), 1, 3, 1, 1, 1), + "You do not have permissions to modify this collection" + ); - // create item - assert_ok!(TemplateModule::create_item( - origin1.clone(), - 1, - [1, 1, 1].to_vec() - )); + // do approve + assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1)); + assert_eq!(TemplateModule::approved(1,(1,1)).len(), 1); + assert_ok!(TemplateModule::approve(origin1.clone(), 10, 1, 1)); + assert_eq!(TemplateModule::approved(1,(1,1)).len(), 2); + assert_eq!(TemplateModule::approved(1,(1,1))[0], ApprovePermissions { approved: 2, amount: 100000000}); - // transfer - assert_ok!(TemplateModule::transfer(origin1.clone(), 1, 1, 2)); - assert_eq!(TemplateModule::item_id((1, 1)).owner, 2); + assert_ok!(TemplateModule::transfer_from(origin2.clone(), 1, 3, 1, 1, 100)); + assert_eq!(TemplateModule::balance_count(1,1), 900); + assert_eq!(TemplateModule::balance_count(1,3), 100); + assert_eq!(TemplateModule::address_tokens(1,1), [1]); + assert_eq!(TemplateModule::address_tokens(1,3), [1]); - // balance_of check - assert_eq!(TemplateModule::balance_count((1, 1)), 0); - assert_eq!(TemplateModule::balance_count((1, 2)), 1); + assert_eq!(TemplateModule::approved(1,(1,1)).len(), 1); + assert_eq!(TemplateModule::approved(1,(1,1))[0], ApprovePermissions { approved: 10, amount: 100000000}); }); } #[test] -fn approve() { +fn fungible_approve_and_transfer_from() { new_test_ext().execute_with(|| { let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + let mode: CollectionMode = CollectionMode::Fungible(3); - let size = 1024; let origin1 = Origin::signed(1); let origin2 = Origin::signed(2); - let origin3 = Origin::signed(3); - assert_ok!(TemplateModule::create_collection( origin1.clone(), col_name1.clone(), col_desc1.clone(), token_prefix1.clone(), - size + mode )); - assert_ok!(TemplateModule::create_collection( - origin2.clone(), - col_name1.clone(), - col_desc1.clone(), - token_prefix1.clone(), - size - )); - assert_ok!(TemplateModule::create_collection( - origin3.clone(), - col_name1.clone(), - col_desc1.clone(), - token_prefix1.clone(), - size - )); + assert_eq!(TemplateModule::collection(1).owner, 1); - assert_eq!(TemplateModule::collection(1).owner, 1); - assert_eq!(TemplateModule::collection(2).owner, 2); - assert_eq!(TemplateModule::collection(3).owner, 3); + assert_ok!(TemplateModule::create_item(origin1.clone(), 1, [].to_vec(), 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]); + + assert_noop!( + TemplateModule::transfer_from(origin2.clone(), 1, 3, 1, 1, 1), + "You do not have permissions to modify this collection" + ); + + // do approve + assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1)); + assert_eq!(TemplateModule::approved(1,(1,1)).len(), 1); + assert_ok!(TemplateModule::approve(origin1.clone(), 10, 1, 1)); + assert_eq!(TemplateModule::approved(1,(1,1)).len(), 2); + assert_eq!(TemplateModule::approved(1,(1,1))[0], ApprovePermissions { approved: 2, amount: 100000000}); + + assert_ok!(TemplateModule::transfer_from(origin2.clone(), 1, 3, 1, 1, 100)); + assert_eq!(TemplateModule::balance_count(1,1), 900); + assert_eq!(TemplateModule::balance_count(1,3), 100); + assert_eq!(TemplateModule::address_tokens(1,1), [1]); + assert_eq!(TemplateModule::address_tokens(1,3), [2]); - // create item - assert_ok!(TemplateModule::create_item( - origin1.clone(), - 1, - [1, 1, 1].to_vec() - )); + assert_eq!(TemplateModule::approved(1,(1,1)).len(), 1); + assert_eq!(TemplateModule::approved(1,(1,1))[0], ApprovePermissions { approved: 10, amount: 100000000}); - // approve assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1)); - assert_eq!(TemplateModule::approved((1, 1)).contains(&2), true); + assert_ok!(TemplateModule::transfer_from(origin2.clone(), 1, 3, 1, 1, 900)); + assert_eq!(TemplateModule::balance_count(1,1), 0); + assert_eq!(TemplateModule::balance_count(1,3), 1000); + assert_eq!(TemplateModule::address_tokens(1,1), []); + assert_eq!(TemplateModule::address_tokens(1,3), [2]); + + assert_eq!(TemplateModule::approved(1,(1,1)).len(), 0); }); } -#[test] -fn get_approved() { - new_test_ext().execute_with(|| { - let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); - let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); - let token_prefix1: Vec = b"token_prefix1\0".to_vec(); - let size = 1024; - let origin1 = Origin::signed(1); - let origin2 = Origin::signed(2); - let origin3 = Origin::signed(3); - assert_ok!(TemplateModule::create_collection( - origin1.clone(), - col_name1.clone(), - col_desc1.clone(), - token_prefix1.clone(), - size - )); - assert_ok!(TemplateModule::create_collection( - origin2.clone(), - col_name1.clone(), - col_desc1.clone(), - token_prefix1.clone(), - size - )); - assert_ok!(TemplateModule::create_collection( - origin3.clone(), - col_name1.clone(), - col_desc1.clone(), - token_prefix1.clone(), - size - )); - assert_eq!(TemplateModule::collection(1).owner, 1); - assert_eq!(TemplateModule::collection(2).owner, 2); - assert_eq!(TemplateModule::collection(3).owner, 3); - // create item - assert_ok!(TemplateModule::create_item( - origin1.clone(), - 1, - [1, 1, 1].to_vec() - )); - // approve - assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1)); - assert_eq!(TemplateModule::approved((1, 1)).contains(&2), true); - }); -} -#[test] -fn transfer_from() { - new_test_ext().execute_with(|| { - let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); - let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); - let token_prefix1: Vec = b"token_prefix1\0".to_vec(); - let size = 1024; - let origin1 = Origin::signed(1); - let origin2 = Origin::signed(2); - let origin3 = Origin::signed(3); - assert_ok!(TemplateModule::create_collection( - origin1.clone(), - col_name1.clone(), - col_desc1.clone(), - token_prefix1.clone(), - size - )); - assert_ok!(TemplateModule::create_collection( - origin2.clone(), - col_name1.clone(), - col_desc1.clone(), - token_prefix1.clone(), - size - )); - assert_ok!(TemplateModule::create_collection( - origin3.clone(), - col_name1.clone(), - col_desc1.clone(), - token_prefix1.clone(), - size - )); - assert_eq!(TemplateModule::collection(1).owner, 1); - assert_eq!(TemplateModule::collection(2).owner, 2); - assert_eq!(TemplateModule::collection(3).owner, 3); - // create item - assert_ok!(TemplateModule::create_item( - origin1.clone(), - 1, - [1, 1, 1].to_vec() - )); - // approve - assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1)); - assert_ok!(TemplateModule::transfer_from(origin1.clone(), 1, 1, 2)); - }); -} -#[test] -fn index_list() { - new_test_ext().execute_with(|| { - let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); - let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); - let token_prefix1: Vec = b"token_prefix1\0".to_vec(); - let size = 1024; - let origin1 = Origin::signed(1); - let origin2 = Origin::signed(2); - let origin3 = Origin::signed(3); - assert_ok!(TemplateModule::create_collection( - origin1.clone(), - col_name1.clone(), - col_desc1.clone(), - token_prefix1.clone(), - size - )); - assert_ok!(TemplateModule::create_collection( - origin2.clone(), - col_name1.clone(), - col_desc1.clone(), - token_prefix1.clone(), - size - )); - assert_ok!(TemplateModule::create_collection( - origin3.clone(), - col_name1.clone(), - col_desc1.clone(), - token_prefix1.clone(), - size - )); - assert_eq!(TemplateModule::collection(1).owner, 1); - assert_eq!(TemplateModule::collection(2).owner, 2); - assert_eq!(TemplateModule::collection(3).owner, 3); - // create items - assert_ok!(TemplateModule::create_item( - origin1.clone(), - 1, - [1, 1, 1].to_vec() - )); - assert_ok!(TemplateModule::create_item( - origin1.clone(), - 1, - [1, 1, 2].to_vec() - )); - assert_ok!(TemplateModule::create_item( - origin1.clone(), - 1, - [1, 2, 3].to_vec() - )); - assert_eq!(TemplateModule::address_tokens((1, 1)).len(), 3); - // burn one - assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 2)); - assert_eq!(TemplateModule::address_tokens((1, 1)).len(), 2); - // burn another one - assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 3)); - assert_eq!(TemplateModule::address_tokens((1, 1))[0], 1); - }); -} +// #[test] +// fn create_collection_test() { +// new_test_ext().execute_with(|| { +// let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); +// let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); +// let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + +// let size = 1024; +// let origin1 = Origin::signed(1); +// assert_ok!(TemplateModule::create_collection( +// origin1.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); +// assert_eq!(TemplateModule::collection(1).owner, 1); +// }); +// } + +// #[test] +// fn change_collection_owner() { +// new_test_ext().execute_with(|| { +// let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); +// let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); +// let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + +// let size = 1024; +// let origin1 = Origin::signed(1); + +// assert_ok!(TemplateModule::create_collection( +// origin1.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); +// assert_ok!(TemplateModule::change_collection_owner( +// origin1.clone(), +// 1, +// 2 +// )); +// assert_eq!(TemplateModule::collection(1).owner, 2); +// }); +// } + +// #[test] +// fn destroy_collection() { +// new_test_ext().execute_with(|| { +// let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); +// let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); +// let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + +// let size = 1024; +// let origin1 = Origin::signed(1); + +// assert_ok!(TemplateModule::create_collection( +// origin1.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); +// assert_ok!(TemplateModule::destroy_collection(origin1.clone(), 1)); +// }); +// } + +// #[test] +// fn create_item() { +// new_test_ext().execute_with(|| { +// let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); +// let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); +// let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + +// let size = 1024; +// let origin1 = Origin::signed(1); +// let origin2 = Origin::signed(2); + +// assert_ok!(TemplateModule::create_collection( +// origin1.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); +// assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2)); +// assert_ok!(TemplateModule::create_item( +// origin2.clone(), +// 1, +// [1, 1, 1].to_vec() +// )); + +// // check balance (collection with id = 1, user id = 2) +// assert_eq!(TemplateModule::balance_count((1, 2)), 1); +// }); +// } + +// #[test] +// fn burn_item() { +// new_test_ext().execute_with(|| { +// let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); +// let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); +// let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + +// let size = 1024; +// let origin1 = Origin::signed(1); +// let origin2 = Origin::signed(2); + +// assert_ok!(TemplateModule::create_collection( +// origin1.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); +// assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2)); +// assert_ok!(TemplateModule::create_item( +// origin2.clone(), +// 1, +// [1, 1, 1].to_vec() +// )); + +// // check balance (collection with id = 1, user id = 2) +// assert_eq!(TemplateModule::balance_count((1, 2)), 1); + +// // burn item +// assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1)); +// assert_noop!( +// TemplateModule::burn_item(origin1.clone(), 1, 1), +// "Item does not exists" +// ); + +// assert_eq!(TemplateModule::balance_count((1, 1)), 0); +// }); +// } + +// #[test] +// fn add_collection_admin() { +// new_test_ext().execute_with(|| { +// let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); +// let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); +// let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + +// let size = 1024; +// let origin1 = Origin::signed(1); +// let origin2 = Origin::signed(2); +// let origin3 = Origin::signed(3); + +// assert_ok!(TemplateModule::create_collection( +// origin1.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); +// assert_ok!(TemplateModule::create_collection( +// origin2.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); +// assert_ok!(TemplateModule::create_collection( +// origin3.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); + +// assert_eq!(TemplateModule::collection(1).owner, 1); +// assert_eq!(TemplateModule::collection(2).owner, 2); +// assert_eq!(TemplateModule::collection(3).owner, 3); + +// // collection admin +// assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2)); +// assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 3)); + +// assert_eq!(TemplateModule::admin_list_collection(1).contains(&2), true); +// assert_eq!(TemplateModule::admin_list_collection(1).contains(&3), true); +// }); +// } + +// #[test] +// fn remove_collection_admin() { +// new_test_ext().execute_with(|| { +// let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); +// let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); +// let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + +// let size = 1024; +// let origin1 = Origin::signed(1); +// let origin2 = Origin::signed(2); +// let origin3 = Origin::signed(3); + +// assert_ok!(TemplateModule::create_collection( +// origin1.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); +// assert_ok!(TemplateModule::create_collection( +// origin2.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); +// assert_ok!(TemplateModule::create_collection( +// origin3.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); + +// assert_eq!(TemplateModule::collection(1).owner, 1); +// assert_eq!(TemplateModule::collection(2).owner, 2); +// assert_eq!(TemplateModule::collection(3).owner, 3); + +// // collection admin +// assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2)); +// assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 3)); + +// assert_eq!(TemplateModule::admin_list_collection(1).contains(&2), true); +// assert_eq!(TemplateModule::admin_list_collection(1).contains(&3), true); + +// // remove admin +// assert_ok!(TemplateModule::remove_collection_admin( +// origin2.clone(), +// 1, +// 3 +// )); +// assert_eq!(TemplateModule::admin_list_collection(1).contains(&3), false); +// }); +// } + +// #[test] +// fn balance_of() { +// new_test_ext().execute_with(|| { +// let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); +// let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); +// let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + +// let size = 1024; +// let origin1 = Origin::signed(1); +// let origin2 = Origin::signed(2); +// let origin3 = Origin::signed(3); + +// assert_ok!(TemplateModule::create_collection( +// origin1.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); +// assert_ok!(TemplateModule::create_collection( +// origin2.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); +// assert_ok!(TemplateModule::create_collection( +// origin3.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); + +// assert_eq!(TemplateModule::collection(1).owner, 1); +// assert_eq!(TemplateModule::collection(2).owner, 2); +// assert_eq!(TemplateModule::collection(3).owner, 3); + +// // check balance before +// assert_eq!(TemplateModule::balance_count((1, 1)), 0); + +// // create item +// assert_ok!(TemplateModule::create_item( +// origin1.clone(), +// 1, +// [1, 1, 1].to_vec() +// )); + +// // check balance (collection with id = 1, user id = 2) +// assert_eq!(TemplateModule::balance_count((1, 1)), 1); +// assert_eq!(TemplateModule::item_id((1, 1)).owner, 1); +// }); +// } + +// #[test] +// fn transfer() { +// new_test_ext().execute_with(|| { +// let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); +// let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); +// let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + +// let size = 1024; +// let origin1 = Origin::signed(1); +// let origin2 = Origin::signed(2); +// let origin3 = Origin::signed(3); + +// assert_ok!(TemplateModule::create_collection( +// origin1.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); +// assert_ok!(TemplateModule::create_collection( +// origin2.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); +// assert_ok!(TemplateModule::create_collection( +// origin3.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); + +// assert_eq!(TemplateModule::collection(1).owner, 1); +// assert_eq!(TemplateModule::collection(2).owner, 2); +// assert_eq!(TemplateModule::collection(3).owner, 3); + +// // create item +// assert_ok!(TemplateModule::create_item( +// origin1.clone(), +// 1, +// [1, 1, 1].to_vec() +// )); + +// // transfer +// assert_ok!(TemplateModule::transfer(origin1.clone(), 1, 1, 2)); +// assert_eq!(TemplateModule::item_id((1, 1)).owner, 2); + +// // balance_of check +// assert_eq!(TemplateModule::balance_count((1, 1)), 0); +// assert_eq!(TemplateModule::balance_count((1, 2)), 1); +// }); +// } + +// #[test] +// fn approve() { +// new_test_ext().execute_with(|| { +// let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); +// let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); +// let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + +// let size = 1024; +// let origin1 = Origin::signed(1); +// let origin2 = Origin::signed(2); +// let origin3 = Origin::signed(3); + +// assert_ok!(TemplateModule::create_collection( +// origin1.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); +// assert_ok!(TemplateModule::create_collection( +// origin2.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); +// assert_ok!(TemplateModule::create_collection( +// origin3.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); + +// assert_eq!(TemplateModule::collection(1).owner, 1); +// assert_eq!(TemplateModule::collection(2).owner, 2); +// assert_eq!(TemplateModule::collection(3).owner, 3); + +// // create item +// assert_ok!(TemplateModule::create_item( +// origin1.clone(), +// 1, +// [1, 1, 1].to_vec() +// )); + +// // approve +// assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1)); +// assert_eq!(TemplateModule::approved((1, 1)).contains(&2), true); +// }); +// } + +// #[test] +// fn get_approved() { +// new_test_ext().execute_with(|| { +// let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); +// let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); +// let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + +// let size = 1024; +// let origin1 = Origin::signed(1); +// let origin2 = Origin::signed(2); +// let origin3 = Origin::signed(3); + +// assert_ok!(TemplateModule::create_collection( +// origin1.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); +// assert_ok!(TemplateModule::create_collection( +// origin2.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); +// assert_ok!(TemplateModule::create_collection( +// origin3.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); + +// assert_eq!(TemplateModule::collection(1).owner, 1); +// assert_eq!(TemplateModule::collection(2).owner, 2); +// assert_eq!(TemplateModule::collection(3).owner, 3); + +// // create item +// assert_ok!(TemplateModule::create_item( +// origin1.clone(), +// 1, +// [1, 1, 1].to_vec() +// )); + +// // approve +// assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1)); +// assert_eq!(TemplateModule::approved((1, 1)).contains(&2), true); +// }); +// } + +// #[test] +// fn transfer_from() { +// new_test_ext().execute_with(|| { +// let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); +// let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); +// let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + +// let size = 1024; +// let origin1 = Origin::signed(1); +// let origin2 = Origin::signed(2); +// let origin3 = Origin::signed(3); + +// assert_ok!(TemplateModule::create_collection( +// origin1.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); +// assert_ok!(TemplateModule::create_collection( +// origin2.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); +// assert_ok!(TemplateModule::create_collection( +// origin3.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); + +// assert_eq!(TemplateModule::collection(1).owner, 1); +// assert_eq!(TemplateModule::collection(2).owner, 2); +// assert_eq!(TemplateModule::collection(3).owner, 3); + +// // create item +// assert_ok!(TemplateModule::create_item( +// origin1.clone(), +// 1, +// [1, 1, 1].to_vec() +// )); + +// // approve +// assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1)); +// assert_ok!(TemplateModule::transfer_from(origin1.clone(), 1, 1, 2)); +// }); +// } + +// #[test] +// fn index_list() { +// new_test_ext().execute_with(|| { +// let col_name1: Vec = "Test1\0".encode_utf16().collect::>(); +// let col_desc1: Vec = "TestDescription1\0".encode_utf16().collect::>(); +// let token_prefix1: Vec = b"token_prefix1\0".to_vec(); + +// let size = 1024; +// let origin1 = Origin::signed(1); +// let origin2 = Origin::signed(2); +// let origin3 = Origin::signed(3); + +// assert_ok!(TemplateModule::create_collection( +// origin1.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); +// assert_ok!(TemplateModule::create_collection( +// origin2.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); +// assert_ok!(TemplateModule::create_collection( +// origin3.clone(), +// col_name1.clone(), +// col_desc1.clone(), +// token_prefix1.clone(), +// size +// )); + +// assert_eq!(TemplateModule::collection(1).owner, 1); +// assert_eq!(TemplateModule::collection(2).owner, 2); +// assert_eq!(TemplateModule::collection(3).owner, 3); +// // create items +// assert_ok!(TemplateModule::create_item( +// origin1.clone(), +// 1, +// [1, 1, 1].to_vec() +// )); +// assert_ok!(TemplateModule::create_item( +// origin1.clone(), +// 1, +// [1, 1, 2].to_vec() +// )); +// assert_ok!(TemplateModule::create_item( +// origin1.clone(), +// 1, +// [1, 2, 3].to_vec() +// )); +// assert_eq!(TemplateModule::address_tokens((1, 1)).len(), 3); +// // burn one +// assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 2)); +// assert_eq!(TemplateModule::address_tokens((1, 1)).len(), 2); +// // burn another one +// assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 3)); +// assert_eq!(TemplateModule::address_tokens((1, 1))[0], 1); +// }); +// }