git.delta.rocks / unique-network / refs/commits / aa92af0d2bde

difftreelog

funfible item added

str-mv2020-08-06parent: #a55594d.patch.diff
in: master

3 files changed

modifiedREADME.mddiffbeforeafterboth
--- 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<Ownership>",
+    "Data": "Vec<u8>"
+  },
   "NftItemType": {
     "Collection": "u64",
     "Owner": "AccountId",
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
122 pub data: Vec<u8>,122 pub data: Vec<u8>,
123}123}
124
125#[derive(Encode, Decode, Default, Clone, PartialEq)]
126#[cfg_attr(feature = "std", derive(Debug))]
127pub struct ApprovePermissions<AccountId> {
128 pub approved: AccountId,
129 pub amount: u64
130}
124131
125pub trait Trait: system::Trait {132pub trait Trait: system::Trait {
126 type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;133 type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
138 pub AdminList get(fn admin_list_collection): map hasher(identity) u64 => Vec<T::AccountId>;145 pub AdminList get(fn admin_list_collection): map hasher(identity) u64 => Vec<T::AccountId>;
139 pub WhiteList get(fn white_list): map hasher(identity) u64 => Vec<T::AccountId>;146 pub WhiteList get(fn white_list): map hasher(identity) u64 => Vec<T::AccountId>;
140147
141 // Balance owner per collection map148 /// Balance owner per collection map
142 pub Balance get(fn balance_count): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) T::AccountId => u64;149 pub Balance get(fn balance_count): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) T::AccountId => u64;
150
151 /// second parameter: item id + owner account id
143 pub ApprovedList get(fn approved): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => Vec<T::AccountId>;152 pub ApprovedList get(fn approved): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) (u64, T::AccountId) => Vec<ApprovePermissions<T::AccountId>>;
144153
145 // Item collections154 /// Item collections
146 pub NftItemList get(fn nft_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => NftItemType<T::AccountId>;155 pub NftItemList get(fn nft_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => NftItemType<T::AccountId>;
147 pub FungibleItemList get(fn fungible_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => FungibleItemType<T::AccountId>;156 pub FungibleItemList get(fn fungible_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => FungibleItemType<T::AccountId>;
148 pub ReFungibleItemList get(fn refungible_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => ReFungibleItemType<T::AccountId>;157 pub ReFungibleItemList get(fn refungible_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => ReFungibleItemType<T::AccountId>;
248 let sender = ensure_signed(origin)?;257 let sender = ensure_signed(origin)?;
249 Self::check_owner_permissions(collection_id, sender)?;258 Self::check_owner_permissions(collection_id, sender)?;
250259
260 // TODO Items remove
251 <AddressTokens<T>>::remove_prefix(collection_id);261 <AddressTokens<T>>::remove_prefix(collection_id);
252 <ApprovedList<T>>::remove_prefix(collection_id);262 <ApprovedList<T>>::remove_prefix(collection_id);
253 <Balance<T>>::remove_prefix(collection_id);263 <Balance<T>>::remove_prefix(collection_id);
357367
358 let sender = ensure_signed(origin)?;368 let sender = ensure_signed(origin)?;
359
360 // check size
361 let target_collection = <Collection<T>>::get(collection_id);369 let target_collection = <Collection<T>>::get(collection_id);
362 ensure!(target_collection.custom_data_size >= properties.len() as u32, "Size of item is too large");
363
364 Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;370 Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;
365371
368 {374 {
369 CollectionMode::NFT(_) => {375 CollectionMode::NFT(_) => {
376
377 // check size
378 ensure!(target_collection.custom_data_size >= properties.len() as u32, "Size of item is too large");
379
370 // Create nft item380 // Create nft item
371 let item = NftItemType {381 let item = NftItemType {
377 Self::add_nft_item(item)?;387 Self::add_nft_item(item)?;
378 388
379 },389 },
390 CollectionMode::Fungible(_) => {
391
392 // check size
393 ensure!(properties.len() as u32 == 0, "Size of item must be 0 with fungible type");
394
395 let item = FungibleItemType {
396 collection: collection_id,
397 owner: owner,
398 value: (10 as u128).pow(target_collection.decimal_points)
399 };
400
401 Self::add_fungible_item(item)?;
402 },
380 CollectionMode::ReFungible(_, _) => {403 CollectionMode::ReFungible(_, _) => {
404
405 // check size
406 ensure!(target_collection.custom_data_size >= properties.len() as u32, "Size of item is too large");
407
381 let mut owner_list = Vec::new();408 let mut owner_list = Vec::new();
382 let value = (10 as u128).pow(target_collection.decimal_points);409 let value = (10 as u128).pow(target_collection.decimal_points);
413 match target_collection.mode 440 match target_collection.mode
414 {441 {
415 CollectionMode::NFT(_) => Self::burn_nft_item(collection_id, item_id)?,442 CollectionMode::NFT(_) => Self::burn_nft_item(collection_id, item_id)?,
443 CollectionMode::Fungible(_) => Self::burn_fungible_item(collection_id, item_id)?,
416 CollectionMode::ReFungible(_, _) => Self::burn_refungible_item(collection_id, item_id, sender.clone())?,444 CollectionMode::ReFungible(_, _) => Self::burn_refungible_item(collection_id, item_id, sender.clone())?,
417 _ => ()445 _ => ()
418 };446 };
435 match target_collection.mode 463 match target_collection.mode
436 {464 {
437 CollectionMode::NFT(_) => Self::transfer_nft(collection_id, item_id, sender.clone(), recipient)?,465 CollectionMode::NFT(_) => Self::transfer_nft(collection_id, item_id, sender.clone(), recipient)?,
466 CollectionMode::Fungible(_) => Self::transfer_fungible(collection_id, item_id, value, sender.clone(), recipient)?,
438 CollectionMode::ReFungible(_, _) => Self::transfer_refungible(collection_id, item_id, value, sender.clone(), recipient)?,467 CollectionMode::ReFungible(_, _) => Self::transfer_refungible(collection_id, item_id, value, sender.clone(), recipient)?,
439 _ => ()468 _ => ()
440 };469 };
447476
448 let sender = ensure_signed(origin)?;477 let sender = ensure_signed(origin)?;
449478
479 // amount param stub
450 let item_owner = Self::is_item_owner(sender.clone(), collection_id, item_id);480 let amount = 100000000;
451 if !item_owner481
452 {
453 Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;482 ensure!(Self::is_item_owner(sender.clone(), collection_id, item_id), "Only item owner can call transfer method");
454 }
455483
456 let list_exists = <ApprovedList<T>>::contains_key(collection_id, item_id);484 let list_exists = <ApprovedList<T>>::contains_key(collection_id, (item_id, sender.clone()));
457 if list_exists {485 if list_exists {
458486
459 let mut list = <ApprovedList<T>>::get(collection_id, item_id);487 let mut list = <ApprovedList<T>>::get(collection_id, (item_id, sender.clone()));
460 let item_contains = list.contains(&approved.clone());488 let item_contains = list.iter().any(|i| i.approved == approved);
461489
462 if !item_contains {490 if !item_contains {
463 list.push(approved.clone());491 list.push(ApprovePermissions { approved: approved.clone(), amount: amount });
492 <ApprovedList<T>>::insert(collection_id, (item_id, sender.clone()), list);
464 }493 }
465 } else {494 } else {
466495
467 let mut itm = Vec::new();496 let mut list = Vec::new();
468 itm.push(approved.clone());497 list.push(ApprovePermissions { approved: approved.clone(), amount: amount });
469 <ApprovedList<T>>::insert(collection_id, item_id, itm);498 <ApprovedList<T>>::insert(collection_id, (item_id, sender.clone()), list);
470 }499 }
471500
472 Ok(())501 Ok(())
475 #[weight = 0]504 #[weight = 0]
476 pub fn transfer_from(origin, from: T::AccountId, recipient: T::AccountId, collection_id: u64, item_id: u64, value: u64 ) -> DispatchResult {505 pub fn transfer_from(origin, from: T::AccountId, recipient: T::AccountId, collection_id: u64, item_id: u64, value: u64 ) -> DispatchResult {
477506
478 let mut approved: bool = false;
479 let sender = ensure_signed(origin)?;507 let sender = ensure_signed(origin)?;
480 let approved_list_exists = <ApprovedList<T>>::contains_key(collection_id, item_id);508 let approved_list_exists = <ApprovedList<T>>::contains_key(collection_id, (item_id, from.clone()));
481 if approved_list_exists509 if approved_list_exists
482 {510 {
483 let list_itm = <ApprovedList<T>>::get(collection_id, item_id);511 let list_itm = <ApprovedList<T>>::get(collection_id, (item_id, from.clone()));
484 approved = list_itm.contains(&recipient.clone());512 let opt_item = list_itm.iter().find(|i| i.approved == sender.clone());
513 ensure!(opt_item.is_some(), "No approve found");
514 ensure!(opt_item.unwrap().amount >= value, "Requested value more than approved");
515
516 // remove approve
517 let approve_list: Vec<ApprovePermissions<T::AccountId>> = <ApprovedList<T>>::get(collection_id, (item_id, from.clone()))
518 .into_iter().filter(|i| i.approved != sender.clone()).collect();
519 <ApprovedList<T>>::insert(collection_id, (item_id, from.clone()), approve_list);
485 }520 }
486521 else
487 if !approved
488 {522 {
489 Self::check_owner_or_admin_permissions(collection_id, sender)?;523 Self::check_owner_or_admin_permissions(collection_id, sender)?;
490 }524 }
494 match target_collection.mode528 match target_collection.mode
495 {529 {
496 CollectionMode::NFT(_) => Self::transfer_nft(collection_id, item_id, from, recipient)?,530 CollectionMode::NFT(_) => Self::transfer_nft(collection_id, item_id, from, recipient)?,
531 CollectionMode::Fungible(_) => Self::transfer_fungible(collection_id, item_id, value, from.clone(), recipient)?,
497 CollectionMode::ReFungible(_, _) => Self::transfer_refungible(collection_id, item_id, value, from, recipient)?,532 CollectionMode::ReFungible(_, _) => Self::transfer_refungible(collection_id, item_id, value, from.clone(), recipient)?,
498 // TODO: implement other modes
499 _ => ()533 _ => ()
500 };534 };
501535
537571
538impl<T: Trait> Module<T> {572impl<T: Trait> Module<T> {
573
574 fn add_fungible_item(item: FungibleItemType<T::AccountId>) -> DispatchResult {
575
576 let current_index = <ItemListIndex>::get(item.collection)
577 .checked_add(1)
578 .expect("Item list index id error");
579 let itemcopy = item.clone();
580 let owner = item.owner.clone();
581 let value = item.value as u64;
582
583 Self::add_token_index(item.collection, current_index, owner.clone())?;
584
585 <ItemListIndex>::insert(item.collection, current_index);
586 <FungibleItemList<T>>::insert(item.collection, current_index, itemcopy);
587
588 // Update balance
589 let new_balance = <Balance<T>>::get(item.collection, owner.clone()).checked_add(value).unwrap();
590 <Balance<T>>::insert(item.collection, owner.clone(), new_balance);
591
592 Ok(())
593 }
594
595 fn add_refungible_item(item: ReFungibleItemType<T::AccountId>) -> DispatchResult {
596
597 let current_index = <ItemListIndex>::get(item.collection)
598 .checked_add(1)
599 .expect("Item list index id error");
600 let itemcopy = item.clone();
601
602 let value = item.owner.first().unwrap().fraction as u64;
603 let owner = item.owner.first().unwrap().owner.clone();
604
605 Self::add_token_index(item.collection, current_index, owner.clone())?;
606
607 <ItemListIndex>::insert(item.collection, current_index);
608 <ReFungibleItemList<T>>::insert(item.collection, current_index, itemcopy);
609
610 // Update balance
611 let new_balance = <Balance<T>>::get(item.collection, owner.clone()).checked_add(value).unwrap();
612 <Balance<T>>::insert(item.collection, owner.clone(), new_balance);
613
614 Ok(())
615 }
616
617 fn add_nft_item(item: NftItemType<T::AccountId>) -> DispatchResult {
618
619 let current_index = <ItemListIndex>::get(item.collection)
620 .checked_add(1)
621 .expect("Item list index id error");
622
623 let item_owner = item.owner.clone();
624 let collection_id = item.collection.clone();
625 Self::add_token_index(collection_id, current_index, item.owner.clone())?;
626
627 <ItemListIndex>::insert(collection_id, current_index);
628 <NftItemList<T>>::insert(collection_id, current_index, item);
629
630 // Update balance
631 let new_balance = <Balance<T>>::get(collection_id, item_owner.clone()).checked_add(1).unwrap();
632 <Balance<T>>::insert(collection_id, item_owner.clone(), new_balance);
633
634 Ok(())
635 }
636
637 fn burn_refungible_item(collection_id: u64, item_id: u64, owner: T::AccountId) -> DispatchResult {
638
639 let collection = <ReFungibleItemList<T>>::get(collection_id, item_id);
640 let item = collection.owner.iter().filter(|&i| i.owner == owner).next().unwrap();
641 Self::remove_token_index(collection_id, item_id, owner.clone())?;
642
643 // remove approve list
644 <ApprovedList<T>>::remove(collection_id, (item_id, owner.clone()));
645
646 // update balance
647 let new_balance = <Balance<T>>::get(collection_id, item.owner.clone()).checked_sub(item.fraction as u64).unwrap();
648 <Balance<T>>::insert(collection_id, item.owner.clone(), new_balance);
649
650
651 <ReFungibleItemList<T>>::remove(collection_id, item_id);
652
653 Ok(())
654 }
655
656 fn burn_nft_item(collection_id: u64, item_id: u64) -> DispatchResult {
657
658 let item = <NftItemList<T>>::get(collection_id, item_id);
659 Self::remove_token_index(collection_id, item_id, item.owner.clone())?;
660
661 // remove approve list
662 <ApprovedList<T>>::remove(collection_id, (item_id, item.owner.clone()));
663
664 // update balance
665 let new_balance = <Balance<T>>::get(collection_id, item.owner.clone()).checked_sub(1).unwrap();
666 <Balance<T>>::insert(collection_id, item.owner.clone(), new_balance);
667 <NftItemList<T>>::remove(collection_id, item_id);
668
669 Ok(())
670 }
671
672 fn burn_fungible_item(collection_id: u64, item_id: u64) -> DispatchResult {
673
674 let item = <FungibleItemList<T>>::get(collection_id, item_id);
675 Self::remove_token_index(collection_id, item_id, item.owner.clone())?;
676
677 // remove approve list
678 <ApprovedList<T>>::remove(collection_id, (item_id, item.owner.clone()));
679
680 // update balance
681 let new_balance = <Balance<T>>::get(collection_id, item.owner.clone()).checked_sub(item.value as u64).unwrap();
682 <Balance<T>>::insert(collection_id, item.owner.clone(), new_balance);
683
684 <FungibleItemList<T>>::remove(collection_id, item_id);
685
686 Ok(())
687 }
539688
540 fn collection_exists(collection_id: u64) -> DispatchResult{689 fn collection_exists(collection_id: u64) -> DispatchResult{
541 ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");690 ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
582 }731 }
583 }732 }
584
585 fn add_refungible_item(item: ReFungibleItemType<T::AccountId>) -> DispatchResult {
586
587 let current_index = <ItemListIndex>::get(item.collection)
588 .checked_add(1)
589 .expect("Item list index id error");
590
591 let value = item.owner.first().unwrap().fraction as u64;
592 let owner = item.owner.first().unwrap().owner.clone();
593
594 Self::add_token_index(item.collection, current_index, owner.clone())?;
595
596 <ItemListIndex>::insert(item.collection, current_index);
597 <ReFungibleItemList<T>>::insert(item.collection, current_index, item);
598
599 // Update balance
600 let new_balance = <Balance<T>>::get(item.collection, owner.clone()).checked_add(value).unwrap();
601 <Balance<T>>::insert(item.collection, owner.clone(), new_balance);
602
603 Ok(())
604 }
605733
606 fn burn_refungible_item(collection_id: u64, item_id: u64, owner: T::AccountId) -> DispatchResult {734 fn transfer_fungible(collection_id: u64, item_id: u64, value: u64, owner: T::AccountId, new_owner: T::AccountId) -> DispatchResult {
607
608 let collection = <ReFungibleItemList<T>>::get(collection_id, item_id);735 let full_item = <FungibleItemList<T>>::get(collection_id, item_id);
736 let amount = full_item.value;
737
738 ensure!(amount >= value.into(),"Item balance not enouth");
739
740 // update balance
609 let item = collection.owner.iter().filter(|&i| i.owner == owner).next().unwrap();741 let balance_old_owner = <Balance<T>>::get(collection_id, owner.clone()).checked_sub(value).unwrap();
610 Self::remove_token_index(collection_id, item_id, owner)?;742 <Balance<T>>::insert(collection_id, owner.clone(), balance_old_owner);
743
744 let mut new_owner_account_id = 0;
745 let new_owner_items = <AddressTokens<T>>::get(collection_id, new_owner.clone());
746 if new_owner_items.len() > 0 {
747 new_owner_account_id = new_owner_items[0];
748 }
749
750 let val64 = value.into();
751
752 // transfer
753 if amount == val64 && new_owner_account_id == 0
754 {
755 // change owner
756 // new owner do not have account
757 let mut new_full_item = full_item.clone();
758 new_full_item.owner = new_owner.clone();
759 <FungibleItemList<T>>::insert(collection_id, item_id, new_full_item);
611760
612 // update balance761 // update balance
613 let new_balance = <Balance<T>>::get(collection_id, item.owner.clone()).checked_sub(item.fraction as u64).unwrap();762 let balance_new_owner = <Balance<T>>::get(collection_id, new_owner.clone()).checked_add(value).unwrap();
614 <Balance<T>>::insert(collection_id, item.owner.clone(), new_balance);763 <Balance<T>>::insert(collection_id, new_owner.clone(), balance_new_owner);
615764
616 // TODO765 // update index collection
766 Self::move_token_index(collection_id, item_id, owner.clone(), new_owner.clone())?;
767 }
768 else
769 {
770 let mut new_full_item = full_item.clone();
771 new_full_item.value -= val64;
772
773 // separate amount
774 if new_owner_account_id > 0 {
775
776 // new owner has account
777 let mut item = <FungibleItemList<T>>::get(collection_id, new_owner_account_id);
778 item.value += val64;
779
780 // update balance
781 let balance_new_owner = <Balance<T>>::get(collection_id, new_owner.clone()).checked_add(value).unwrap();
782 <Balance<T>>::insert(collection_id, new_owner.clone(), balance_new_owner);
783
784 <FungibleItemList<T>>::insert(collection_id, new_owner_account_id, item);
785 }
786 else
787 {
788 // new owner do not have account
789 let item = FungibleItemType {
790 collection: collection_id,
791 owner: new_owner.clone(),
792 value: val64
793 };
794
795 Self::add_fungible_item(item)?;
796 }
797
798 if amount == val64{
799 Self::remove_token_index(collection_id, item_id, full_item.owner.clone())?;
800
801 // remove approve list
617 <ReFungibleItemList<T>>::remove(collection_id, item_id);802 <ApprovedList<T>>::remove(collection_id, (item_id, full_item.owner.clone()));
803 <FungibleItemList<T>>::remove(collection_id, item_id);
804 }
805
806 <FungibleItemList<T>>::insert(collection_id, item_id, new_full_item);
807 }
618808
619 Ok(())809 Ok(())
620 }810 }
625 let item = full_item.owner.iter().filter(|i| i.owner == owner).next().unwrap();814 let item = full_item.owner.iter().filter(|i| i.owner == owner).next().unwrap();
626 let amount = item.fraction;815 let amount = item.fraction;
627816
628 ensure!(amount < value.into(),"Item balance not enouth");817 ensure!(amount >= value.into(),"Item balance not enouth");
629818
630 // update balance819 // update balance
631 let balance_old_owner = <Balance<T>>::get(collection_id, item.owner.clone()).checked_sub(value).unwrap();820 let balance_old_owner = <Balance<T>>::get(collection_id, item.owner.clone()).checked_sub(value).unwrap();
637 let old_owner = item.owner.clone();826 let old_owner = item.owner.clone();
638 let new_owner_has_account = full_item.owner.iter().any(|i| i.owner == new_owner);827 let new_owner_has_account = full_item.owner.iter().any(|i| i.owner == new_owner);
639
640 // transfer
641 if amount == value.into() && !new_owner_has_account828 let val64 = value.into();
829
830 // transfer
831 if amount == val64 && !new_owner_has_account
642 {832 {
643 // change owner833 // change owner
644 // new owner do not have account834 // new owner do not have account
652 else842 else
653 {843 {
654 let mut new_full_item = full_item.clone();844 let mut new_full_item = full_item.clone();
655 new_full_item.owner.iter_mut().find(|i| i.owner == owner).unwrap().fraction -= amount;845 new_full_item.owner.iter_mut().find(|i| i.owner == owner).unwrap().fraction -= val64;
656846
657 // separate amount847 // separate amount
658 if new_owner_has_account {848 if new_owner_has_account {
659 // new owner has account849 // new owner has account
660 new_full_item.owner.iter_mut().find(|i| i.owner == new_owner).unwrap().fraction += amount;850 new_full_item.owner.iter_mut().find(|i| i.owner == new_owner).unwrap().fraction += val64;
661 }851 }
662 else852 else
663 {853 {
664 // new owner do not have account854 // new owner do not have account
665 new_full_item.owner.push(Ownership { owner: new_owner.clone(), fraction: amount});855 new_full_item.owner.push(Ownership { owner: new_owner.clone(), fraction: val64});
666 Self::add_token_index(collection_id, item_id, new_owner.clone())?;856 Self::add_token_index(collection_id, item_id, new_owner.clone())?;
667 }857 }
668858
672 Ok(())862 Ok(())
673 }863 }
674
675 fn add_nft_item(item: NftItemType<T::AccountId>) -> DispatchResult {
676
677 let current_index = <ItemListIndex>::get(item.collection)
678 .checked_add(1)
679 .expect("Item list index id error");
680
681 Self::add_token_index(item.collection, current_index, item.owner.clone())?;
682
683 <ItemListIndex>::insert(item.collection, current_index);
684 <NftItemList<T>>::insert(item.collection, current_index, item);
685
686 // Update balance
687 let new_balance = <Balance<T>>::get(item.collection, item.owner.clone()).checked_add(1).unwrap();
688 <Balance<T>>::insert(item.collection_id, item.owner.clone(), new_balance);
689
690 Ok(())
691 }
692
693 fn burn_nft_item(collection_id: u64, item_id: u64) -> DispatchResult {
694
695 let item = <NftItemList<T>>::get(collection_id, item_id);
696 Self::remove_token_index(collection_id, item_id, item.owner.clone())?;
697
698 // update balance
699 let new_balance = <Balance<T>>::get(collection_id, item.owner.clone()).checked_sub(1).unwrap();
700 <Balance<T>>::insert(collection_id, item.owner.clone(), new_balance);
701 <NftItemList<T>>::remove(collection_id, item_id);
702
703 Ok(())
704 }
705864
706 fn transfer_nft(collection_id: u64, item_id: u64, sender: T::AccountId, new_owner: T::AccountId) -> DispatchResult {865 fn transfer_nft(collection_id: u64, item_id: u64, sender: T::AccountId, new_owner: T::AccountId) -> DispatchResult {
707866
722 <NftItemList<T>>::insert(collection_id, item_id, item);881 <NftItemList<T>>::insert(collection_id, item_id, item);
723882
724 // update index collection883 // update index collection
725 Self::move_token_index(collection_id, item_id, old_owner, new_owner.clone())?;884 Self::move_token_index(collection_id, item_id, old_owner.clone(), new_owner.clone())?;
726885
727 // reset approved list886 // reset approved list
728 let itm: Vec<T::AccountId> = Vec::new();
729 <ApprovedList<T>>::insert(collection_id, item_id, itm);887 <ApprovedList<T>>::remove(collection_id, (item_id, old_owner));
730
731 Ok(())888 Ok(())
732 }889 }
modifiedpallets/nft/src/tests.rsdiffbeforeafterboth
--- 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<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);
 
-        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<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 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<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);
 
-        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<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);
 
-        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<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);
 
-        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<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);
 
-        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<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);
 
-        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<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);
 
-        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<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);
 
-        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<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);
 
-        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<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 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<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 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<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 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<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 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<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 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<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 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<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 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<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 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<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 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<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 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<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 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<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 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<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 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<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 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<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 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<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 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);
+//     });
+// }