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

difftreelog

Merge pull request #4 from usetech-llc/release/v1.0.1

str-mv2020-09-22parents: #357788d #8d30d14.patch.diff
in: master
Release/v1.0.1

10 files changed

modifiedREADME.mddiffbeforeafterboth
--- a/README.md
+++ b/README.md
@@ -171,6 +171,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",
modifiednode/src/cli.rsdiffbeforeafterboth
--- a/node/src/cli.rs
+++ b/node/src/cli.rs
@@ -3,9 +3,9 @@
 
 #[derive(Debug, StructOpt)]
 pub struct Cli {
-	#[structopt(subcommand)]
-	pub subcommand: Option<Subcommand>,
+    #[structopt(subcommand)]
+    pub subcommand: Option<Subcommand>,
 
-	#[structopt(flatten)]
-	pub run: RunCmd,
+    #[structopt(flatten)]
+    pub run: RunCmd,
 }
modifiednode/src/command.rsdiffbeforeafterboth
--- a/node/src/command.rs
+++ b/node/src/command.rs
@@ -21,61 +21,57 @@
 use sc_cli::SubstrateCli;
 
 impl SubstrateCli for Cli {
-	fn impl_name() -> &'static str {
-		"Substrate Node"
-	}
+    fn impl_name() -> &'static str {
+        "Substrate Node"
+    }
 
-	fn impl_version() -> &'static str {
-		env!("SUBSTRATE_CLI_IMPL_VERSION")
-	}
+    fn impl_version() -> &'static str {
+        env!("SUBSTRATE_CLI_IMPL_VERSION")
+    }
 
-	fn description() -> &'static str {
-		env!("CARGO_PKG_DESCRIPTION")
-	}
+    fn description() -> &'static str {
+        env!("CARGO_PKG_DESCRIPTION")
+    }
 
-	fn author() -> &'static str {
-		env!("CARGO_PKG_AUTHORS")
-	}
+    fn author() -> &'static str {
+        env!("CARGO_PKG_AUTHORS")
+    }
 
-	fn support_url() -> &'static str {
-		"support.anonymous.an"
-	}
+    fn support_url() -> &'static str {
+        "support.anonymous.an"
+    }
 
-	fn copyright_start_year() -> i32 {
-		2017
-	}
+    fn copyright_start_year() -> i32 {
+        2017
+    }
 
-	fn executable_name() -> &'static str {
-		env!("CARGO_PKG_NAME")
-	}
+    fn executable_name() -> &'static str {
+        env!("CARGO_PKG_NAME")
+    }
 
-	fn load_spec(&self, id: &str) -> Result<Box<dyn sc_service::ChainSpec>, String> {
-		Ok(match id {
-			"dev" => Box::new(chain_spec::development_config()),
-			"" | "local" => Box::new(chain_spec::local_testnet_config()),
-			path => Box::new(chain_spec::ChainSpec::from_json_file(
-				std::path::PathBuf::from(path),
-			)?),
-		})
-	}
+    fn load_spec(&self, id: &str) -> Result<Box<dyn sc_service::ChainSpec>, String> {
+        Ok(match id {
+            "dev" => Box::new(chain_spec::development_config()),
+            "" | "local" => Box::new(chain_spec::local_testnet_config()),
+            path => Box::new(chain_spec::ChainSpec::from_json_file(
+                std::path::PathBuf::from(path),
+            )?),
+        })
+    }
 }
 
 /// Parse and run command line arguments
 pub fn run() -> sc_cli::Result<()> {
-	let cli = Cli::from_args();
+    let cli = Cli::from_args();
 
-	match &cli.subcommand {
-		Some(subcommand) => {
-			let runner = cli.create_runner(subcommand)?;
-			runner.run_subcommand(subcommand, |config| Ok(new_full_start!(config).0))
-		}
-		None => {
-			let runner = cli.create_runner(&cli.run)?;
-			runner.run_node(
-				service::new_light,
-				service::new_full,
-				nft_runtime::VERSION
-			)
-		}
-	}
-}
\ No newline at end of file
+    match &cli.subcommand {
+        Some(subcommand) => {
+            let runner = cli.create_runner(subcommand)?;
+            runner.run_subcommand(subcommand, |config| Ok(new_full_start!(config).0))
+        }
+        None => {
+            let runner = cli.create_runner(&cli.run)?;
+            runner.run_node(service::new_light, service::new_full, nft_runtime::VERSION)
+        }
+    }
+}
modifiednode/src/main.rsdiffbeforeafterboth
--- a/node/src/main.rs
+++ b/node/src/main.rs
@@ -8,5 +8,5 @@
 mod command;
 
 fn main() -> sc_cli::Result<()> {
-	command::run()
+    command::run()
 }
modifiednode/src/service.rsdiffbeforeafterboth
--- a/node/src/service.rs
+++ b/node/src/service.rs
@@ -188,7 +188,7 @@
             prometheus_registry: service.prometheus_registry(),
             shared_voter_state: SharedVoterState::empty(),
         };
-        
+
         // the GRANDPA voter task is considered infallible, i.e.
         // if it fails we take down the service with it.
         service.spawn_essential_task_handle().spawn_blocking(
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -2,34 +2,37 @@
 
 /// For more guidance on Substrate FRAME, see the example pallet
 /// https://github.com/paritytech/substrate/blob/master/frame/example/src/lib.rs
-
 use codec::{Decode, Encode};
 pub use frame_support::{
-    decl_event, decl_module, decl_storage,
-    construct_runtime, parameter_types,
-    traits::{Currency, Get, ExistenceRequirement, KeyOwnerProofSystem, OnUnbalanced, Randomness, WithdrawReason, Imbalance},
+    construct_runtime, decl_event, decl_module, decl_storage,
+    dispatch::DispatchResult,
+    ensure, parameter_types,
+    traits::{
+        Currency, ExistenceRequirement, Get, Imbalance, KeyOwnerProofSystem, OnUnbalanced,
+        Randomness, WithdrawReason,
+    },
     weights::{
-        DispatchInfo, PostDispatchInfo, constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
-        IdentityFee, Weight, WeightToFeePolynomial, GetDispatchInfo, Pays,
+        constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
+        DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,
+        WeightToFeePolynomial,
     },
-    StorageValue,
-    dispatch::DispatchResult, 
-    IsSubType,
-    ensure
+    IsSubType, StorageValue,
 };
 
 use frame_system::{self as system, ensure_signed};
 use sp_runtime::sp_std::prelude::Vec;
-use sp_std::prelude::*;
 use sp_runtime::{
-	FixedU128, FixedPointOperand, 
-	transaction_validity::{
-		TransactionPriority, ValidTransaction, InvalidTransaction, TransactionValidityError, TransactionValidity
-	},
-	traits::{
-        Saturating, Dispatchable, DispatchInfoOf, PostDispatchInfoOf, SignedExtension, Zero, SaturatedConversion,
-	},
+    traits::{
+        DispatchInfoOf, Dispatchable, PostDispatchInfoOf, SaturatedConversion, Saturating,
+        SignedExtension, Zero,
+    },
+    transaction_validity::{
+        InvalidTransaction, TransactionPriority, TransactionValidity, TransactionValidityError,
+        ValidTransaction,
+    },
+    FixedPointOperand, FixedU128,
 };
+use sp_std::prelude::*;
 
 #[cfg(test)]
 mod mock;
@@ -45,11 +48,11 @@
     // decimal points
     Fungible(u32),
     // custom data size and decimal points
-	ReFungible(u32, u32),
+    ReFungible(u32, u32),
 }
 
 impl Into<u8> for CollectionMode {
-    fn into(self) -> u8{
+    fn into(self) -> u8 {
         match self {
             CollectionMode::Invalid => 0,
             CollectionMode::NFT(_) => 1,
@@ -62,17 +65,25 @@
 #[derive(Encode, Decode, Debug, Clone, PartialEq)]
 pub enum AccessMode {
     Normal,
-	WhiteList,
+    WhiteList,
 }
-impl Default for AccessMode { fn default() -> Self { Self::Normal } }
+impl Default for AccessMode {
+    fn default() -> Self {
+        Self::Normal
+    }
+}
 
-impl Default for CollectionMode { fn default() -> Self { Self::Invalid } }
+impl Default for CollectionMode {
+    fn default() -> Self {
+        Self::Invalid
+    }
+}
 
 #[derive(Encode, Decode, Default, Clone, PartialEq)]
 #[cfg_attr(feature = "std", derive(Debug))]
 pub struct Ownership<AccountId> {
     pub owner: AccountId,
-    pub fraction: u128
+    pub fraction: u128,
 }
 
 #[derive(Encode, Decode, Default, Clone, PartialEq)]
@@ -87,7 +98,7 @@
     pub token_prefix: Vec<u8>, // 16 include null escape char
     pub custom_data_size: u32,
     pub offchain_schema: Vec<u8>,
-    pub sponsor: AccountId,    // Who pays fees. If set to default address, the fees are applied to the transaction sender
+    pub sponsor: AccountId, // Who pays fees. If set to default address, the fees are applied to the transaction sender
     pub unconfirmed_sponsor: AccountId, // Sponsor address that has not yet confirmed sponsorship
 }
 
@@ -122,31 +133,56 @@
     pub data: Vec<u8>,
 }
 
+#[derive(Encode, Decode, Default, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Debug))]
+pub struct ApprovePermissions<AccountId> {
+    pub approved: AccountId,
+    pub amount: u64,
+}
+
+#[derive(Encode, Decode, Default, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Debug))]
+pub struct VestingItem<AccountId, Moment> {
+    pub sender: AccountId,
+    pub recipient: AccountId,
+    pub collection_id: u64,
+    pub item_id: u64,
+    pub amount: u64,
+    pub vesting_date: Moment,
+}
+
 pub trait Trait: system::Trait {
     type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
-
 }
 
 decl_storage! {
     trait Store for Module<T: Trait> as Nft {
 
         // Private members
+        NextCollectionID: u64;
         CreatedCollectionCount: u64;
+        ChainVersion: u64;
         ItemListIndex: map hasher(blake2_128_concat) u64 => u64;
 
         pub Collection get(fn collection): map hasher(identity) u64 => CollectionType<T::AccountId>;
         pub AdminList get(fn admin_list_collection): map hasher(identity) u64 => Vec<T::AccountId>;
         pub WhiteList get(fn white_list): map hasher(identity) u64 => Vec<T::AccountId>;
 
-        // 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<T::AccountId>;
 
-        // 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<ApprovePermissions<T::AccountId>>;
+
+        /// Item collections
         pub NftItemList get(fn nft_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => NftItemType<T::AccountId>;
         pub FungibleItemList get(fn fungible_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => FungibleItemType<T::AccountId>;
         pub ReFungibleItemList get(fn refungible_item_id): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => ReFungibleItemType<T::AccountId>;
 
+        // Active vesting list
+        // pub VestingList get(fn vesting): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) u64 => VestingItem<T::AccountId, T::Moment>;
+
+        /// Index list
         pub AddressTokens get(fn address_tokens): double_map hasher(blake2_128_concat) u64, hasher(blake2_128_concat) T::AccountId => Vec<u64>;
 
         // Sponsorship
@@ -171,6 +207,18 @@
 
         fn deposit_event() = default;
 
+        fn on_initialize(now: T::BlockNumber) -> Weight {
+
+            if ChainVersion::get() == 0
+            {
+                let value = NextCollectionID::get();
+                CreatedCollectionCount::put(value);
+                ChainVersion::put(2);
+            }
+
+            0
+        }
+
         // Create collection of NFT with given parameters
         //
         // @param customDataSz size of custom data in each collection item
@@ -197,7 +245,7 @@
             };
 
             // check params
-            ensure!(decimal_points <= 4, "decimal_points parameter must be lower than 4"); 
+            ensure!(decimal_points <= 4, "decimal_points parameter must be lower than 4");
 
             let mut name = collection_name.to_vec();
             name.push(0);
@@ -248,6 +296,7 @@
             let sender = ensure_signed(origin)?;
             Self::check_owner_permissions(collection_id, sender)?;
 
+            // TODO Items remove
             <AddressTokens<T>>::remove_prefix(collection_id);
             <ApprovedList<T>>::remove_prefix(collection_id);
             <Balance<T>>::remove_prefix(collection_id);
@@ -351,33 +400,49 @@
 
             Ok(())
         }
-        
+
         #[weight = 0]
         pub fn create_item(origin, collection_id: u64, properties: Vec<u8>, owner: T::AccountId) -> DispatchResult {
 
             let sender = ensure_signed(origin)?;
-
-            // check size
             let target_collection = <Collection<T>>::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 
+            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,
                         data: properties.clone(),
                     };
-    
+
                     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.clone(), fraction: value});
@@ -387,7 +452,7 @@
                         owner: owner_list,
                         data: properties.clone()
                     };
-    
+
                     Self::add_refungible_item(item)?;
                 },
                 _ => { ensure!(1 == 0,"just error"); }
@@ -411,9 +476,10 @@
             }
             let target_collection = <Collection<T>>::get(collection_id);
 
-            match target_collection.mode 
+            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())?,
                 _ => ()
             };
@@ -433,9 +499,10 @@
             let target_collection = <Collection<T>>::get(collection_id);
 
             // TODO: implement other modes
-            match target_collection.mode 
+            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)?,
                 _ => ()
             };
@@ -448,26 +515,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;
+
+            ensure!(Self::is_item_owner(sender.clone(), collection_id, item_id), "Only item owner can call transfer method");
 
-            let list_exists = <ApprovedList<T>>::contains_key(collection_id, item_id);
+            let list_exists = <ApprovedList<T>>::contains_key(collection_id, (item_id, sender.clone()));
             if list_exists {
 
-                let mut list = <ApprovedList<T>>::get(collection_id, item_id);
-                let item_contains = list.contains(&approved.clone());
+                let mut list = <ApprovedList<T>>::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 });
+                    <ApprovedList<T>>::insert(collection_id, (item_id, sender.clone()), list);
                 }
             } else {
 
-                let mut itm = Vec::new();
-                itm.push(approved.clone());
-                <ApprovedList<T>>::insert(collection_id, item_id, itm);
+                let mut list = Vec::new();
+                list.push(ApprovePermissions { approved: approved.clone(), amount: amount });
+                <ApprovedList<T>>::insert(collection_id, (item_id, sender.clone()), list);
             }
 
             Ok(())
@@ -476,27 +543,32 @@
         #[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 = <ApprovedList<T>>::contains_key(collection_id, item_id);
+            let approved_list_exists = <ApprovedList<T>>::contains_key(collection_id, (item_id, from.clone()));
             if approved_list_exists
             {
-                let list_itm = <ApprovedList<T>>::get(collection_id, item_id);
-                approved = list_itm.contains(&recipient.clone());
+                let list_itm = <ApprovedList<T>>::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");
+
+                // remove approve
+                let approve_list: Vec<ApprovePermissions<T::AccountId>> = <ApprovedList<T>>::get(collection_id, (item_id, from.clone()))
+                    .into_iter().filter(|i| i.approved != sender.clone()).collect();
+                <ApprovedList<T>>::insert(collection_id, (item_id, from.clone()), approve_list);
             }
-
-            if !approved
+            else
             {
                 Self::check_owner_or_admin_permissions(collection_id, sender)?;
             }
-            
+
             let target_collection = <Collection<T>>::get(collection_id);
 
             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)?,
                 _ => ()
             };
 
@@ -526,35 +598,182 @@
         ) -> DispatchResult {
             let sender = ensure_signed(origin)?;
             Self::check_owner_or_admin_permissions(collection_id, sender.clone())?;
-            
+
             let mut target_collection = <Collection<T>>::get(collection_id);
             target_collection.offchain_schema = schema;
             <Collection<T>>::insert(collection_id, target_collection);
 
-            Ok(())        
+            Ok(())
         }
     }
 }
 
 impl<T: Trait> Module<T> {
+    fn add_fungible_item(item: FungibleItemType<T::AccountId>) -> DispatchResult {
+        let current_index = <ItemListIndex>::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;
 
-    fn collection_exists(collection_id: u64) -> DispatchResult{
-        ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
+        Self::add_token_index(item.collection, current_index, owner.clone())?;
+
+        <ItemListIndex>::insert(item.collection, current_index);
+        <FungibleItemList<T>>::insert(item.collection, current_index, itemcopy);
+
+        // Update balance
+        let new_balance = <Balance<T>>::get(item.collection, owner.clone())
+            .checked_add(value)
+            .unwrap();
+        <Balance<T>>::insert(item.collection, owner.clone(), new_balance);
+
         Ok(())
     }
 
-    fn check_owner_permissions(collection_id: u64, subject: T::AccountId) -> DispatchResult {
+    fn add_refungible_item(item: ReFungibleItemType<T::AccountId>) -> DispatchResult {
+        let current_index = <ItemListIndex>::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())?;
+
+        <ItemListIndex>::insert(item.collection, current_index);
+        <ReFungibleItemList<T>>::insert(item.collection, current_index, itemcopy);
+
+        // Update balance
+        let new_balance = <Balance<T>>::get(item.collection, owner.clone())
+            .checked_add(value)
+            .unwrap();
+        <Balance<T>>::insert(item.collection, owner.clone(), new_balance);
 
+        Ok(())
+    }
+
+    fn add_nft_item(item: NftItemType<T::AccountId>) -> DispatchResult {
+        let current_index = <ItemListIndex>::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())?;
+
+        <ItemListIndex>::insert(collection_id, current_index);
+        <NftItemList<T>>::insert(collection_id, current_index, item);
+
+        // Update balance
+        let new_balance = <Balance<T>>::get(collection_id, item_owner.clone())
+            .checked_add(1)
+            .unwrap();
+        <Balance<T>>::insert(collection_id, item_owner.clone(), new_balance);
+
+        Ok(())
+    }
+
+    fn burn_refungible_item(
+        collection_id: u64,
+        item_id: u64,
+        owner: T::AccountId,
+    ) -> DispatchResult {
+        ensure!(
+            <ReFungibleItemList<T>>::contains_key(collection_id, item_id),
+            "Item does not exists"
+        );
+        let collection = <ReFungibleItemList<T>>::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
+        <ApprovedList<T>>::remove(collection_id, (item_id, owner.clone()));
+
+        // update balance
+        let new_balance = <Balance<T>>::get(collection_id, item.owner.clone())
+            .checked_sub(item.fraction as u64)
+            .unwrap();
+        <Balance<T>>::insert(collection_id, item.owner.clone(), new_balance);
+
+        <ReFungibleItemList<T>>::remove(collection_id, item_id);
+
+        Ok(())
+    }
+
+    fn burn_nft_item(collection_id: u64, item_id: u64) -> DispatchResult {
+        ensure!(
+            <NftItemList<T>>::contains_key(collection_id, item_id),
+            "Item does not exists"
+        );
+        let item = <NftItemList<T>>::get(collection_id, item_id);
+        Self::remove_token_index(collection_id, item_id, item.owner.clone())?;
+
+        // remove approve list
+        <ApprovedList<T>>::remove(collection_id, (item_id, item.owner.clone()));
+
+        // update balance
+        let new_balance = <Balance<T>>::get(collection_id, item.owner.clone())
+            .checked_sub(1)
+            .unwrap();
+        <Balance<T>>::insert(collection_id, item.owner.clone(), new_balance);
+        <NftItemList<T>>::remove(collection_id, item_id);
+
+        Ok(())
+    }
+
+    fn burn_fungible_item(collection_id: u64, item_id: u64) -> DispatchResult {
+        ensure!(
+            <FungibleItemList<T>>::contains_key(collection_id, item_id),
+            "Item does not exists"
+        );
+        let item = <FungibleItemList<T>>::get(collection_id, item_id);
+        Self::remove_token_index(collection_id, item_id, item.owner.clone())?;
+
+        // remove approve list
+        <ApprovedList<T>>::remove(collection_id, (item_id, item.owner.clone()));
+
+        // update balance
+        let new_balance = <Balance<T>>::get(collection_id, item.owner.clone())
+            .checked_sub(item.value as u64)
+            .unwrap();
+        <Balance<T>>::insert(collection_id, item.owner.clone(), new_balance);
+
+        <FungibleItemList<T>>::remove(collection_id, item_id);
+
+        Ok(())
+    }
+
+    fn collection_exists(collection_id: u64) -> DispatchResult {
+        ensure!(
+            <Collection<T>>::contains_key(collection_id),
+            "This collection does not exist"
+        );
+        Ok(())
+    }
+
+    fn check_owner_permissions(collection_id: u64, subject: T::AccountId) -> DispatchResult {
         Self::collection_exists(collection_id)?;
 
         let target_collection = <Collection<T>>::get(collection_id);
-        ensure!(subject == target_collection.owner, "You do not own this collection");
+        ensure!(
+            subject == target_collection.owner,
+            "You do not own this collection"
+        );
 
         Ok(())
     }
 
-    fn check_owner_or_admin_permissions(collection_id: u64, subject: T::AccountId) -> DispatchResult {
-
+    fn check_owner_or_admin_permissions(
+        collection_id: u64,
+        subject: T::AccountId,
+    ) -> DispatchResult {
         Self::collection_exists(collection_id)?;
 
         let target_collection = <Collection<T>>::get(collection_id);
@@ -563,77 +782,147 @@
         let no_perm_mes = "You do not have permissions to modify this collection";
         let exists = <AdminList<T>>::contains_key(collection_id);
 
-        if !is_owner
-        {
+        if !is_owner {
             ensure!(exists, no_perm_mes);
-            ensure!(<AdminList<T>>::get(collection_id).contains(&subject), no_perm_mes);
+            ensure!(
+                <AdminList<T>>::get(collection_id).contains(&subject),
+                no_perm_mes
+            );
         }
         Ok(())
     }
 
-    fn is_item_owner(subject: T::AccountId, collection_id: u64, item_id: u64) -> bool{
-
+    fn is_item_owner(subject: T::AccountId, collection_id: u64, item_id: u64) -> bool {
         let target_collection = <Collection<T>>::get(collection_id);
 
         match target_collection.mode {
-            CollectionMode::NFT(_) => <NftItemList<T>>::get(collection_id, item_id).owner == subject,
-            CollectionMode::Fungible(_) => <FungibleItemList<T>>::get(collection_id, item_id).owner == subject,
-            CollectionMode::ReFungible(_, _)  => <ReFungibleItemList<T>>::get(collection_id, item_id).owner.iter().any(|i| i.owner == subject),
-            CollectionMode::Invalid => false
+            CollectionMode::NFT(_) => {
+                <NftItemList<T>>::get(collection_id, item_id).owner == subject
+            }
+            CollectionMode::Fungible(_) => {
+                <FungibleItemList<T>>::get(collection_id, item_id).owner == subject
+            }
+            CollectionMode::ReFungible(_, _) => {
+                <ReFungibleItemList<T>>::get(collection_id, item_id)
+                    .owner
+                    .iter()
+                    .any(|i| i.owner == subject)
+            }
+            CollectionMode::Invalid => false,
         }
     }
 
-    fn add_refungible_item(item: ReFungibleItemType<T::AccountId>) -> DispatchResult {
+    fn transfer_fungible(
+        collection_id: u64,
+        item_id: u64,
+        value: u64,
+        owner: T::AccountId,
+        new_owner: T::AccountId,
+    ) -> DispatchResult {
+        let full_item = <FungibleItemList<T>>::get(collection_id, item_id);
+        let amount = full_item.value;
+
+        ensure!(amount >= value.into(), "Item balance not enouth");
+
+        // update balance
+        let balance_old_owner = <Balance<T>>::get(collection_id, owner.clone())
+            .checked_sub(value)
+            .unwrap();
+        <Balance<T>>::insert(collection_id, owner.clone(), balance_old_owner);
+
+        let mut new_owner_account_id = 0;
+        let new_owner_items = <AddressTokens<T>>::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 = <ItemListIndex>::get(item.collection)
-        .checked_add(1)
-        .expect("Item list index id error");
-        let itemcopy = item.clone();
+        // 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();
+            <FungibleItemList<T>>::insert(collection_id, item_id, new_full_item);
+
+            // update balance
+            let balance_new_owner = <Balance<T>>::get(collection_id, new_owner.clone())
+                .checked_add(value)
+                .unwrap();
+            <Balance<T>>::insert(collection_id, new_owner.clone(), balance_new_owner);
+
+            // 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;
 
-        let value = item.owner.first().unwrap().fraction as u64;
-        let owner = item.owner.first().unwrap().owner.clone();
+            // separate amount
+            if new_owner_account_id > 0 {
+                // new owner has account
+                let mut item = <FungibleItemList<T>>::get(collection_id, new_owner_account_id);
+                item.value += val64;
 
-        Self::add_token_index(item.collection, current_index, owner.clone())?;
+                // update balance
+                let balance_new_owner = <Balance<T>>::get(collection_id, new_owner.clone())
+                    .checked_add(value)
+                    .unwrap();
+                <Balance<T>>::insert(collection_id, new_owner.clone(), balance_new_owner);
 
-        <ItemListIndex>::insert(item.collection, current_index);
-        <ReFungibleItemList<T>>::insert(item.collection, current_index, itemcopy);  
-        
-        // Update balance
-       let new_balance = <Balance<T>>::get(item.collection, owner.clone()).checked_add(value).unwrap();
-       <Balance<T>>::insert(item.collection, owner.clone(), new_balance);
+                <FungibleItemList<T>>::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,
+                };
 
-        Ok(())
-    }
+                Self::add_fungible_item(item)?;
+            }
 
-    fn burn_refungible_item(collection_id: u64, item_id: u64, owner: T::AccountId) -> DispatchResult {
-  
-        let collection = <ReFungibleItemList<T>>::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)?;
+            if amount == val64 {
+                Self::remove_token_index(collection_id, item_id, full_item.owner.clone())?;
 
-        // update balance
-        let new_balance = <Balance<T>>::get(collection_id, item.owner.clone()).checked_sub(item.fraction as u64).unwrap();
-        <Balance<T>>::insert(collection_id, item.owner.clone(), new_balance);
+                // remove approve list
+                <ApprovedList<T>>::remove(collection_id, (item_id, full_item.owner.clone()));
+                <FungibleItemList<T>>::remove(collection_id, item_id);
+            }
 
-        // TODO
-        <ReFungibleItemList<T>>::remove(collection_id, item_id);
+            <FungibleItemList<T>>::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 {
-
+    fn transfer_refungible(
+        collection_id: u64,
+        item_id: u64,
+        value: u64,
+        owner: T::AccountId,
+        new_owner: T::AccountId,
+    ) -> DispatchResult {
         let full_item = <ReFungibleItemList<T>>::get(collection_id, item_id);
-        let item = full_item.owner.iter().filter(|i| i.owner == owner).next().unwrap();
+        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 = <Balance<T>>::get(collection_id, item.owner.clone()).checked_sub(value).unwrap();
+        let balance_old_owner = <Balance<T>>::get(collection_id, item.owner.clone())
+            .checked_sub(value)
+            .unwrap();
         <Balance<T>>::insert(collection_id, item.owner.clone(), balance_old_owner);
 
-        let balance_new_owner = <Balance<T>>::get(collection_id, new_owner.clone()).checked_add(value).unwrap();
+        let balance_new_owner = <Balance<T>>::get(collection_id, new_owner.clone())
+            .checked_add(value)
+            .unwrap();
         <Balance<T>>::insert(collection_id, new_owner.clone(), balance_new_owner);
 
         let old_owner = item.owner.clone();
@@ -641,83 +930,75 @@
         let val64 = value.into();
 
         // transfer
-        if amount == val64 && !new_owner_has_account
-        {
+        if amount == val64 && !new_owner_has_account {
             // change owner
             // new owner do not have account
             let mut new_full_item = full_item.clone();
-            new_full_item.owner.iter_mut().find(|i| i.owner == owner).unwrap().owner = new_owner.clone();
+            new_full_item
+                .owner
+                .iter_mut()
+                .find(|i| i.owner == owner)
+                .unwrap()
+                .owner = new_owner.clone();
             <ReFungibleItemList<T>>::insert(collection_id, item_id, new_full_item);
 
             // update index collection
             Self::move_token_index(collection_id, item_id, old_owner.clone(), new_owner.clone())?;
-        }
-        else
-        {
+        } else {
             let mut new_full_item = full_item.clone();
-            new_full_item.owner.iter_mut().find(|i| i.owner == owner).unwrap().fraction -= val64;
+            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 += val64;
-            }
-            else
-            {
+                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: val64});
+                new_full_item.owner.push(Ownership {
+                    owner: new_owner.clone(),
+                    fraction: val64,
+                });
                 Self::add_token_index(collection_id, item_id, new_owner.clone())?;
             }
 
             <ReFungibleItemList<T>>::insert(collection_id, item_id, new_full_item);
         }
-
-        Ok(())
-    }
-    
-    fn add_nft_item(item: NftItemType<T::AccountId>) -> DispatchResult {
-
-        let current_index = <ItemListIndex>::get(item.collection)
-        .checked_add(1)
-        .expect("Item list index id error");
-        let itemcopy = item.clone();
-
-        Self::add_token_index(item.collection, current_index, item.owner.clone())?;
-
-        <ItemListIndex>::insert(item.collection, current_index);
-        <NftItemList<T>>::insert(item.collection, current_index, item);
 
-        // Update balance
-        let new_balance = <Balance<T>>::get(itemcopy.collection, itemcopy.owner.clone()).checked_add(1).unwrap();
-        <Balance<T>>::insert(itemcopy.collection, itemcopy.owner.clone(), new_balance);
-
         Ok(())
     }
 
-    fn burn_nft_item(collection_id: u64, item_id: u64) -> DispatchResult {
-  
-        let item = <NftItemList<T>>::get(collection_id, item_id);
-        Self::remove_token_index(collection_id, item_id, item.owner.clone())?;
-
-        // update balance
-        let new_balance = <Balance<T>>::get(collection_id, item.owner.clone()).checked_sub(1).unwrap();
-        <Balance<T>>::insert(collection_id, item.owner.clone(), new_balance);
-        <NftItemList<T>>::remove(collection_id, item_id);
-
-        Ok(())
-    }
-
-    fn transfer_nft(collection_id: u64, item_id: u64, sender: T::AccountId, new_owner: T::AccountId) -> DispatchResult {
-
+    fn transfer_nft(
+        collection_id: u64,
+        item_id: u64,
+        sender: T::AccountId,
+        new_owner: T::AccountId,
+    ) -> DispatchResult {
         let mut item = <NftItemList<T>>::get(collection_id, item_id);
 
-        ensure!(sender == item.owner,"sender parameter and item owner must be equal");
+        ensure!(
+            sender == item.owner,
+            "sender parameter and item owner must be equal"
+        );
 
         // update balance
-        let balance_old_owner = <Balance<T>>::get(collection_id, item.owner.clone()).checked_sub(1).unwrap();
+        let balance_old_owner = <Balance<T>>::get(collection_id, item.owner.clone())
+            .checked_sub(1)
+            .unwrap();
         <Balance<T>>::insert(collection_id, item.owner.clone(), balance_old_owner);
 
-        let balance_new_owner = <Balance<T>>::get(collection_id, new_owner.clone()).checked_add(1).unwrap();
+        let balance_new_owner = <Balance<T>>::get(collection_id, new_owner.clone())
+            .checked_add(1)
+            .unwrap();
         <Balance<T>>::insert(collection_id, new_owner.clone(), balance_new_owner);
 
         // change owner
@@ -726,12 +1007,10 @@
         <NftItemList<T>>::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<T::AccountId> = Vec::new();
-        <ApprovedList<T>>::insert(collection_id, item_id, itm);
-
+        <ApprovedList<T>>::remove(collection_id, (item_id, old_owner));
         Ok(())
     }
 
@@ -786,7 +1065,6 @@
         Ok(())
     }
 }
-
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // Economic models
@@ -794,65 +1072,70 @@
 /// Fee multiplier.
 pub type Multiplier = FixedU128;
 
-type BalanceOf<T> =
-	<<T as transaction_payment::Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::Balance;
+type BalanceOf<T> = <<T as transaction_payment::Trait>::Currency as Currency<
+    <T as system::Trait>::AccountId,
+>>::Balance;
 type NegativeImbalanceOf<T> = <<T as transaction_payment::Trait>::Currency as Currency<
-	<T as system::Trait>::AccountId,>>::NegativeImbalance;
-
-
+    <T as system::Trait>::AccountId,
+>>::NegativeImbalance;
 
 /// Require the transactor pay for themselves and maybe include a tip to gain additional priority
 /// in the queue.
 #[derive(Encode, Decode, Clone, Eq, PartialEq)]
-pub struct ChargeTransactionPayment<T: transaction_payment::Trait + Send + Sync>(#[codec(compact)] BalanceOf<T>);
+pub struct ChargeTransactionPayment<T: transaction_payment::Trait + Send + Sync>(
+    #[codec(compact)] BalanceOf<T>,
+);
 
-impl<T:Trait + transaction_payment::Trait + Send + Sync> sp_std::fmt::Debug for ChargeTransactionPayment<T> {
-	#[cfg(feature = "std")]
-	fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
-		write!(f, "ChargeTransactionPayment<{:?}>", self.0)
-	}
-	#[cfg(not(feature = "std"))]
-	fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
-		Ok(())
-	}
+impl<T: Trait + transaction_payment::Trait + Send + Sync> sp_std::fmt::Debug
+    for ChargeTransactionPayment<T>
+{
+    #[cfg(feature = "std")]
+    fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
+        write!(f, "ChargeTransactionPayment<{:?}>", self.0)
+    }
+    #[cfg(not(feature = "std"))]
+    fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
+        Ok(())
+    }
 }
 
-impl<T:Trait + transaction_payment::Trait + Send + Sync> ChargeTransactionPayment<T> where
-	T::Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo> + IsSubType<Module<T>, T>,
-	BalanceOf<T>: Send + Sync + FixedPointOperand,
+impl<T: Trait + transaction_payment::Trait + Send + Sync> ChargeTransactionPayment<T>
+where
+    T::Call:
+        Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType<Module<T>, T>,
+    BalanceOf<T>: Send + Sync + FixedPointOperand,
 {
-	/// utility constructor. Used only in client/factory code.
-	pub fn from(fee: BalanceOf<T>) -> Self {
-		Self(fee)
-	}
+    /// utility constructor. Used only in client/factory code.
+    pub fn from(fee: BalanceOf<T>) -> Self {
+        Self(fee)
+    }
 
     pub fn traditional_fee(
         len: usize,
         info: &DispatchInfoOf<T::Call>,
         tip: BalanceOf<T>,
-    ) -> BalanceOf<T> where
-        T::Call: Dispatchable<Info=DispatchInfo>,
+    ) -> BalanceOf<T>
+    where
+        T::Call: Dispatchable<Info = DispatchInfo>,
     {
         <transaction_payment::Module<T>>::compute_fee(len as u32, info, tip)
     }
 
-	fn withdraw_fee(
-		&self,
+    fn withdraw_fee(
+        &self,
         who: &T::AccountId,
         call: &T::Call,
-		info: &DispatchInfoOf<T::Call>,
-		len: usize,
-	) -> Result<(BalanceOf<T>, Option<NegativeImbalanceOf<T>>), TransactionValidityError> {
+        info: &DispatchInfoOf<T::Call>,
+        len: usize,
+    ) -> Result<(BalanceOf<T>, Option<NegativeImbalanceOf<T>>), TransactionValidityError> {
         let tip = self.0;
 
         // Set fee based on call type. Creating collection costs 1 Unique.
         // All other transactions have traditional fees so far
         let fee = match call.is_sub_type() {
             Some(Call::create_collection(..)) => <BalanceOf<T>>::from(1_000_000_000),
-            _ => Self::traditional_fee(len, info, tip)
-
-            // Flat fee model, use only for testing purposes
-            // _ => <BalanceOf<T>>::from(100)
+            _ => Self::traditional_fee(len, info, tip), // Flat fee model, use only for testing purposes
+                                                        // _ => <BalanceOf<T>>::from(100)
         };
 
         // Determine who is paying transaction fee based on ecnomic model
@@ -860,12 +1143,12 @@
         let sponsor: T::AccountId = match call.is_sub_type() {
             Some(Call::create_item(collection_id, _properties, _owner)) => {
                 <Collection<T>>::get(collection_id).sponsor
-            },
+            }
             Some(Call::transfer(_new_owner, collection_id, _item_id, _value)) => {
                 <Collection<T>>::get(collection_id).sponsor
-            },
+            }
 
-            _ => T::AccountId::default()
+            _ => T::AccountId::default(),
         };
 
         let mut who_pays_fee: T::AccountId = sponsor.clone();
@@ -873,98 +1156,109 @@
             who_pays_fee = who.clone();
         }
 
-		// Only mess with balances if fee is not zero.
-		if fee.is_zero() {
-			return Ok((fee, None));
-		}
+        // Only mess with balances if fee is not zero.
+        if fee.is_zero() {
+            return Ok((fee, None));
+        }
 
-		match <T as transaction_payment::Trait>::Currency::withdraw(
-			&who_pays_fee,
-			fee,
-			if tip.is_zero() {
-				WithdrawReason::TransactionPayment.into()
-			} else {
-				WithdrawReason::TransactionPayment | WithdrawReason::Tip
-			},
-			ExistenceRequirement::KeepAlive,
-		) {
-			Ok(imbalance) => Ok((fee, Some(imbalance))),
-			Err(_) => Err(InvalidTransaction::Payment.into()),
-		}
-	}
+        match <T as transaction_payment::Trait>::Currency::withdraw(
+            &who_pays_fee,
+            fee,
+            if tip.is_zero() {
+                WithdrawReason::TransactionPayment.into()
+            } else {
+                WithdrawReason::TransactionPayment | WithdrawReason::Tip
+            },
+            ExistenceRequirement::KeepAlive,
+        ) {
+            Ok(imbalance) => Ok((fee, Some(imbalance))),
+            Err(_) => Err(InvalidTransaction::Payment.into()),
+        }
+    }
 }
 
-impl<T:Trait + transaction_payment::Trait + Send + Sync> SignedExtension for ChargeTransactionPayment<T> where
+impl<T: Trait + transaction_payment::Trait + Send + Sync> SignedExtension
+    for ChargeTransactionPayment<T>
+where
     BalanceOf<T>: Send + Sync + From<u64> + FixedPointOperand,
-    T::Call: Dispatchable<Info=DispatchInfo, PostInfo=PostDispatchInfo> + IsSubType<Module<T>, T>,
+    T::Call:
+        Dispatchable<Info = DispatchInfo, PostInfo = PostDispatchInfo> + IsSubType<Module<T>, T>,
 {
-	const IDENTIFIER: &'static str = "ChargeTransactionPayment";
-	type AccountId = T::AccountId;
-	type Call = T::Call;
-	type AdditionalSigned = ();
-	type Pre = (BalanceOf<T>, Self::AccountId, Option<NegativeImbalanceOf<T>>, BalanceOf<T>);
-	fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> { Ok(()) }
+    const IDENTIFIER: &'static str = "ChargeTransactionPayment";
+    type AccountId = T::AccountId;
+    type Call = T::Call;
+    type AdditionalSigned = ();
+    type Pre = (
+        BalanceOf<T>,
+        Self::AccountId,
+        Option<NegativeImbalanceOf<T>>,
+        BalanceOf<T>,
+    );
+    fn additional_signed(&self) -> sp_std::result::Result<(), TransactionValidityError> {
+        Ok(())
+    }
 
-	fn validate(
-		&self,
-		who: &Self::AccountId,
-		call: &Self::Call,
-		info: &DispatchInfoOf<Self::Call>,
-		len: usize,
-	) -> TransactionValidity {
-		let (fee, _) = self.withdraw_fee(who, call, info, len)?;
+    fn validate(
+        &self,
+        who: &Self::AccountId,
+        call: &Self::Call,
+        info: &DispatchInfoOf<Self::Call>,
+        len: usize,
+    ) -> TransactionValidity {
+        let (fee, _) = self.withdraw_fee(who, call, info, len)?;
 
-		let mut r = ValidTransaction::default();
-		// NOTE: we probably want to maximize the _fee (of any type) per weight unit_ here, which
-		// will be a bit more than setting the priority to tip. For now, this is enough.
-		r.priority = fee.saturated_into::<TransactionPriority>();
-		Ok(r)
-	}
+        let mut r = ValidTransaction::default();
+        // NOTE: we probably want to maximize the _fee (of any type) per weight unit_ here, which
+        // will be a bit more than setting the priority to tip. For now, this is enough.
+        r.priority = fee.saturated_into::<TransactionPriority>();
+        Ok(r)
+    }
 
-	fn pre_dispatch(
-		self,
-		who: &Self::AccountId,
-		call: &Self::Call,
-		info: &DispatchInfoOf<Self::Call>,
-		len: usize
-	) -> Result<Self::Pre, TransactionValidityError> {
-		let (fee, imbalance) = self.withdraw_fee(who, call, info, len)?;
-		Ok((self.0, who.clone(), imbalance, fee))
-	}
+    fn pre_dispatch(
+        self,
+        who: &Self::AccountId,
+        call: &Self::Call,
+        info: &DispatchInfoOf<Self::Call>,
+        len: usize,
+    ) -> Result<Self::Pre, TransactionValidityError> {
+        let (fee, imbalance) = self.withdraw_fee(who, call, info, len)?;
+        Ok((self.0, who.clone(), imbalance, fee))
+    }
 
-	fn post_dispatch(
-		pre: Self::Pre,
-		info: &DispatchInfoOf<Self::Call>,
-		post_info: &PostDispatchInfoOf<Self::Call>,
-		len: usize,
-		_result: &DispatchResult,
-	) -> Result<(), TransactionValidityError> {
-		let (tip, who, imbalance, fee) = pre;
-		if let Some(payed) = imbalance {
-			let actual_fee = <transaction_payment::Module<T>>::compute_actual_fee(
-				len as u32,
-				info,
-				post_info,
-				tip,
-			);
-			let refund = fee.saturating_sub(actual_fee);
-			let actual_payment = match <T as transaction_payment::Trait>::Currency::deposit_into_existing(&who, refund) {
-				Ok(refund_imbalance) => {
-					// The refund cannot be larger than the up front payed max weight.
-					// `PostDispatchInfo::calc_unspent` guards against such a case.
-					match payed.offset(refund_imbalance) {
-						Ok(actual_payment) => actual_payment,
-						Err(_) => return Err(InvalidTransaction::Payment.into()),
-					}
-				}
-				// We do not recreate the account using the refund. The up front payment
-				// is gone in that case.
-				Err(_) => payed,
-			};
-			let imbalances = actual_payment.split(tip);
-			<T as transaction_payment::Trait>::OnTransactionPayment::on_unbalanceds(Some(imbalances.0).into_iter()
-				.chain(Some(imbalances.1)));
-		}
-		Ok(())
-	}
+    fn post_dispatch(
+        pre: Self::Pre,
+        info: &DispatchInfoOf<Self::Call>,
+        post_info: &PostDispatchInfoOf<Self::Call>,
+        len: usize,
+        _result: &DispatchResult,
+    ) -> Result<(), TransactionValidityError> {
+        let (tip, who, imbalance, fee) = pre;
+        if let Some(payed) = imbalance {
+            let actual_fee = <transaction_payment::Module<T>>::compute_actual_fee(
+                len as u32, info, post_info, tip,
+            );
+            let refund = fee.saturating_sub(actual_fee);
+            let actual_payment =
+                match <T as transaction_payment::Trait>::Currency::deposit_into_existing(
+                    &who, refund,
+                ) {
+                    Ok(refund_imbalance) => {
+                        // The refund cannot be larger than the up front payed max weight.
+                        // `PostDispatchInfo::calc_unspent` guards against such a case.
+                        match payed.offset(refund_imbalance) {
+                            Ok(actual_payment) => actual_payment,
+                            Err(_) => return Err(InvalidTransaction::Payment.into()),
+                        }
+                    }
+                    // We do not recreate the account using the refund. The up front payment
+                    // is gone in that case.
+                    Err(_) => payed,
+                };
+            let imbalances = actual_payment.split(tip);
+            <T as transaction_payment::Trait>::OnTransactionPayment::on_unbalanceds(
+                Some(imbalances.0).into_iter().chain(Some(imbalances.1)),
+            );
+        }
+        Ok(())
+    }
 }
modifiedpallets/nft/src/mock.rsdiffbeforeafterboth
--- a/pallets/nft/src/mock.rs
+++ b/pallets/nft/src/mock.rs
@@ -1,19 +1,19 @@
 // Creating mock runtime here
 
 use crate::{Module, Trait};
+use frame_support::{
+    impl_outer_origin, parameter_types,
+    weights::{
+        constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight},
+        Weight,
+    },
+};
 use frame_system as system;
 use sp_core::H256;
 use sp_runtime::{
     testing::Header,
     traits::{BlakeTwo256, IdentityLookup, Saturating},
     Perbill,
-};
-use frame_support::{
-    parameter_types, impl_outer_origin,
-    weights::{
-        constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight},
-        Weight,
-    },
 };
 
 impl_outer_origin! {
@@ -49,9 +49,9 @@
     type MaximumBlockWeight = MaximumBlockWeight;
     type MaximumBlockLength = MaximumBlockLength;
     type AvailableBlockRatio = AvailableBlockRatio;
-    type BaseCallFilter = (); 
-    type DbWeight = RocksDbWeight; 
-    type BlockExecutionWeight = BlockExecutionWeight; 
+    type BaseCallFilter = ();
+    type DbWeight = RocksDbWeight;
+    type BlockExecutionWeight = BlockExecutionWeight;
     type ExtrinsicBaseWeight = ExtrinsicBaseWeight;
     type MaximumExtrinsicWeight = MaximumExtrinsicWeight;
     type Version = ();
modifiedpallets/nft/src/tests.rsdiffbeforeafterboth
1// Tests to be written here1// Tests to be written here
2use crate::mock::*;2use crate::mock::*;
3use crate::{CollectionMode, Ownership};3use crate::{ApprovePermissions, CollectionMode, Ownership};
4use frame_support::{assert_noop, assert_ok};4use frame_support::{assert_noop, assert_ok};
55
6#[test]6#[test]
52 });69 });
53}70}
71
72#[test]
73fn create_fungible_item() {
74 new_test_ext().execute_with(|| {
75 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
76 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
77 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
78 let mode: CollectionMode = CollectionMode::Fungible(3);
79
80 let origin1 = Origin::signed(1);
81 assert_ok!(TemplateModule::create_collection(
82 origin1.clone(),
83 col_name1.clone(),
84 col_desc1.clone(),
85 token_prefix1.clone(),
86 mode
87 ));
88 assert_eq!(TemplateModule::collection(1).owner, 1);
89
90 assert_ok!(TemplateModule::create_item(
91 origin1.clone(),
92 1,
93 [].to_vec(),
94 1
95 ));
96 assert_eq!(TemplateModule::fungible_item_id(1, 1).owner, 1);
97 assert_eq!(TemplateModule::balance_count(1, 1), 1000);
98 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
99 });
100}
101
102#[test]
103fn transfer_fungible_item() {
104 new_test_ext().execute_with(|| {
105 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
106 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
107 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
108 let mode: CollectionMode = CollectionMode::Fungible(3);
109
110 let origin1 = Origin::signed(1);
111 let origin2 = Origin::signed(2);
112 assert_ok!(TemplateModule::create_collection(
113 origin1.clone(),
114 col_name1.clone(),
115 col_desc1.clone(),
116 token_prefix1.clone(),
117 mode
118 ));
119 assert_eq!(TemplateModule::collection(1).owner, 1);
120
121 assert_ok!(TemplateModule::create_item(
122 origin1.clone(),
123 1,
124 [].to_vec(),
125 1
126 ));
127 assert_eq!(TemplateModule::fungible_item_id(1, 1).owner, 1);
128 assert_eq!(TemplateModule::balance_count(1, 1), 1000);
129 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
130
131 // change owner scenario
132 assert_ok!(TemplateModule::transfer(origin1.clone(), 2, 1, 1, 1000));
133 assert_eq!(TemplateModule::fungible_item_id(1, 1).owner, 2);
134 assert_eq!(TemplateModule::fungible_item_id(1, 1).value, 1000);
135 assert_eq!(TemplateModule::balance_count(1, 1), 0);
136 assert_eq!(TemplateModule::balance_count(1, 2), 1000);
137 assert_eq!(TemplateModule::address_tokens(1, 1), []);
138 assert_eq!(TemplateModule::address_tokens(1, 2), [1]);
139
140 // split item scenario
141 assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 500));
142 assert_eq!(TemplateModule::fungible_item_id(1, 1).owner, 2);
143 assert_eq!(TemplateModule::fungible_item_id(1, 2).owner, 3);
144 assert_eq!(TemplateModule::balance_count(1, 2), 500);
145 assert_eq!(TemplateModule::balance_count(1, 3), 500);
146 assert_eq!(TemplateModule::address_tokens(1, 2), [1]);
147 assert_eq!(TemplateModule::address_tokens(1, 3), [2]);
148
149 // split item and new owner has account scenario
150 assert_ok!(TemplateModule::transfer(origin2.clone(), 3, 1, 1, 200));
151 assert_eq!(TemplateModule::fungible_item_id(1, 1).value, 300);
152 assert_eq!(TemplateModule::fungible_item_id(1, 2).value, 700);
153 assert_eq!(TemplateModule::balance_count(1, 2), 300);
154 assert_eq!(TemplateModule::balance_count(1, 3), 700);
155 assert_eq!(TemplateModule::address_tokens(1, 2), [1]);
156 assert_eq!(TemplateModule::address_tokens(1, 3), [2]);
157 });
158}
54159
55#[test]160#[test]
56fn transfer_refungible_item() {161fn transfer_refungible_item() {
140 });292 });
141}293}
142294
143295#[test]
144// #[test]296fn nft_approve_and_transfer_from() {
145// fn create_collection_test() {297 new_test_ext().execute_with(|| {
146// new_test_ext().execute_with(|| {298 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
147// let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();299 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
148// let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();300 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
149// let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();301 let mode: CollectionMode = CollectionMode::NFT(2000);
150302
151// let size = 1024;303 let origin1 = Origin::signed(1);
152// let origin1 = Origin::signed(1);304 let origin2 = Origin::signed(2);
153// assert_ok!(TemplateModule::create_collection(305 assert_ok!(TemplateModule::create_collection(
154// origin1.clone(),306 origin1.clone(),
155// col_name1.clone(),307 col_name1.clone(),
156// col_desc1.clone(),308 col_desc1.clone(),
157// token_prefix1.clone(),309 token_prefix1.clone(),
158// size310 mode
159// ));311 ));
160// assert_eq!(TemplateModule::collection(1).owner, 1);312 assert_eq!(TemplateModule::collection(1).owner, 1);
161// });313
162// }314 assert_ok!(TemplateModule::create_item(
163315 origin1.clone(),
164// #[test]316 1,
165// fn change_collection_owner() {317 [1, 2, 3].to_vec(),
166// new_test_ext().execute_with(|| {318 1
167// let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();319 ));
168// let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();320 assert_eq!(TemplateModule::nft_item_id(1, 1).data, [1, 2, 3].to_vec());
169// let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();321 assert_eq!(TemplateModule::balance_count(1, 1), 1);
170322 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
171// let size = 1024;323
172// let origin1 = Origin::signed(1);324 assert_noop!(
173325 TemplateModule::transfer_from(origin2.clone(), 1, 3, 1, 1, 1),
174// assert_ok!(TemplateModule::create_collection(326 "You do not have permissions to modify this collection"
175// origin1.clone(),327 );
176// col_name1.clone(),328
177// col_desc1.clone(),329 // do approve
178// token_prefix1.clone(),330 assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1));
179// size331 assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 1);
180// ));332 assert_ok!(TemplateModule::approve(origin1.clone(), 10, 1, 1));
181// assert_ok!(TemplateModule::change_collection_owner(333 assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 2);
182// origin1.clone(),334 assert_eq!(
183// 1,335 TemplateModule::approved(1, (1, 1))[0],
184// 2336 ApprovePermissions {
185// ));337 approved: 2,
186// assert_eq!(TemplateModule::collection(1).owner, 2);338 amount: 100000000
187// });339 }
188// }340 );
189341
190// #[test]342 assert_ok!(TemplateModule::transfer_from(
191// fn destroy_collection() {343 origin2.clone(),
192// new_test_ext().execute_with(|| {344 1,
193// let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();345 3,
194// let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();346 1,
195// let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();347 1,
196348 1
197// let size = 1024;349 ));
198// let origin1 = Origin::signed(1);350 assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 0);
199351 });
200// assert_ok!(TemplateModule::create_collection(352}
201// origin1.clone(),353
202// col_name1.clone(),354#[test]
203// col_desc1.clone(),355fn refungible_approve_and_transfer_from() {
204// token_prefix1.clone(),356 new_test_ext().execute_with(|| {
205// size357 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
206// ));358 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
207// assert_ok!(TemplateModule::destroy_collection(origin1.clone(), 1));359 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
208// });360 let mode: CollectionMode = CollectionMode::ReFungible(2000, 3);
209// }361
210362 let origin1 = Origin::signed(1);
211// #[test]363 let origin2 = Origin::signed(2);
212// fn create_item() {364 assert_ok!(TemplateModule::create_collection(
213// new_test_ext().execute_with(|| {365 origin1.clone(),
214// let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();366 col_name1.clone(),
215// let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();367 col_desc1.clone(),
216// let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();368 token_prefix1.clone(),
217369 mode
218// let size = 1024;370 ));
219// let origin1 = Origin::signed(1);371 assert_eq!(TemplateModule::collection(1).owner, 1);
220// let origin2 = Origin::signed(2);372
221373 assert_ok!(TemplateModule::create_item(
222// assert_ok!(TemplateModule::create_collection(374 origin1.clone(),
223// origin1.clone(),375 1,
224// col_name1.clone(),376 [1, 2, 3].to_vec(),
225// col_desc1.clone(),377 1
226// token_prefix1.clone(),378 ));
227// size379 assert_eq!(
228// ));380 TemplateModule::refungible_item_id(1, 1).data,
229// assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2));381 [1, 2, 3].to_vec()
230// assert_ok!(TemplateModule::create_item(382 );
231// origin2.clone(),383 assert_eq!(
232// 1,384 TemplateModule::refungible_item_id(1, 1).owner[0],
233// [1, 1, 1].to_vec()385 Ownership {
234// ));386 owner: 1,
387 fraction: 1000
388 }
389 );
390 assert_eq!(TemplateModule::balance_count(1, 1), 1000);
391 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
392
393 assert_noop!(
394 TemplateModule::transfer_from(origin2.clone(), 1, 3, 1, 1, 1),
395 "You do not have permissions to modify this collection"
396 );
397
398 // do approve
399 assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1));
400 assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 1);
401 assert_ok!(TemplateModule::approve(origin1.clone(), 10, 1, 1));
402 assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 2);
403 assert_eq!(
404 TemplateModule::approved(1, (1, 1))[0],
405 ApprovePermissions {
406 approved: 2,
407 amount: 100000000
408 }
409 );
410
411 assert_ok!(TemplateModule::transfer_from(
412 origin2.clone(),
413 1,
414 3,
415 1,
416 1,
417 100
418 ));
419 assert_eq!(TemplateModule::balance_count(1, 1), 900);
420 assert_eq!(TemplateModule::balance_count(1, 3), 100);
421 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
422 assert_eq!(TemplateModule::address_tokens(1, 3), [1]);
423
424 assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 1);
425 assert_eq!(
426 TemplateModule::approved(1, (1, 1))[0],
427 ApprovePermissions {
428 approved: 10,
429 amount: 100000000
430 }
431 );
432 });
433}
434
435#[test]
436fn fungible_approve_and_transfer_from() {
437 new_test_ext().execute_with(|| {
438 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
439 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
440 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
441 let mode: CollectionMode = CollectionMode::Fungible(3);
442
443 let origin1 = Origin::signed(1);
444 let origin2 = Origin::signed(2);
445 assert_ok!(TemplateModule::create_collection(
446 origin1.clone(),
447 col_name1.clone(),
448 col_desc1.clone(),
449 token_prefix1.clone(),
450 mode
451 ));
452 assert_eq!(TemplateModule::collection(1).owner, 1);
453
454 assert_ok!(TemplateModule::create_item(
455 origin1.clone(),
456 1,
457 [].to_vec(),
458 1
459 ));
460 assert_eq!(TemplateModule::fungible_item_id(1, 1).owner, 1);
461 assert_eq!(TemplateModule::balance_count(1, 1), 1000);
462 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
463
464 assert_noop!(
465 TemplateModule::transfer_from(origin2.clone(), 1, 3, 1, 1, 1),
466 "You do not have permissions to modify this collection"
467 );
468
469 // do approve
470 assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1));
471 assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 1);
472 assert_ok!(TemplateModule::approve(origin1.clone(), 10, 1, 1));
473 assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 2);
474 assert_eq!(
475 TemplateModule::approved(1, (1, 1))[0],
476 ApprovePermissions {
477 approved: 2,
478 amount: 100000000
479 }
480 );
481
482 assert_ok!(TemplateModule::transfer_from(
483 origin2.clone(),
484 1,
485 3,
486 1,
487 1,
488 100
489 ));
490 assert_eq!(TemplateModule::balance_count(1, 1), 900);
491 assert_eq!(TemplateModule::balance_count(1, 3), 100);
492 assert_eq!(TemplateModule::address_tokens(1, 1), [1]);
493 assert_eq!(TemplateModule::address_tokens(1, 3), [2]);
494
495 assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 1);
496 assert_eq!(
497 TemplateModule::approved(1, (1, 1))[0],
498 ApprovePermissions {
499 approved: 10,
500 amount: 100000000
501 }
502 );
503
504 assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1));
505 assert_ok!(TemplateModule::transfer_from(
506 origin2.clone(),
507 1,
508 3,
509 1,
510 1,
511 900
512 ));
513 assert_eq!(TemplateModule::balance_count(1, 1), 0);
514 assert_eq!(TemplateModule::balance_count(1, 3), 1000);
515 assert_eq!(TemplateModule::address_tokens(1, 1), []);
516 assert_eq!(TemplateModule::address_tokens(1, 3), [2]);
517
518 assert_eq!(TemplateModule::approved(1, (1, 1)).len(), 0);
519 });
520}
521
522#[test]
523fn change_collection_owner() {
524 new_test_ext().execute_with(|| {
525 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
526 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
527 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
528 let mode: CollectionMode = CollectionMode::NFT(2000);
529
530 let origin1 = Origin::signed(1);
531 assert_ok!(TemplateModule::create_collection(
532 origin1.clone(),
533 col_name1.clone(),
534 col_desc1.clone(),
535 token_prefix1.clone(),
536 mode
537 ));
538 assert_ok!(TemplateModule::change_collection_owner(
539 origin1.clone(),
540 1,
541 2
542 ));
543 assert_eq!(TemplateModule::collection(1).owner, 2);
544 });
545}
546
547#[test]
548fn destroy_collection() {
549 new_test_ext().execute_with(|| {
550 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
551 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
552 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
553 let mode: CollectionMode = CollectionMode::NFT(2000);
554
555 let origin1 = Origin::signed(1);
556 assert_ok!(TemplateModule::create_collection(
557 origin1.clone(),
558 col_name1.clone(),
559 col_desc1.clone(),
560 token_prefix1.clone(),
561 mode
562 ));
563 assert_ok!(TemplateModule::destroy_collection(origin1.clone(), 1));
564 });
565}
566
567#[test]
568fn burn_nft_item() {
569 new_test_ext().execute_with(|| {
570 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
571 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
572 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
573 let mode: CollectionMode = CollectionMode::NFT(2000);
574
575 let origin1 = Origin::signed(1);
576 let origin2 = Origin::signed(2);
577 assert_ok!(TemplateModule::create_collection(
578 origin1.clone(),
579 col_name1.clone(),
580 col_desc1.clone(),
581 token_prefix1.clone(),
582 mode
583 ));
584 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2));
585 assert_ok!(TemplateModule::create_item(
586 origin2.clone(),
587 1,
588 [1, 2, 3].to_vec(),
589 1
590 ));
591
592 assert_eq!(TemplateModule::nft_item_id(1, 1).data, [1, 2, 3].to_vec());
593
594 // check balance (collection with id = 1, user id = 1)
595 assert_eq!(TemplateModule::balance_count(1, 1), 1);
596
597 // burn item
598 assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1));
599 assert_noop!(
600 TemplateModule::burn_item(origin1.clone(), 1, 1),
601 "Item does not exists"
602 );
603
604 assert_eq!(TemplateModule::balance_count(1, 1), 0);
605 });
606}
607
608#[test]
609fn burn_fungible_item() {
610 new_test_ext().execute_with(|| {
611 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
612 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
613 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
614 let mode: CollectionMode = CollectionMode::Fungible(3);
615
616 let origin1 = Origin::signed(1);
617 let origin2 = Origin::signed(2);
618 assert_ok!(TemplateModule::create_collection(
619 origin1.clone(),
620 col_name1.clone(),
621 col_desc1.clone(),
622 token_prefix1.clone(),
623 mode
624 ));
625 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2));
626 assert_ok!(TemplateModule::create_item(
627 origin2.clone(),
628 1,
629 [].to_vec(),
630 1
631 ));
235632
236// // check balance (collection with id = 1, user id = 2)633 // check balance (collection with id = 1, user id = 1)
237// assert_eq!(TemplateModule::balance_count((1, 2)), 1);634 assert_eq!(TemplateModule::balance_count(1, 1), 1000);
238// });635
239// }636 // burn item
240637 assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1));
241// #[test]638 assert_noop!(
242// fn burn_item() {639 TemplateModule::burn_item(origin1.clone(), 1, 1),
243// new_test_ext().execute_with(|| {640 "Item does not exists"
244// let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();641 );
245// let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();642
246// let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();643 assert_eq!(TemplateModule::balance_count(1, 1), 0);
247644 });
248// let size = 1024;645}
249// let origin1 = Origin::signed(1);646
250// let origin2 = Origin::signed(2);647#[test]
251648fn burn_refungible_item() {
252// assert_ok!(TemplateModule::create_collection(649 new_test_ext().execute_with(|| {
253// origin1.clone(),650 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
254// col_name1.clone(),651 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
255// col_desc1.clone(),652 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
256// token_prefix1.clone(),653 let mode: CollectionMode = CollectionMode::ReFungible(200, 3);
257// size654
258// ));655 let origin1 = Origin::signed(1);
259// assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2));656 let origin2 = Origin::signed(2);
260// assert_ok!(TemplateModule::create_item(657 assert_ok!(TemplateModule::create_collection(
261// origin2.clone(),658 origin1.clone(),
262// 1,659 col_name1.clone(),
263// [1, 1, 1].to_vec()660 col_desc1.clone(),
264// ));661 token_prefix1.clone(),
662 mode
663 ));
664 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2));
665 assert_ok!(TemplateModule::create_item(
666 origin2.clone(),
667 1,
668 [1, 2, 3].to_vec(),
669 1
670 ));
671
672 assert_eq!(
673 TemplateModule::refungible_item_id(1, 1).data,
674 [1, 2, 3].to_vec()
675 );
265676
266// // check balance (collection with id = 1, user id = 2)677 // check balance (collection with id = 1, user id = 2)
267// assert_eq!(TemplateModule::balance_count((1, 2)), 1);678 assert_eq!(TemplateModule::balance_count(1, 1), 1000);
268679
269// // burn item680 // burn item
270// assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1));681 assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1));
271// assert_noop!(682 assert_noop!(
272// TemplateModule::burn_item(origin1.clone(), 1, 1),683 TemplateModule::burn_item(origin1.clone(), 1, 1),
273// "Item does not exists"684 "Item does not exists"
274// );685 );
275686
276// assert_eq!(TemplateModule::balance_count((1, 1)), 0);687 assert_eq!(TemplateModule::balance_count(1, 1), 0);
277// });688 });
278// }689}
279690
280// #[test]691#[test]
281// fn add_collection_admin() {692fn add_collection_admin() {
282// new_test_ext().execute_with(|| {693 new_test_ext().execute_with(|| {
283// let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();694 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
284// let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();695 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
285// let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();696 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
286697 let mode: CollectionMode = CollectionMode::NFT(2000);
287// let size = 1024;698
288// let origin1 = Origin::signed(1);699 let origin1 = Origin::signed(1);
289// let origin2 = Origin::signed(2);700 let origin2 = Origin::signed(2);
290// let origin3 = Origin::signed(3);701 let origin3 = Origin::signed(3);
291702 assert_ok!(TemplateModule::create_collection(
292// assert_ok!(TemplateModule::create_collection(703 origin1.clone(),
293// origin1.clone(),704 col_name1.clone(),
294// col_name1.clone(),705 col_desc1.clone(),
295// col_desc1.clone(),706 token_prefix1.clone(),
296// token_prefix1.clone(),707 mode.clone()
297// size708 ));
298// ));709 assert_ok!(TemplateModule::create_collection(
299// assert_ok!(TemplateModule::create_collection(710 origin2.clone(),
300// origin2.clone(),711 col_name1.clone(),
301// col_name1.clone(),712 col_desc1.clone(),
302// col_desc1.clone(),713 token_prefix1.clone(),
303// token_prefix1.clone(),714 mode.clone()
304// size715 ));
305// ));716 assert_ok!(TemplateModule::create_collection(
306// assert_ok!(TemplateModule::create_collection(717 origin3.clone(),
307// origin3.clone(),718 col_name1.clone(),
308// col_name1.clone(),719 col_desc1.clone(),
309// col_desc1.clone(),720 token_prefix1.clone(),
310// token_prefix1.clone(),721 mode.clone()
311// size722 ));
312// ));723
313724 assert_eq!(TemplateModule::collection(1).owner, 1);
314// assert_eq!(TemplateModule::collection(1).owner, 1);725 assert_eq!(TemplateModule::collection(2).owner, 2);
315// assert_eq!(TemplateModule::collection(2).owner, 2);726 assert_eq!(TemplateModule::collection(3).owner, 3);
316// assert_eq!(TemplateModule::collection(3).owner, 3);727
317728 // collection admin
318// // collection admin729 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2));
319// assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2));730 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 3));
320// assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 3));731
321732 assert_eq!(TemplateModule::admin_list_collection(1).contains(&2), true);
322// assert_eq!(TemplateModule::admin_list_collection(1).contains(&2), true);733 assert_eq!(TemplateModule::admin_list_collection(1).contains(&3), true);
323// assert_eq!(TemplateModule::admin_list_collection(1).contains(&3), true);734 });
324// });735}
325// }736
326737#[test]
327// #[test]738fn remove_collection_admin() {
328// fn remove_collection_admin() {739 new_test_ext().execute_with(|| {
329// new_test_ext().execute_with(|| {740 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
330// let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();741 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
331// let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();742 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
332// let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();743 let mode: CollectionMode = CollectionMode::NFT(2000);
333744
334// let size = 1024;745 let origin1 = Origin::signed(1);
335// let origin1 = Origin::signed(1);746 let origin2 = Origin::signed(2);
336// let origin2 = Origin::signed(2);747 let origin3 = Origin::signed(3);
337// let origin3 = Origin::signed(3);748
338749 assert_ok!(TemplateModule::create_collection(
339// assert_ok!(TemplateModule::create_collection(750 origin1.clone(),
340// origin1.clone(),751 col_name1.clone(),
341// col_name1.clone(),752 col_desc1.clone(),
342// col_desc1.clone(),753 token_prefix1.clone(),
343// token_prefix1.clone(),754 mode.clone()
344// size755 ));
345// ));756 assert_ok!(TemplateModule::create_collection(
346// assert_ok!(TemplateModule::create_collection(757 origin2.clone(),
347// origin2.clone(),758 col_name1.clone(),
348// col_name1.clone(),759 col_desc1.clone(),
349// col_desc1.clone(),760 token_prefix1.clone(),
350// token_prefix1.clone(),761 mode.clone()
351// size762 ));
352// ));763 assert_ok!(TemplateModule::create_collection(
353// assert_ok!(TemplateModule::create_collection(764 origin3.clone(),
354// origin3.clone(),765 col_name1.clone(),
355// col_name1.clone(),766 col_desc1.clone(),
356// col_desc1.clone(),767 token_prefix1.clone(),
357// token_prefix1.clone(),768 mode.clone()
358// size769 ));
359// ));770
360771 assert_eq!(TemplateModule::collection(1).owner, 1);
361// assert_eq!(TemplateModule::collection(1).owner, 1);772 assert_eq!(TemplateModule::collection(2).owner, 2);
362// assert_eq!(TemplateModule::collection(2).owner, 2);773 assert_eq!(TemplateModule::collection(3).owner, 3);
363// assert_eq!(TemplateModule::collection(3).owner, 3);774
364775 // collection admin
365// // collection admin776 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2));
366// assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2));777 assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 3));
367// assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 3));778
368779 assert_eq!(TemplateModule::admin_list_collection(1).contains(&2), true);
369// assert_eq!(TemplateModule::admin_list_collection(1).contains(&2), true);780 assert_eq!(TemplateModule::admin_list_collection(1).contains(&3), true);
370// assert_eq!(TemplateModule::admin_list_collection(1).contains(&3), true);781
371782 // remove admin
372// // remove admin783 assert_ok!(TemplateModule::remove_collection_admin(
373// assert_ok!(TemplateModule::remove_collection_admin(784 origin2.clone(),
374// origin2.clone(),785 1,
375// 1,786 3
376// 3787 ));
377// ));788 assert_eq!(TemplateModule::admin_list_collection(1).contains(&3), false);
378// assert_eq!(TemplateModule::admin_list_collection(1).contains(&3), false);789 });
379// });790}
380// }791
381792#[test]
382// #[test]793fn balance_of() {
383// fn balance_of() {794 new_test_ext().execute_with(|| {
384// new_test_ext().execute_with(|| {795 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
385// let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();796 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
386// let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();797 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
387// let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();798 let nft_mode: CollectionMode = CollectionMode::NFT(2000);
388799 let furg_mode: CollectionMode = CollectionMode::Fungible(3);
389// let size = 1024;800 let refung_mode: CollectionMode = CollectionMode::ReFungible(2000, 3);
390// let origin1 = Origin::signed(1);801
391// let origin2 = Origin::signed(2);802 let origin1 = Origin::signed(1);
392// let origin3 = Origin::signed(3);803
393804 assert_ok!(TemplateModule::create_collection(
394// assert_ok!(TemplateModule::create_collection(805 origin1.clone(),
395// origin1.clone(),806 col_name1.clone(),
396// col_name1.clone(),807 col_desc1.clone(),
397// col_desc1.clone(),808 token_prefix1.clone(),
398// token_prefix1.clone(),809 nft_mode.clone()
399// size810 ));
400// ));811 assert_ok!(TemplateModule::create_collection(
401// assert_ok!(TemplateModule::create_collection(812 origin1.clone(),
402// origin2.clone(),813 col_name1.clone(),
403// col_name1.clone(),814 col_desc1.clone(),
404// col_desc1.clone(),815 token_prefix1.clone(),
405// token_prefix1.clone(),816 furg_mode.clone()
406// size817 ));
407// ));818 assert_ok!(TemplateModule::create_collection(
408// assert_ok!(TemplateModule::create_collection(819 origin1.clone(),
409// origin3.clone(),820 col_name1.clone(),
410// col_name1.clone(),821 col_desc1.clone(),
411// col_desc1.clone(),822 token_prefix1.clone(),
412// token_prefix1.clone(),823 refung_mode.clone()
413// size824 ));
414// ));825
415826 assert_eq!(TemplateModule::collection(1).owner, 1);
416// assert_eq!(TemplateModule::collection(1).owner, 1);827 assert_eq!(TemplateModule::collection(2).owner, 1);
417// assert_eq!(TemplateModule::collection(2).owner, 2);828 assert_eq!(TemplateModule::collection(3).owner, 1);
418// assert_eq!(TemplateModule::collection(3).owner, 3);829
419830 // check balance before
420// // check balance before831 assert_eq!(TemplateModule::balance_count(1, 1), 0);
421// assert_eq!(TemplateModule::balance_count((1, 1)), 0);832 assert_eq!(TemplateModule::balance_count(2, 1), 0);
422833 assert_eq!(TemplateModule::balance_count(3, 1), 0);
423// // create item834
424// assert_ok!(TemplateModule::create_item(835 // create item
425// origin1.clone(),836 assert_ok!(TemplateModule::create_item(
426// 1,837 origin1.clone(),
427// [1, 1, 1].to_vec()838 1,
428// ));839 [1, 1, 1].to_vec(),
840 1
841 ));
842
843 assert_ok!(TemplateModule::create_item(
844 origin1.clone(),
845 2,
846 [].to_vec(),
847 1
848 ));
849
850 assert_ok!(TemplateModule::create_item(
851 origin1.clone(),
852 3,
853 [1, 1, 1].to_vec(),
854 1
855 ));
429856
430// // check balance (collection with id = 1, user id = 2)857 // check balance (collection with id = 1, user id = 1)
431// assert_eq!(TemplateModule::balance_count((1, 1)), 1);858 assert_eq!(TemplateModule::balance_count(1, 1), 1);
432// assert_eq!(TemplateModule::item_id((1, 1)).owner, 1);859 assert_eq!(TemplateModule::balance_count(2, 1), 1000);
433// });860 assert_eq!(TemplateModule::balance_count(3, 1), 1000);
434// }861 assert_eq!(TemplateModule::nft_item_id(1, 1).owner, 1);
435862 assert_eq!(TemplateModule::fungible_item_id(2, 1).owner, 1);
436// #[test]863 assert_eq!(TemplateModule::refungible_item_id(3, 1).owner[0].owner, 1);
437// fn transfer() {864 });
438// new_test_ext().execute_with(|| {865}
439// let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();866
440// let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();867#[test]
441// let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();868fn approve() {
442869 new_test_ext().execute_with(|| {
443// let size = 1024;870 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
444// let origin1 = Origin::signed(1);871 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
445// let origin2 = Origin::signed(2);872 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
446// let origin3 = Origin::signed(3);873 let nft_mode: CollectionMode = CollectionMode::NFT(2000);
447874 let origin1 = Origin::signed(1);
448// assert_ok!(TemplateModule::create_collection(875
449// origin1.clone(),876 assert_ok!(TemplateModule::create_collection(
450// col_name1.clone(),877 origin1.clone(),
451// col_desc1.clone(),878 col_name1.clone(),
452// token_prefix1.clone(),879 col_desc1.clone(),
453// size880 token_prefix1.clone(),
454// ));881 nft_mode.clone()
455// assert_ok!(TemplateModule::create_collection(882 ));
456// origin2.clone(),883
457// col_name1.clone(),884 assert_eq!(TemplateModule::collection(1).owner, 1);
458// col_desc1.clone(),885
459// token_prefix1.clone(),886 // create item
460// size887 assert_ok!(TemplateModule::create_item(
461// ));888 origin1.clone(),
462// assert_ok!(TemplateModule::create_collection(889 1,
463// origin3.clone(),890 [1, 1, 1].to_vec(),
464// col_name1.clone(),891 1
465// col_desc1.clone(),892 ));
466// token_prefix1.clone(),893
467// size
468// ));
469
470// assert_eq!(TemplateModule::collection(1).owner, 1);
471// assert_eq!(TemplateModule::collection(2).owner, 2);
472// assert_eq!(TemplateModule::collection(3).owner, 3);
473
474// // create item
475// assert_ok!(TemplateModule::create_item(
476// origin1.clone(),
477// 1,
478// [1, 1, 1].to_vec()
479// ));
480
481// // transfer
482// assert_ok!(TemplateModule::transfer(origin1.clone(), 1, 1, 2));
483// assert_eq!(TemplateModule::item_id((1, 1)).owner, 2);
484
485// // balance_of check
486// assert_eq!(TemplateModule::balance_count((1, 1)), 0);
487// assert_eq!(TemplateModule::balance_count((1, 2)), 1);
488// });
489// }
490
491// #[test]
492// fn approve() {894 // approve
493// new_test_ext().execute_with(|| {895 assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1));
494// let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();896 assert_eq!(TemplateModule::approved(1, (1, 1))[0].approved, 2);
495// let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();897 });
496// let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();898}
497899
498// let size = 1024;900#[test]
499// let origin1 = Origin::signed(1);901fn transfer_from() {
500// let origin2 = Origin::signed(2);902 new_test_ext().execute_with(|| {
501// let origin3 = Origin::signed(3);903 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
502904 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
503// assert_ok!(TemplateModule::create_collection(905 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
504// origin1.clone(),906 let mode: CollectionMode = CollectionMode::NFT(2000);
505// col_name1.clone(),907 let origin1 = Origin::signed(1);
506// col_desc1.clone(),908 let origin2 = Origin::signed(2);
507// token_prefix1.clone(),909
508// size910 assert_ok!(TemplateModule::create_collection(
509// ));911 origin1.clone(),
510// assert_ok!(TemplateModule::create_collection(912 col_name1.clone(),
511// origin2.clone(),913 col_desc1.clone(),
512// col_name1.clone(),914 token_prefix1.clone(),
513// col_desc1.clone(),915 mode
514// token_prefix1.clone(),916 ));
515// size917
516// ));918 assert_eq!(TemplateModule::collection(1).owner, 1);
517// assert_ok!(TemplateModule::create_collection(919
518// origin3.clone(),920 // create item
519// col_name1.clone(),921 assert_ok!(TemplateModule::create_item(
520// col_desc1.clone(),922 origin1.clone(),
521// token_prefix1.clone(),923 1,
522// size924 [1, 1, 1].to_vec(),
523// ));925 1
524926 ));
525// assert_eq!(TemplateModule::collection(1).owner, 1);927
526// assert_eq!(TemplateModule::collection(2).owner, 2);928 // approve
527// assert_eq!(TemplateModule::collection(3).owner, 3);929 assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1));
528930 assert_eq!(TemplateModule::approved(1, (1, 1))[0].approved, 2);
529// // create item931 assert_ok!(TemplateModule::transfer_from(
530// assert_ok!(TemplateModule::create_item(932 origin2.clone(),
531// origin1.clone(),933 1,
532// 1,934 2,
533// [1, 1, 1].to_vec()935 1,
534// ));936 1,
535937 1
536// // approve938 ));
537// assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1));939
538// assert_eq!(TemplateModule::approved((1, 1)).contains(&2), true);940 // after transfer
539// });941 assert_eq!(TemplateModule::balance_count(1, 1), 0);
540// }942 assert_eq!(TemplateModule::balance_count(1, 2), 1);
541943 });
542// #[test]944}
543// fn get_approved() {
544// new_test_ext().execute_with(|| {
545// let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
546// let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
547// let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
548
549// let size = 1024;
550// let origin1 = Origin::signed(1);
551// let origin2 = Origin::signed(2);
552// let origin3 = Origin::signed(3);
553
554// assert_ok!(TemplateModule::create_collection(
555// origin1.clone(),
556// col_name1.clone(),
557// col_desc1.clone(),
558// token_prefix1.clone(),
559// size
560// ));
561// assert_ok!(TemplateModule::create_collection(
562// origin2.clone(),
563// col_name1.clone(),
564// col_desc1.clone(),
565// token_prefix1.clone(),
566// size
567// ));
568// assert_ok!(TemplateModule::create_collection(
569// origin3.clone(),
570// col_name1.clone(),
571// col_desc1.clone(),
572// token_prefix1.clone(),
573// size
574// ));
575
576// assert_eq!(TemplateModule::collection(1).owner, 1);
577// assert_eq!(TemplateModule::collection(2).owner, 2);
578// assert_eq!(TemplateModule::collection(3).owner, 3);
579
580// // create item
581// assert_ok!(TemplateModule::create_item(
582// origin1.clone(),
583// 1,
584// [1, 1, 1].to_vec()
585// ));
586
587// // approve
588// assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1));
589// assert_eq!(TemplateModule::approved((1, 1)).contains(&2), true);
590// });
591// }
592
593// #[test]
594// fn transfer_from() {
595// new_test_ext().execute_with(|| {
596// let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
597// let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
598// let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
599
600// let size = 1024;
601// let origin1 = Origin::signed(1);
602// let origin2 = Origin::signed(2);
603// let origin3 = Origin::signed(3);
604
605// assert_ok!(TemplateModule::create_collection(
606// origin1.clone(),
607// col_name1.clone(),
608// col_desc1.clone(),
609// token_prefix1.clone(),
610// size
611// ));
612// assert_ok!(TemplateModule::create_collection(
613// origin2.clone(),
614// col_name1.clone(),
615// col_desc1.clone(),
616// token_prefix1.clone(),
617// size
618// ));
619// assert_ok!(TemplateModule::create_collection(
620// origin3.clone(),
621// col_name1.clone(),
622// col_desc1.clone(),
623// token_prefix1.clone(),
624// size
625// ));
626
627// assert_eq!(TemplateModule::collection(1).owner, 1);
628// assert_eq!(TemplateModule::collection(2).owner, 2);
629// assert_eq!(TemplateModule::collection(3).owner, 3);
630
631// // create item
632// assert_ok!(TemplateModule::create_item(
633// origin1.clone(),
634// 1,
635// [1, 1, 1].to_vec()
636// ));
637
638// // approve
639// assert_ok!(TemplateModule::approve(origin1.clone(), 2, 1, 1));
640// assert_ok!(TemplateModule::transfer_from(origin1.clone(), 1, 1, 2));
641// });
642// }
643
644// #[test]
645// fn index_list() {
646// new_test_ext().execute_with(|| {
647// let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();
648// let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();
649// let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();
650
651// let size = 1024;
652// let origin1 = Origin::signed(1);
653// let origin2 = Origin::signed(2);
654// let origin3 = Origin::signed(3);
655
656// assert_ok!(TemplateModule::create_collection(
657// origin1.clone(),
658// col_name1.clone(),
659// col_desc1.clone(),
660// token_prefix1.clone(),
661// size
662// ));
663// assert_ok!(TemplateModule::create_collection(
664// origin2.clone(),
665// col_name1.clone(),
666// col_desc1.clone(),
667// token_prefix1.clone(),
668// size
669// ));
670// assert_ok!(TemplateModule::create_collection(
671// origin3.clone(),
672// col_name1.clone(),
673// col_desc1.clone(),
674// token_prefix1.clone(),
675// size
676// ));
677
678// assert_eq!(TemplateModule::collection(1).owner, 1);
679// assert_eq!(TemplateModule::collection(2).owner, 2);
680// assert_eq!(TemplateModule::collection(3).owner, 3);
681// // create items
682// assert_ok!(TemplateModule::create_item(
683// origin1.clone(),
684// 1,
685// [1, 1, 1].to_vec()
686// ));
687// assert_ok!(TemplateModule::create_item(
688// origin1.clone(),
689// 1,
690// [1, 1, 2].to_vec()
691// ));
692// assert_ok!(TemplateModule::create_item(
693// origin1.clone(),
694// 1,
695// [1, 2, 3].to_vec()
696// ));
697// assert_eq!(TemplateModule::address_tokens((1, 1)).len(), 3);
698// // burn one
699// assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 2));
700// assert_eq!(TemplateModule::address_tokens((1, 1)).len(), 2);
701// // burn another one
702// assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 3));
703// assert_eq!(TemplateModule::address_tokens((1, 1))[0], 1);
704// });
705// }
706945
modifiedruntime/build.rsdiffbeforeafterboth
--- a/runtime/build.rs
+++ b/runtime/build.rs
@@ -1,10 +1,10 @@
 use wasm_builder_runner::WasmBuilder;
 
 fn main() {
-	WasmBuilder::new()
-		.with_current_project()
-		.with_wasm_builder_from_crates("1.0.11")
-		.export_heap_base()
-		.import_memory()
-		.build()
+    WasmBuilder::new()
+        .with_current_project()
+        .with_wasm_builder_from_crates("1.0.11")
+        .export_heap_base()
+        .import_memory()
+        .build()
 }
modifiedruntime/src/lib.rsdiffbeforeafterboth
--- a/runtime/src/lib.rs
+++ b/runtime/src/lib.rs
@@ -16,11 +16,12 @@
 use sp_core::{crypto::KeyTypeId, OpaqueMetadata};
 use sp_runtime::{
     create_runtime_str, generic, impl_opaque_keys,
+    traits::{
+        BlakeTwo256, Block as BlockT, IdentifyAccount, IdentityLookup, NumberFor, Saturating,
+        Verify,
+    },
     transaction_validity::{TransactionSource, TransactionValidity},
     ApplyExtrinsicResult, MultiSignature,
-	traits::{
-        BlakeTwo256, Block as BlockT, IdentifyAccount, IdentityLookup, NumberFor, Saturating, Verify,
-	},
 };
 use sp_std::prelude::*;
 #[cfg(feature = "std")]
@@ -31,22 +32,24 @@
 pub use balances::Call as BalancesCall;
 pub use contracts::Schedule as ContractsSchedule;
 pub use frame_support::{
-    construct_runtime, parameter_types,
-    traits::{Currency, Get, ExistenceRequirement, KeyOwnerProofSystem, OnUnbalanced, Randomness, WithdrawReason},
+    construct_runtime,
+    dispatch::DispatchResult,
+    parameter_types,
+    traits::{
+        Currency, ExistenceRequirement, Get, KeyOwnerProofSystem, OnUnbalanced, Randomness,
+        WithdrawReason,
+    },
     weights::{
-        DispatchInfo, PostDispatchInfo, constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
-        IdentityFee, Weight, WeightToFeePolynomial, GetDispatchInfo, Pays,
+        constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},
+        DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,
+        WeightToFeePolynomial,
     },
     StorageValue,
-	dispatch::DispatchResult,
 };
-use system::{self as system};
 #[cfg(any(feature = "std", test))]
 pub use sp_runtime::BuildStorage;
-use sp_runtime::{
-	Perbill,
-};
-
+use sp_runtime::Perbill;
+use system::{self as system};
 
 pub use timestamp::Call as TimestampCall;
 
@@ -190,7 +193,6 @@
     /// Version of the runtime.
     type Version = Version;
     /// Converts a module to the index of the module in `construct_runtime!`.
-    ///
     /// This type is being generated by `construct_runtime!`.
     type ModuleToIndex = ModuleToIndex;
     /// What to do if a new account is created.
@@ -493,4 +495,3 @@
         }
     }
 }
-