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

difftreelog

Substrate nft v2. 4 tests added

str-mv2020-05-06parent: #c03cc94.patch.diff
in: master

16 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2512,25 +2512,12 @@
 ]
 
 [[package]]
-name = "nix"
-version = "0.17.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363"
-dependencies = [
- "bitflags",
- "cc",
- "cfg-if",
- "libc",
- "void",
-]
-
-[[package]]
-name = "node-template"
+name = "nft"
 version = "2.0.0-alpha.6"
 dependencies = [
  "futures 0.3.4",
  "log",
- "node-template-runtime",
+ "nft-runtime",
  "sc-basic-authorship",
  "sc-cli",
  "sc-client",
@@ -2553,7 +2540,7 @@
 ]
 
 [[package]]
-name = "node-template-runtime"
+name = "nft-runtime"
 version = "2.0.0-alpha.6"
 dependencies = [
  "frame-executive",
@@ -2562,9 +2549,9 @@
  "pallet-aura",
  "pallet-balances",
  "pallet-grandpa",
+ "pallet-nft",
  "pallet-randomness-collective-flip",
  "pallet-sudo",
- "pallet-template",
  "pallet-timestamp",
  "pallet-transaction-payment",
  "parity-scale-codec",
@@ -2585,6 +2572,19 @@
 ]
 
 [[package]]
+name = "nix"
+version = "0.17.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363"
+dependencies = [
+ "bitflags",
+ "cc",
+ "cfg-if",
+ "libc",
+ "void",
+]
+
+[[package]]
 name = "nodrop"
 version = "0.1.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2802,6 +2802,19 @@
 ]
 
 [[package]]
+name = "pallet-nft"
+version = "2.0.0-alpha.6"
+dependencies = [
+ "frame-support",
+ "frame-system",
+ "parity-scale-codec",
+ "sp-core",
+ "sp-io",
+ "sp-runtime",
+ "sp-std",
+]
+
+[[package]]
 name = "pallet-randomness-collective-flip"
 version = "2.0.0-alpha.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2844,19 +2857,6 @@
  "frame-system",
  "parity-scale-codec",
  "serde",
- "sp-io",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "pallet-template"
-version = "2.0.0-alpha.6"
-dependencies = [
- "frame-support",
- "frame-system",
- "parity-scale-codec",
- "sp-core",
  "sp-io",
  "sp-runtime",
  "sp-std",
modifiedCargo.tomldiffbeforeafterboth
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [workspace]
 members = [
     'node',
-    'pallets/template',
+    'pallets/nft',
     'runtime',
 ]
 [profile.release]
modifiednode/Cargo.tomldiffbeforeafterboth
--- a/node/Cargo.toml
+++ b/node/Cargo.toml
@@ -1,11 +1,11 @@
 [package]
 authors = ['Anonymous']
 build = 'build.rs'
-description = 'Substrate Node template'
+description = 'Substrate Node nft'
 edition = '2018'
 homepage = 'https://substrate.dev'
 license = 'Unlicense'
-name = 'node-template'
+name = 'nft'
 repository = 'https://github.com/paritytech/substrate/'
 version = '2.0.0-alpha.6'
 
@@ -17,7 +17,7 @@
 log = '0.4.8'
 structopt = '0.3.8'
 
-[dependencies.node-template-runtime]
+[dependencies.nft-runtime]
 path = '../runtime'
 version = '2.0.0-alpha.6'
 
@@ -75,4 +75,4 @@
 version = '2.0.0-alpha.6'
 
 [[bin]]
-name = 'node-template'
+name = 'nft'
modifiednode/src/chain_spec.rsdiffbeforeafterboth
--- a/node/src/chain_spec.rs
+++ b/node/src/chain_spec.rs
@@ -1,5 +1,5 @@
 use sp_core::{Pair, Public, sr25519};
-use node_template_runtime::{
+use nft_runtime::{
 	AccountId, AuraConfig, BalancesConfig, GenesisConfig, GrandpaConfig,
 	SudoConfig, SystemConfig, WASM_BINARY, Signature
 };
modifiednode/src/command.rsdiffbeforeafterboth
--- a/node/src/command.rs
+++ b/node/src/command.rs
@@ -74,7 +74,7 @@
 			runner.run_node(
 				service::new_light,
 				service::new_full,
-				node_template_runtime::VERSION
+				nft_runtime::VERSION
 			)
 		}
 	}
modifiednode/src/service.rsdiffbeforeafterboth
--- a/node/src/service.rs
+++ b/node/src/service.rs
@@ -4,7 +4,7 @@
 use std::time::Duration;
 use sc_client::LongestChain;
 use sc_client_api::ExecutorProvider;
-use node_template_runtime::{self, opaque::Block, RuntimeApi};
+use nft_runtime::{self, opaque::Block, RuntimeApi};
 use sc_service::{error::{Error as ServiceError}, AbstractService, Configuration, ServiceBuilder};
 use sp_inherents::InherentDataProviders;
 use sc_executor::native_executor_instance;
@@ -15,8 +15,8 @@
 // Our native executor instance.
 native_executor_instance!(
 	pub Executor,
-	node_template_runtime::api::dispatch,
-	node_template_runtime::native_version,
+	nft_runtime::api::dispatch,
+	nft_runtime::native_version,
 );
 
 /// Starts a `ServiceBuilder` for a full service.
@@ -30,7 +30,7 @@
 		let inherent_data_providers = sp_inherents::InherentDataProviders::new();
 
 		let builder = sc_service::ServiceBuilder::new_full::<
-			node_template_runtime::opaque::Block, node_template_runtime::RuntimeApi, crate::service::Executor
+			nft_runtime::opaque::Block, nft_runtime::RuntimeApi, crate::service::Executor
 		>($config)?
 			.with_select_chain(|_config, backend| {
 				Ok(sc_client::LongestChain::new(backend.clone()))
addedpallets/nft/Cargo.tomldiffbeforeafterboth
--- /dev/null
+++ b/pallets/nft/Cargo.toml
@@ -0,0 +1,54 @@
+[package]
+authors = ['Anonymous']
+description = 'FRAME pallet nft'
+edition = '2018'
+homepage = 'https://substrate.dev'
+license = 'Unlicense'
+name = 'pallet-nft'
+repository = 'https://github.com/paritytech/substrate/'
+version = '2.0.0-alpha.6'
+
+[package.metadata.docs.rs]
+targets = ['x86_64-unknown-linux-gnu']
+
+[dependencies.codec]
+default-features = false
+features = ['derive']
+package = 'parity-scale-codec'
+version = '1.3.0'
+
+[dependencies.sp-std]
+default-features = false
+version = '2.0.0-alpha.6'
+
+[dependencies.sp-runtime]
+default-features = false
+version = '2.0.0-alpha.6'
+
+[dependencies.frame-support]
+default-features = false
+version = '2.0.0-alpha.6'
+
+[dependencies.frame-system]
+default-features = false
+version = '2.0.0-alpha.6'
+[dev-dependencies.sp-core]
+default-features = false
+version = '2.0.0-alpha.6'
+
+[dev-dependencies.sp-io]
+default-features = false
+version = '2.0.0-alpha.6'
+
+
+
+[features]
+default = ['std']
+std = [
+    'codec/std',
+    'frame-support/std',
+    'frame-system/std',
+    "sp-io/std",
+    "sp-runtime/std",
+    'sp-std/std',
+]
addedpallets/nft/src/lib.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/nft/src/lib.rs
@@ -0,0 +1,315 @@
+#![cfg_attr(not(feature = "std"), no_std)]
+
+/// A FRAME pallet template with necessary imports
+
+/// Feel free to remove or edit this file as needed.
+/// If you change the name of this file, make sure to update its references in runtime/src/lib.rs
+/// If you remove this file, you can remove those references
+
+/// For more guidance on Substrate FRAME, see the example pallet
+/// https://github.com/paritytech/substrate/blob/master/frame/example/src/lib.rs
+
+use frame_support::{
+	dispatch::DispatchResult, decl_module, decl_storage, decl_event,
+	ensure,
+};
+use frame_system::{self as system, ensure_signed };
+use codec::{Encode, Decode};
+use sp_runtime::sp_std::prelude::Vec;
+
+#[cfg(test)]
+mod mock;
+
+#[cfg(test)]
+mod tests;
+
+#[derive(Encode, Decode, Default, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Debug))]
+pub struct CollectionType<AccountId> {
+	pub owner: AccountId,
+	pub next_item_id: u64,
+	pub custom_data_size: u32,
+}
+
+#[derive(Encode, Decode, Default, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Debug))]
+pub struct CollectionAdminsType<AccountId> {
+	pub admin: AccountId,
+	pub collection_id: u64,
+}
+
+#[derive(Encode, Decode, Default, Clone, PartialEq)]
+#[cfg_attr(feature = "std", derive(Debug))]
+pub struct NftItemType<AccountId> {
+	pub collection: u64,
+	pub owner: AccountId,
+	pub data: Vec<u8>,
+}
+
+/// The pallet's configuration trait.
+pub trait Trait: system::Trait {
+	// Add other types and constants required to configure this pallet.
+
+	/// The overarching event type.
+	type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
+}
+
+// This pallet's storage items.
+decl_storage! {
+	// It is important to update your storage name so that your pallet's
+	// storage items are isolated from other pallets.
+	trait Store for Module<T: Trait> as TemplateModule {
+
+		/// Next available collection ID
+		pub NextCollectionID get(next_collection_id): u64 = 1;
+
+		/// Collection map
+		pub Collection get(collection): map hasher(blake2_128_concat) u64 => CollectionType<T::AccountId>;
+
+		/// Admins map (collection)
+		pub AdminList get(admin_list_collection): map hasher(blake2_128_concat) u64 => Vec<T::AccountId>;
+
+		/// Balance owner per collection map
+		pub Balance get(balance_count): map hasher(blake2_128_concat) (u64, T::AccountId) => u64;
+
+		/// Item double map (collection)
+		pub ItemList get(item_id): map hasher(blake2_128_concat) (u64, u64) => NftItemType<T::AccountId>;
+		pub ItemListIndex get(item_index): map hasher(blake2_128_concat) u64 => u64;
+	}
+}
+
+// The pallet's events
+decl_event!(
+	pub enum Event<T> where AccountId = <T as system::Trait>::AccountId {
+		Created(u32, AccountId),
+	}
+);
+
+// The pallet's dispatchable functions.
+decl_module! {
+	/// The module declaration.
+	pub struct Module<T: Trait> for enum Call where origin: T::Origin {
+
+		// Initializing events
+		// this is needed only if you are using events in your pallet
+		fn deposit_event() = default;
+
+		// Initializing events
+		// this is needed only if you are using events in your module
+		// fn deposit_event<T>() = default;
+
+		// Create collection of NFT with given parameters
+		//
+		// @param customDataSz size of custom data in each collection item
+		// returns collection ID
+
+		// Create collection of NFT with given parameters
+		//
+		// @param customDataSz size of custom data in each collection item
+		// returns collection ID
+		#[weight = frame_support::weights::SimpleDispatchInfo::default()]
+		pub fn create_collection(origin, custom_data_sz: u32) -> DispatchResult {
+			// Anyone can create a collection
+			let who = ensure_signed(origin)?;
+
+			// Generate next collection ID
+			let next_id = Self::next_collection_id();
+			<NextCollectionID>::put(next_id+1);
+
+			// Create new collection
+			let new_collection = CollectionType {
+				owner: who,
+				next_item_id: next_id,
+				custom_data_size: custom_data_sz,
+			};
+			
+			// Add new collection to map
+			<Collection<T>>::insert(next_id, new_collection);
+
+			Ok(())
+		}
+
+		#[weight = frame_support::weights::SimpleDispatchInfo::default()]
+		pub fn destroy_collection(origin, collection_id: u64) -> DispatchResult {
+
+			let sender = ensure_signed(origin)?;
+			ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
+
+			let owner = <Collection<T>>::get(collection_id).owner;
+			ensure!(sender == owner, "You do not own this collection");
+			<Collection<T>>::remove(collection_id);
+
+			Ok(())
+		}
+
+		#[weight = frame_support::weights::SimpleDispatchInfo::default()]
+		pub fn change_collection_owner(origin, collection_id: u64, new_owner: T::AccountId) -> DispatchResult {
+
+			let sender = ensure_signed(origin)?;
+			ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
+
+			let mut target_collection = <Collection<T>>::get(collection_id);
+			ensure!(sender == target_collection.owner, "You do not own this collection");
+
+			target_collection.owner = new_owner;
+			<Collection<T>>::insert(collection_id, target_collection);
+
+			Ok(())
+		}
+
+		#[weight = frame_support::weights::SimpleDispatchInfo::default()]
+		pub fn add_collection_admin(origin, collection_id: u64, new_admin_id: T::AccountId) -> DispatchResult {
+
+			let sender = ensure_signed(origin)?;
+			ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
+
+			let target_collection = <Collection<T>>::get(collection_id);
+			let is_owner = sender == target_collection.owner;
+
+			let no_perm_mes = "You do not have permissions to modify this collection";
+			let exists = <AdminList<T>>::contains_key(collection_id);
+
+			if !is_owner 
+			{
+				 ensure!(exists, no_perm_mes);
+				 ensure!(<AdminList<T>>::get(collection_id).contains(&sender), no_perm_mes);
+			}
+			
+			let mut admin_arr: Vec<T::AccountId> = Vec::new();
+			if exists
+			{
+				admin_arr = <AdminList<T>>::get(collection_id);
+				ensure!(!admin_arr.contains(&new_admin_id), "Account already has admin role");
+			}
+
+			admin_arr.push(new_admin_id);
+			<AdminList<T>>::insert(collection_id, admin_arr);
+
+			Ok(())
+		}
+
+		#[weight = frame_support::weights::SimpleDispatchInfo::default()]
+		pub fn remove_collection_admin(origin, collection_id: u64, account_id: T::AccountId) -> DispatchResult {
+
+			let sender = ensure_signed(origin)?;
+			ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
+
+			let target_collection = <Collection<T>>::get(collection_id);
+			let is_owner = sender == target_collection.owner;
+
+			let no_perm_mes = "You do not have permissions to modify this collection";
+			let exists = <AdminList<T>>::contains_key(collection_id);
+
+			if !is_owner 
+			{
+				ensure!(exists, no_perm_mes);
+				ensure!(<AdminList<T>>::get(collection_id).contains(&sender), no_perm_mes);
+			}
+
+			if exists
+			{
+				let mut admin_arr = <AdminList<T>>::get(collection_id);
+				admin_arr.retain(|i| *i != account_id);
+				<AdminList<T>>::insert(collection_id, admin_arr);
+			}
+
+			Ok(())
+		}
+
+		#[weight = frame_support::weights::SimpleDispatchInfo::default()]
+		pub fn create_item(origin, collection_id: u64, properties: Vec<u8>) -> DispatchResult {
+
+			let sender = ensure_signed(origin)?;
+			ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
+
+			let target_collection = <Collection<T>>::get(collection_id);
+			ensure!(target_collection.custom_data_size >= properties.len() as u32, "Size of item is too large");
+			let is_owner = sender == target_collection.owner;
+
+			let no_perm_mes = "You do not have permissions to modify this collection";
+			let exists = <AdminList<T>>::contains_key(collection_id);
+
+			if !is_owner 
+			{
+				ensure!(exists, no_perm_mes);
+				ensure!(<AdminList<T>>::get(collection_id).contains(&sender), no_perm_mes);
+			}
+
+			let new_balance = <Balance<T>>::get((collection_id, sender.clone())) + 1;
+			<Balance<T>>::insert((collection_id, sender.clone()), new_balance);
+
+			// Create new item
+			let new_item = NftItemType {
+				collection: collection_id,
+				owner: sender,
+				data: properties,
+			};
+
+			let current_index = <ItemListIndex>::get(collection_id);
+			<ItemListIndex>::insert(collection_id, current_index+1);
+			<ItemList<T>>::insert((collection_id, current_index), new_item);
+
+			Ok(())
+		}
+
+		#[weight = frame_support::weights::SimpleDispatchInfo::default()]
+		pub fn burn_item(origin, collection_id: u64, item_id: u64) -> DispatchResult {
+
+			let sender = ensure_signed(origin)?;
+			ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
+
+			let target_collection = <Collection<T>>::get(collection_id);
+			let is_owner = sender == target_collection.owner;
+
+			ensure!(<ItemList<T>>::contains_key((collection_id, item_id)), "Item does not exists");
+			let item = <ItemList<T>>::get((collection_id, item_id));
+
+			if !is_owner 
+			{
+				// check if item owner
+				if item.owner != sender 
+				{
+					let no_perm_mes = "You do not have permissions to modify this collection";
+
+					ensure!(<AdminList<T>>::contains_key(collection_id), no_perm_mes);
+					ensure!(<AdminList<T>>::get(collection_id).contains(&sender), no_perm_mes);
+				}
+			}
+			<ItemList<T>>::remove((collection_id, item_id));
+
+			Ok(())
+		}
+
+		#[weight = frame_support::weights::SimpleDispatchInfo::default()]
+		pub fn transfer(origin, collection_id: u64, item_id: u64, new_owner: T::AccountId) -> DispatchResult {
+
+			let sender = ensure_signed(origin)?;
+			ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
+
+			let target_collection = <Collection<T>>::get(collection_id);
+			let is_owner = sender == target_collection.owner;
+
+			ensure!(<ItemList<T>>::contains_key((collection_id, item_id)), "Item does not exists");
+			let mut item = <ItemList<T>>::get((collection_id, item_id));
+
+			if !is_owner 
+			{
+				// check if item owner
+				if item.owner != sender 
+				{
+					let no_perm_mes = "You do not have permissions to modify this collection";
+
+					ensure!(<AdminList<T>>::contains_key(collection_id), no_perm_mes);
+					ensure!(<AdminList<T>>::get(collection_id).contains(&sender), no_perm_mes);
+				}
+			}
+			<ItemList<T>>::remove((collection_id, item_id));
+
+			// change owner
+			item.owner = new_owner;
+			<ItemList<T>>::insert((collection_id, item_id), item);
+
+			Ok(())
+		}
+	}
+}
\ No newline at end of file
addedpallets/nft/src/mock.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/nft/src/mock.rs
@@ -0,0 +1,56 @@
+// Creating mock runtime here
+
+use crate::{Module, Trait};
+use sp_core::H256;
+use frame_support::{impl_outer_origin, parameter_types, weights::Weight};
+use sp_runtime::{
+	traits::{BlakeTwo256, IdentityLookup}, testing::Header, Perbill,
+};
+use frame_system as system;
+
+impl_outer_origin! {
+	pub enum Origin for Test {}
+}
+
+// For testing the pallet, we construct most of a mock runtime. This means
+// first constructing a configuration type (`Test`) which `impl`s each of the
+// configuration traits of pallets we want to use.
+#[derive(Clone, Eq, PartialEq)]
+pub struct Test;
+parameter_types! {
+	pub const BlockHashCount: u64 = 250;
+	pub const MaximumBlockWeight: Weight = 1024;
+	pub const MaximumBlockLength: u32 = 2 * 1024;
+	pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
+}
+impl system::Trait for Test {
+	type Origin = Origin;
+	type Call = ();
+	type Index = u64;
+	type BlockNumber = u64;
+	type Hash = H256;
+	type Hashing = BlakeTwo256;
+	type AccountId = u64;
+	type Lookup = IdentityLookup<Self::AccountId>;
+	type Header = Header;
+	type Event = ();
+	type BlockHashCount = BlockHashCount;
+	type MaximumBlockWeight = MaximumBlockWeight;
+	type MaximumBlockLength = MaximumBlockLength;
+	type AvailableBlockRatio = AvailableBlockRatio;
+	type Version = ();
+	type ModuleToIndex = ();
+	type AccountData = ();
+	type OnNewAccount = ();
+	type OnKilledAccount = ();
+}
+impl Trait for Test {
+	type Event = ();
+}
+pub type TemplateModule = Module<Test>;
+
+// This function basically just builds a genesis storage key/value store according to
+// our desired mockup.
+pub fn new_test_ext() -> sp_io::TestExternalities {
+	system::GenesisConfig::default().build_storage::<Test>().unwrap().into()
+}
addedpallets/nft/src/tests.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/nft/src/tests.rs
@@ -0,0 +1,84 @@
+// Tests to be written here
+use crate::{ mock::*};
+use frame_support::{assert_ok, assert_noop};
+
+#[test]
+fn create_collection_test() {
+    new_test_ext().execute_with(|| {
+        let size = 1024;
+        let origin1 = Origin::signed(1);
+        assert_ok!(TemplateModule::create_collection(origin1.clone(), size));
+        assert_eq!(TemplateModule::collection(1).owner, 1);
+    });
+}
+
+#[test]
+fn change_collection_owner() {
+	new_test_ext().execute_with(|| {
+        let size = 1024;
+        let origin1 = Origin::signed(1);
+        let origin2 = Origin::signed(2);
+
+        assert_ok!(TemplateModule::create_collection(origin1.clone(), size));
+        assert_ok!(TemplateModule::change_collection_owner(origin1.clone(), 1, 2));
+        assert_eq!(TemplateModule::collection(1).owner, 2);
+	});
+}
+
+#[test]
+fn destroy_collection() {
+	new_test_ext().execute_with(|| {
+        let size = 1024;
+        let origin1 = Origin::signed(1);
+
+        assert_ok!(TemplateModule::create_collection(origin1.clone(), size));
+        assert_ok!(TemplateModule::destroy_collection(origin1.clone(), 1));
+	});
+}
+
+#[test]
+fn create_item() {
+	new_test_ext().execute_with(|| {
+        let size = 1024;
+        let origin1 = Origin::signed(1);
+        let origin2 = Origin::signed(2);
+
+        assert_ok!(TemplateModule::create_collection(origin1.clone(), size));
+        assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2));
+        assert_ok!(TemplateModule::create_item(origin2.clone(), 1, [1,1,1].to_vec()));
+
+        // check balance (collection with id = 1, user id = 2)
+        assert_eq!(TemplateModule::balance_count((1, 2)), 1);
+	});
+}
+
+// #[test]
+// fn burn_item() {
+// 	new_test_ext().execute_with(|| {
+//         let size = 1024;
+//         let origin1 = Origin::signed(1);
+//         let origin2 = Origin::signed(2);
+
+//         assert_ok!(TemplateModule::create_collection(origin1.clone(), size));
+//         assert_ok!(TemplateModule::add_collection_admin(origin1.clone(), 1, 2));
+//         assert_ok!(TemplateModule::create_item(origin2.clone(), 1, [1,1,1].to_vec()));
+
+//         // check balance (collection with id = 1, user id = 2)
+//         assert_eq!(TemplateModule::balance_count((1, 2)), 1);
+
+//         // burn item
+//         assert_ok!(TemplateModule::burn_item(origin1.clone(), 1, 1));
+//         assert_noop!(TemplateModule::burn_item(origin1.clone(), 1, 1), "Item does not exists");
+// 	});
+// }
+
+// #[test]
+// fn correct_error_for_none_value() {
+// 	new_test_ext().execute_with(|| {
+// 		// Ensure the correct error is thrown on None value
+// 		assert_noop!(
+// 			TemplateModule::cause_error(Origin::signed(1)),
+// 			Error::<Test>::NoneValue
+// 		);
+// 	});
+// }
deletedpallets/template/Cargo.tomldiffbeforeafterboth
--- a/pallets/template/Cargo.toml
+++ /dev/null
@@ -1,54 +0,0 @@
-[package]
-authors = ['Anonymous']
-description = 'FRAME pallet template'
-edition = '2018'
-homepage = 'https://substrate.dev'
-license = 'Unlicense'
-name = 'pallet-template'
-repository = 'https://github.com/paritytech/substrate/'
-version = '2.0.0-alpha.6'
-
-[package.metadata.docs.rs]
-targets = ['x86_64-unknown-linux-gnu']
-
-[dependencies.codec]
-default-features = false
-features = ['derive']
-package = 'parity-scale-codec'
-version = '1.3.0'
-
-[dependencies.sp-std]
-default-features = false
-version = '2.0.0-alpha.6'
-
-[dependencies.sp-runtime]
-default-features = false
-version = '2.0.0-alpha.6'
-
-[dependencies.frame-support]
-default-features = false
-version = '2.0.0-alpha.6'
-
-[dependencies.frame-system]
-default-features = false
-version = '2.0.0-alpha.6'
-[dev-dependencies.sp-core]
-default-features = false
-version = '2.0.0-alpha.6'
-
-[dev-dependencies.sp-io]
-default-features = false
-version = '2.0.0-alpha.6'
-
-
-
-[features]
-default = ['std']
-std = [
-    'codec/std',
-    'frame-support/std',
-    'frame-system/std',
-    "sp-io/std",
-    "sp-runtime/std",
-    'sp-std/std',
-]
deletedpallets/template/src/lib.rsdiffbeforeafterboth
--- a/pallets/template/src/lib.rs
+++ /dev/null
@@ -1,316 +0,0 @@
-#![cfg_attr(not(feature = "std"), no_std)]
-
-/// A FRAME pallet template with necessary imports
-
-/// Feel free to remove or edit this file as needed.
-/// If you change the name of this file, make sure to update its references in runtime/src/lib.rs
-/// If you remove this file, you can remove those references
-
-/// For more guidance on Substrate FRAME, see the example pallet
-/// https://github.com/paritytech/substrate/blob/master/frame/example/src/lib.rs
-
-use frame_support::{
-	dispatch::DispatchResult, decl_module, decl_storage, decl_event,
-	weights::{DispatchClass, ClassifyDispatch, WeighData, Weight},
-	ensure,
-};
-use frame_system::{self as system, ensure_signed };
-use codec::{Encode, Decode};
-use sp_runtime::sp_std::prelude::Vec;
-
-#[cfg(test)]
-mod mock;
-
-#[cfg(test)]
-mod tests;
-
-#[derive(Encode, Decode, Default, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Debug))]
-pub struct CollectionType<AccountId> {
-	pub owner: AccountId,
-	pub next_item_id: u64,
-	pub custom_data_size: u32,
-}
-
-#[derive(Encode, Decode, Default, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Debug))]
-pub struct CollectionAdminsType<AccountId> {
-	pub admin: AccountId,
-	pub collection_id: u64,
-}
-
-#[derive(Encode, Decode, Default, Clone, PartialEq)]
-#[cfg_attr(feature = "std", derive(Debug))]
-pub struct NftItemType<AccountId> {
-	pub collection: u64,
-	pub owner: AccountId,
-	pub data: Vec<u8>,
-}
-
-/// The pallet's configuration trait.
-pub trait Trait: system::Trait {
-	// Add other types and constants required to configure this pallet.
-
-	/// The overarching event type.
-	type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
-}
-
-// This pallet's storage items.
-decl_storage! {
-	// It is important to update your storage name so that your pallet's
-	// storage items are isolated from other pallets.
-	trait Store for Module<T: Trait> as TemplateModule {
-
-		/// Next available collection ID
-		pub NextCollectionID get(next_collection_id): u64;
-
-		/// Collection map
-		pub Collection get(collection): map hasher(blake2_128_concat) u64 => CollectionType<T::AccountId>;
-
-		/// Admins map (collection)
-		pub AdminList get(admin_list_collection): map hasher(blake2_128_concat) u64 => Vec<T::AccountId>;
-
-		/// Balance owner per collection map
-		pub Balance get(balance_count): map hasher(blake2_128_concat) (u64, T::AccountId) => u64;
-
-		/// Item double map (collection)
-		pub ItemList get(item_id): map hasher(blake2_128_concat) (u64, u64) => NftItemType<T::AccountId>;
-		pub ItemListIndex get(item_index): map hasher(blake2_128_concat) u64 => u64;
-	}
-}
-
-// The pallet's events
-decl_event!(
-	pub enum Event<T> where AccountId = <T as system::Trait>::AccountId {
-		Created(u32, AccountId),
-	}
-);
-
-// The pallet's dispatchable functions.
-decl_module! {
-	/// The module declaration.
-	pub struct Module<T: Trait> for enum Call where origin: T::Origin {
-
-		// Initializing events
-		// this is needed only if you are using events in your pallet
-		fn deposit_event() = default;
-
-		// Initializing events
-		// this is needed only if you are using events in your module
-		// fn deposit_event<T>() = default;
-
-		// Create collection of NFT with given parameters
-		//
-		// @param customDataSz size of custom data in each collection item
-		// returns collection ID
-
-		// Create collection of NFT with given parameters
-		//
-		// @param customDataSz size of custom data in each collection item
-		// returns collection ID
-		#[weight = frame_support::weights::SimpleDispatchInfo::default()]
-		pub fn create_collection(origin, custom_data_sz: u32) -> DispatchResult {
-			// Anyone can create a collection
-			let who = ensure_signed(origin)?;
-
-			// Generate next collection ID
-			let next_id = Self::next_collection_id();
-			<NextCollectionID>::put(next_id+1);
-
-			// Create new collection
-			let new_collection = CollectionType {
-				owner: who,
-				next_item_id: next_id,
-				custom_data_size: custom_data_sz,
-			};
-			
-			// Add new collection to map
-			<Collection<T>>::insert(next_id, new_collection);
-
-			Ok(())
-		}
-
-		#[weight = frame_support::weights::SimpleDispatchInfo::default()]
-		pub fn destroy_collection(origin, collection_id: u64) -> DispatchResult {
-
-			let sender = ensure_signed(origin)?;
-			ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
-
-			let owner = <Collection<T>>::get(collection_id).owner;
-			ensure!(sender == owner, "You do not own this collection");
-			<Collection<T>>::remove(collection_id);
-
-			Ok(())
-		}
-
-		#[weight = frame_support::weights::SimpleDispatchInfo::default()]
-		pub fn change_collection_owner(origin, collection_id: u64, new_owner: T::AccountId) -> DispatchResult {
-
-			let sender = ensure_signed(origin)?;
-			ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
-
-			let mut target_collection = <Collection<T>>::get(collection_id);
-			ensure!(sender == target_collection.owner, "You do not own this collection");
-
-			target_collection.owner = new_owner;
-			<Collection<T>>::insert(collection_id, target_collection);
-
-			Ok(())
-		}
-
-		#[weight = frame_support::weights::SimpleDispatchInfo::default()]
-		pub fn add_collection_admin(origin, collection_id: u64, new_admin_id: T::AccountId) -> DispatchResult {
-
-			let sender = ensure_signed(origin)?;
-			ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
-
-			let target_collection = <Collection<T>>::get(collection_id);
-			let is_owner = sender == target_collection.owner;
-
-			let no_perm_mes = "You do not have permissions to modify this collection";
-			let exists = <AdminList<T>>::contains_key(collection_id);
-
-			if !is_owner 
-			{
-				 ensure!(exists, no_perm_mes);
-				 ensure!(<AdminList<T>>::get(collection_id).contains(&sender), no_perm_mes);
-			}
-			
-			let mut admin_arr: Vec<T::AccountId> = Vec::new();
-			if exists
-			{
-				admin_arr = <AdminList<T>>::get(collection_id);
-				ensure!(!admin_arr.contains(&new_admin_id), "Account already has admin role");
-			}
-
-			admin_arr.push(new_admin_id);
-			<AdminList<T>>::insert(collection_id, admin_arr);
-
-			Ok(())
-		}
-
-		#[weight = frame_support::weights::SimpleDispatchInfo::default()]
-		pub fn remove_collection_admin(origin, collection_id: u64, account_id: T::AccountId) -> DispatchResult {
-
-			let sender = ensure_signed(origin)?;
-			ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
-
-			let target_collection = <Collection<T>>::get(collection_id);
-			let is_owner = sender == target_collection.owner;
-
-			let no_perm_mes = "You do not have permissions to modify this collection";
-			let exists = <AdminList<T>>::contains_key(collection_id);
-
-			if !is_owner 
-			{
-				ensure!(exists, no_perm_mes);
-				ensure!(<AdminList<T>>::get(collection_id).contains(&sender), no_perm_mes);
-			}
-
-			if exists
-			{
-				let mut admin_arr = <AdminList<T>>::get(collection_id);
-				admin_arr.retain(|i| *i != account_id);
-				<AdminList<T>>::insert(collection_id, admin_arr);
-			}
-
-			Ok(())
-		}
-
-		#[weight = frame_support::weights::SimpleDispatchInfo::default()]
-		pub fn create_item(origin, collection_id: u64, properties: Vec<u8>) -> DispatchResult {
-
-			let sender = ensure_signed(origin)?;
-			ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
-
-			let target_collection = <Collection<T>>::get(collection_id);
-			ensure!(target_collection.custom_data_size >= properties.len() as u32, "Size of item is too large");
-			let is_owner = sender == target_collection.owner;
-
-			let no_perm_mes = "You do not have permissions to modify this collection";
-			let exists = <AdminList<T>>::contains_key(collection_id);
-
-			if !is_owner 
-			{
-				ensure!(exists, no_perm_mes);
-				ensure!(<AdminList<T>>::get(collection_id).contains(&sender), no_perm_mes);
-			}
-
-			let new_balance = <Balance<T>>::get((collection_id, sender.clone())) + 1;
-			<Balance<T>>::insert((collection_id, sender.clone()), new_balance);
-
-			// Create new item
-			let new_item = NftItemType {
-				collection: collection_id,
-				owner: sender,
-				data: properties,
-			};
-
-			let current_index = <ItemListIndex>::get(collection_id);
-			<ItemListIndex>::insert(collection_id, current_index+1);
-			<ItemList<T>>::insert((collection_id, current_index), new_item);
-
-			Ok(())
-		}
-
-		#[weight = frame_support::weights::SimpleDispatchInfo::default()]
-		pub fn burn_item(origin, collection_id: u64, item_id: u64) -> DispatchResult {
-
-			let sender = ensure_signed(origin)?;
-			ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
-
-			let target_collection = <Collection<T>>::get(collection_id);
-			let is_owner = sender == target_collection.owner;
-
-			ensure!(<ItemList<T>>::contains_key((collection_id, item_id)), "Item does not exists");
-			let item = <ItemList<T>>::get((collection_id, item_id));
-
-			if !is_owner 
-			{
-				// check if item owner
-				if item.owner != sender 
-				{
-					let no_perm_mes = "You do not have permissions to modify this collection";
-
-					ensure!(<AdminList<T>>::contains_key(collection_id), no_perm_mes);
-					ensure!(<AdminList<T>>::get(collection_id).contains(&sender), no_perm_mes);
-				}
-			}
-			<ItemList<T>>::remove((collection_id, item_id));
-
-			Ok(())
-		}
-
-		#[weight = frame_support::weights::SimpleDispatchInfo::default()]
-		pub fn transfer(origin, collection_id: u64, item_id: u64, new_owner: T::AccountId) -> DispatchResult {
-
-			let sender = ensure_signed(origin)?;
-			ensure!(<Collection<T>>::contains_key(collection_id), "This collection does not exist");
-
-			let target_collection = <Collection<T>>::get(collection_id);
-			let is_owner = sender == target_collection.owner;
-
-			ensure!(<ItemList<T>>::contains_key((collection_id, item_id)), "Item does not exists");
-			let mut item = <ItemList<T>>::get((collection_id, item_id));
-
-			if !is_owner 
-			{
-				// check if item owner
-				if item.owner != sender 
-				{
-					let no_perm_mes = "You do not have permissions to modify this collection";
-
-					ensure!(<AdminList<T>>::contains_key(collection_id), no_perm_mes);
-					ensure!(<AdminList<T>>::get(collection_id).contains(&sender), no_perm_mes);
-				}
-			}
-			<ItemList<T>>::remove((collection_id, item_id));
-
-			// change owner
-			item.owner = new_owner;
-			<ItemList<T>>::insert((collection_id, item_id), item);
-
-			Ok(())
-		}
-	}
-}
\ No newline at end of file
deletedpallets/template/src/mock.rsdiffbeforeafterboth
--- a/pallets/template/src/mock.rs
+++ /dev/null
@@ -1,56 +0,0 @@
-// Creating mock runtime here
-
-use crate::{Module, Trait};
-use sp_core::H256;
-use frame_support::{impl_outer_origin, parameter_types, weights::Weight};
-use sp_runtime::{
-	traits::{BlakeTwo256, IdentityLookup}, testing::Header, Perbill,
-};
-use frame_system as system;
-
-impl_outer_origin! {
-	pub enum Origin for Test {}
-}
-
-// For testing the pallet, we construct most of a mock runtime. This means
-// first constructing a configuration type (`Test`) which `impl`s each of the
-// configuration traits of pallets we want to use.
-#[derive(Clone, Eq, PartialEq)]
-pub struct Test;
-parameter_types! {
-	pub const BlockHashCount: u64 = 250;
-	pub const MaximumBlockWeight: Weight = 1024;
-	pub const MaximumBlockLength: u32 = 2 * 1024;
-	pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
-}
-impl system::Trait for Test {
-	type Origin = Origin;
-	type Call = ();
-	type Index = u64;
-	type BlockNumber = u64;
-	type Hash = H256;
-	type Hashing = BlakeTwo256;
-	type AccountId = u64;
-	type Lookup = IdentityLookup<Self::AccountId>;
-	type Header = Header;
-	type Event = ();
-	type BlockHashCount = BlockHashCount;
-	type MaximumBlockWeight = MaximumBlockWeight;
-	type MaximumBlockLength = MaximumBlockLength;
-	type AvailableBlockRatio = AvailableBlockRatio;
-	type Version = ();
-	type ModuleToIndex = ();
-	type AccountData = ();
-	type OnNewAccount = ();
-	type OnKilledAccount = ();
-}
-impl Trait for Test {
-	type Event = ();
-}
-pub type TemplateModule = Module<Test>;
-
-// This function basically just builds a genesis storage key/value store according to
-// our desired mockup.
-pub fn new_test_ext() -> sp_io::TestExternalities {
-	system::GenesisConfig::default().build_storage::<Test>().unwrap().into()
-}
deletedpallets/template/src/tests.rsdiffbeforeafterboth
--- a/pallets/template/src/tests.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Tests to be written here
-use frame_support::{assert_ok, assert_noop};
-
-// #[test]
-// fn it_works_for_default_value() {
-// 	new_test_ext().execute_with(|| {
-// 		// Just a dummy test for the dummy function `do_something`
-// 		// calling the `do_something` function with a value 42
-// 		assert_ok!(TemplateModule::do_something(Origin::signed(1), 42));
-// 		// asserting that the stored value is equal to what we stored
-// 		assert_eq!(TemplateModule::something(), Some(42));
-// 	});
-// }
-
-// #[test]
-// fn correct_error_for_none_value() {
-// 	new_test_ext().execute_with(|| {
-// 		// Ensure the correct error is thrown on None value
-// 		assert_noop!(
-// 			TemplateModule::cause_error(Origin::signed(1)),
-// 			Error::<Test>::NoneValue
-// 		);
-// 	});
-// }
modifiedruntime/Cargo.tomldiffbeforeafterboth
95package = 'frame-system'95package = 'frame-system'
96version = '2.0.0-alpha.6'96version = '2.0.0-alpha.6'
9797
98[dependencies.template]98[dependencies.nft]
99default-features = false99default-features = false
100package = 'pallet-template'100package = 'pallet-nft'
101path = '../pallets/template'101path = '../pallets/nft'
102version = '2.0.0-alpha.6'102version = '2.0.0-alpha.6'
103103
104[dependencies.timestamp]104[dependencies.timestamp]
120edition = '2018'120edition = '2018'
121homepage = 'https://substrate.dev'121homepage = 'https://substrate.dev'
122license = 'Unlicense'122license = 'Unlicense'
123name = 'node-template-runtime'123name = 'nft-runtime'
124repository = 'https://github.com/paritytech/substrate/'124repository = 'https://github.com/paritytech/substrate/'
125version = '2.0.0-alpha.6'125version = '2.0.0-alpha.6'
126126
154 'system/std',154 'system/std',
155 'timestamp/std',155 'timestamp/std',
156 'transaction-payment/std',156 'transaction-payment/std',
157 'template/std',157 'nft/std',
158]158]
159159
modifiedruntime/src/lib.rsdiffbeforeafterboth
--- a/runtime/src/lib.rs
+++ b/runtime/src/lib.rs
@@ -38,7 +38,7 @@
 };
 
 /// Importing a template pallet
-pub use template;
+pub use nft;
 
 /// An index to a block.
 pub type BlockNumber = u32;
@@ -92,8 +92,8 @@
 
 /// This runtime version.
 pub const VERSION: RuntimeVersion = RuntimeVersion {
-	spec_name: create_runtime_str!("node-template"),
-	impl_name: create_runtime_str!("node-template"),
+	spec_name: create_runtime_str!("nft"),
+	impl_name: create_runtime_str!("nft"),
 	authoring_version: 1,
 	spec_version: 1,
 	impl_version: 1,
@@ -222,7 +222,7 @@
 }
 
 /// Used for the module template in `./template.rs`
-impl template::Trait for Runtime {
+impl nft::Trait for Runtime {
 	type Event = Event;
 }
 
@@ -241,7 +241,7 @@
 		TransactionPayment: transaction_payment::{Module, Storage},
 		Sudo: sudo::{Module, Call, Config<T>, Storage, Event<T>},
 		// Used for the module template in `./template.rs`
-		TemplateModule: template::{Module, Call, Storage, Event<T>},
+		Nft: nft::{Module, Call, Storage, Event<T>},
 	}
 );