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
--- a/runtime/Cargo.toml
+++ b/runtime/Cargo.toml
@@ -95,10 +95,10 @@
 package = 'frame-system'
 version = '2.0.0-alpha.6'
 
-[dependencies.template]
+[dependencies.nft]
 default-features = false
-package = 'pallet-template'
-path = '../pallets/template'
+package = 'pallet-nft'
+path = '../pallets/nft'
 version = '2.0.0-alpha.6'
 
 [dependencies.timestamp]
@@ -120,7 +120,7 @@
 edition = '2018'
 homepage = 'https://substrate.dev'
 license = 'Unlicense'
-name = 'node-template-runtime'
+name = 'nft-runtime'
 repository = 'https://github.com/paritytech/substrate/'
 version = '2.0.0-alpha.6'
 
@@ -154,5 +154,5 @@
     'system/std',
     'timestamp/std',
     'transaction-payment/std',
-    'template/std',
+    'nft/std',
 ]
modifiedruntime/src/lib.rsdiffbeforeafterboth
before · runtime/src/lib.rs
1//! The Substrate Node Template runtime. This can be compiled with `#[no_std]`, ready for Wasm.23#![cfg_attr(not(feature = "std"), no_std)]4// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.5#![recursion_limit="256"]67// Make the WASM binary available.8#[cfg(feature = "std")]9include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));1011use sp_std::prelude::*;12use sp_core::OpaqueMetadata;13use sp_runtime::{14	ApplyExtrinsicResult, generic, create_runtime_str, impl_opaque_keys, MultiSignature,15	transaction_validity::{TransactionValidity, TransactionSource},16};17use sp_runtime::traits::{18	BlakeTwo256, Block as BlockT, IdentityLookup, Verify, ConvertInto, IdentifyAccount19};20use sp_api::impl_runtime_apis;21use sp_consensus_aura::sr25519::AuthorityId as AuraId;22use grandpa::AuthorityList as GrandpaAuthorityList;23use grandpa::fg_primitives;24use sp_version::RuntimeVersion;25#[cfg(feature = "std")]26use sp_version::NativeVersion;2728// A few exports that help ease life for downstream crates.29#[cfg(any(feature = "std", test))]30pub use sp_runtime::BuildStorage;31pub use timestamp::Call as TimestampCall;32pub use balances::Call as BalancesCall;33pub use sp_runtime::{Permill, Perbill};34pub use frame_support::{35	StorageValue, construct_runtime, parameter_types,36	traits::Randomness,37	weights::Weight,38};3940/// Importing a template pallet41pub use template;4243/// An index to a block.44pub type BlockNumber = u32;4546/// Alias to 512-bit hash when used in the context of a transaction signature on the chain.47pub type Signature = MultiSignature;4849/// Some way of identifying an account on the chain. We intentionally make it equivalent50/// to the public key of our transaction signing scheme.51pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;5253/// The type for looking up accounts. We don't expect more than 4 billion of them, but you54/// never know...55pub type AccountIndex = u32;5657/// Balance of an account.58pub type Balance = u128;5960/// Index of a transaction in the chain.61pub type Index = u32;6263/// A hash of some data used by the chain.64pub type Hash = sp_core::H256;6566/// Digest item type.67pub type DigestItem = generic::DigestItem<Hash>;6869/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know70/// the specifics of the runtime. They can then be made to be agnostic over specific formats71/// of data like extrinsics, allowing for them to continue syncing the network through upgrades72/// to even the core data structures.73pub mod opaque {74	use super::*;7576	pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic;7778	/// Opaque block header type.79	pub type Header = generic::Header<BlockNumber, BlakeTwo256>;80	/// Opaque block type.81	pub type Block = generic::Block<Header, UncheckedExtrinsic>;82	/// Opaque block identifier type.83	pub type BlockId = generic::BlockId<Block>;8485	impl_opaque_keys! {86		pub struct SessionKeys {87			pub aura: Aura,88			pub grandpa: Grandpa,89		}90	}91}9293/// This runtime version.94pub const VERSION: RuntimeVersion = RuntimeVersion {95	spec_name: create_runtime_str!("node-template"),96	impl_name: create_runtime_str!("node-template"),97	authoring_version: 1,98	spec_version: 1,99	impl_version: 1,100	apis: RUNTIME_API_VERSIONS,101};102103pub const MILLISECS_PER_BLOCK: u64 = 6000;104105pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK;106107// These time units are defined in number of blocks.108pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber);109pub const HOURS: BlockNumber = MINUTES * 60;110pub const DAYS: BlockNumber = HOURS * 24;111112/// The version information used to identify this runtime when compiled natively.113#[cfg(feature = "std")]114pub fn native_version() -> NativeVersion {115	NativeVersion {116		runtime_version: VERSION,117		can_author_with: Default::default(),118	}119}120121parameter_types! {122	pub const BlockHashCount: BlockNumber = 250;123	pub const MaximumBlockWeight: Weight = 1_000_000_000;124	pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);125	pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;126	pub const Version: RuntimeVersion = VERSION;127}128129impl system::Trait for Runtime {130	/// The identifier used to distinguish between accounts.131	type AccountId = AccountId;132	/// The aggregated dispatch type that is available for extrinsics.133	type Call = Call;134	/// The lookup mechanism to get account ID from whatever is passed in dispatchers.135	type Lookup = IdentityLookup<AccountId>;136	/// The index type for storing how many extrinsics an account has signed.137	type Index = Index;138	/// The index type for blocks.139	type BlockNumber = BlockNumber;140	/// The type for hashing blocks and tries.141	type Hash = Hash;142	/// The hashing algorithm used.143	type Hashing = BlakeTwo256;144	/// The header type.145	type Header = generic::Header<BlockNumber, BlakeTwo256>;146	/// The ubiquitous event type.147	type Event = Event;148	/// The ubiquitous origin type.149	type Origin = Origin;150	/// Maximum number of block number to block hash mappings to keep (oldest pruned first).151	type BlockHashCount = BlockHashCount;152	/// Maximum weight of each block.153	type MaximumBlockWeight = MaximumBlockWeight;154	/// Maximum size of all encoded transactions (in bytes) that are allowed in one block.155	type MaximumBlockLength = MaximumBlockLength;156	/// Portion of the block weight that is available to all normal transactions.157	type AvailableBlockRatio = AvailableBlockRatio;158	/// Version of the runtime.159	type Version = Version;160	/// Converts a module to the index of the module in `construct_runtime!`.161	///162	/// This type is being generated by `construct_runtime!`.163	type ModuleToIndex = ModuleToIndex;164	/// What to do if a new account is created.165	type OnNewAccount = ();166	/// What to do if an account is fully reaped from the system.167	type OnKilledAccount = ();168	/// The data to be stored in an account.169	type AccountData = balances::AccountData<Balance>;170}171172impl aura::Trait for Runtime {173	type AuthorityId = AuraId;174}175176impl grandpa::Trait for Runtime {177	type Event = Event;178}179180parameter_types! {181	pub const MinimumPeriod: u64 = SLOT_DURATION / 2;182}183184impl timestamp::Trait for Runtime {185	/// A timestamp: milliseconds since the unix epoch.186	type Moment = u64;187	type OnTimestampSet = Aura;188	type MinimumPeriod = MinimumPeriod;189}190191parameter_types! {192	pub const ExistentialDeposit: u128 = 500;193}194195impl balances::Trait for Runtime {196	/// The type for recording an account's balance.197	type Balance = Balance;198	/// The ubiquitous event type.199	type Event = Event;200	type DustRemoval = ();201	type ExistentialDeposit = ExistentialDeposit;202	type AccountStore = System;203}204205parameter_types! {206	pub const TransactionBaseFee: Balance = 0;207	pub const TransactionByteFee: Balance = 1;208}209210impl transaction_payment::Trait for Runtime {211	type Currency = balances::Module<Runtime>;212	type OnTransactionPayment = ();213	type TransactionBaseFee = TransactionBaseFee;214	type TransactionByteFee = TransactionByteFee;215	type WeightToFee = ConvertInto;216	type FeeMultiplierUpdate = ();217}218219impl sudo::Trait for Runtime {220	type Event = Event;221	type Call = Call;222}223224/// Used for the module template in `./template.rs`225impl template::Trait for Runtime {226	type Event = Event;227}228229construct_runtime!(230	pub enum Runtime where231		Block = Block,232		NodeBlock = opaque::Block,233		UncheckedExtrinsic = UncheckedExtrinsic234	{235		System: system::{Module, Call, Config, Storage, Event<T>},236		RandomnessCollectiveFlip: randomness_collective_flip::{Module, Call, Storage},237		Timestamp: timestamp::{Module, Call, Storage, Inherent},238		Aura: aura::{Module, Config<T>, Inherent(Timestamp)},239		Grandpa: grandpa::{Module, Call, Storage, Config, Event},240		Balances: balances::{Module, Call, Storage, Config<T>, Event<T>},241		TransactionPayment: transaction_payment::{Module, Storage},242		Sudo: sudo::{Module, Call, Config<T>, Storage, Event<T>},243		// Used for the module template in `./template.rs`244		TemplateModule: template::{Module, Call, Storage, Event<T>},245	}246);247248/// The address format for describing accounts.249pub type Address = AccountId;250/// Block header type as expected by this runtime.251pub type Header = generic::Header<BlockNumber, BlakeTwo256>;252/// Block type as expected by this runtime.253pub type Block = generic::Block<Header, UncheckedExtrinsic>;254/// A Block signed with a Justification255pub type SignedBlock = generic::SignedBlock<Block>;256/// BlockId type as expected by this runtime.257pub type BlockId = generic::BlockId<Block>;258/// The SignedExtension to the basic transaction logic.259pub type SignedExtra = (260	system::CheckVersion<Runtime>,261	system::CheckGenesis<Runtime>,262	system::CheckEra<Runtime>,263	system::CheckNonce<Runtime>,264	system::CheckWeight<Runtime>,265	transaction_payment::ChargeTransactionPayment<Runtime>266);267/// Unchecked extrinsic type as expected by this runtime.268pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;269/// Extrinsic type that has already been checked.270pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;271/// Executive: handles dispatch to the various modules.272pub type Executive = frame_executive::Executive<Runtime, Block, system::ChainContext<Runtime>, Runtime, AllModules>;273274impl_runtime_apis! {275	impl sp_api::Core<Block> for Runtime {276		fn version() -> RuntimeVersion {277			VERSION278		}279280		fn execute_block(block: Block) {281			Executive::execute_block(block)282		}283284		fn initialize_block(header: &<Block as BlockT>::Header) {285			Executive::initialize_block(header)286		}287	}288289	impl sp_api::Metadata<Block> for Runtime {290		fn metadata() -> OpaqueMetadata {291			Runtime::metadata().into()292		}293	}294295	impl sp_block_builder::BlockBuilder<Block> for Runtime {296		fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyExtrinsicResult {297			Executive::apply_extrinsic(extrinsic)298		}299300		fn finalize_block() -> <Block as BlockT>::Header {301			Executive::finalize_block()302		}303304		fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<<Block as BlockT>::Extrinsic> {305			data.create_extrinsics()306		}307308		fn check_inherents(309			block: Block,310			data: sp_inherents::InherentData,311		) -> sp_inherents::CheckInherentsResult {312			data.check_extrinsics(&block)313		}314315		fn random_seed() -> <Block as BlockT>::Hash {316			RandomnessCollectiveFlip::random_seed()317		}318	}319320	impl sp_transaction_pool::runtime_api::TaggedTransactionQueue<Block> for Runtime {321		fn validate_transaction(322			source: TransactionSource,323			tx: <Block as BlockT>::Extrinsic,324		) -> TransactionValidity {325			Executive::validate_transaction(source, tx)326		}327	}328329	impl sp_offchain::OffchainWorkerApi<Block> for Runtime {330		fn offchain_worker(header: &<Block as BlockT>::Header) {331			Executive::offchain_worker(header)332		}333	}334335	impl sp_consensus_aura::AuraApi<Block, AuraId> for Runtime {336		fn slot_duration() -> u64 {337			Aura::slot_duration()338		}339340		fn authorities() -> Vec<AuraId> {341			Aura::authorities()342		}343	}344345	impl sp_session::SessionKeys<Block> for Runtime {346		fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {347			opaque::SessionKeys::generate(seed)348		}349350		fn decode_session_keys(351			encoded: Vec<u8>,352		) -> Option<Vec<(Vec<u8>, sp_core::crypto::KeyTypeId)>> {353			opaque::SessionKeys::decode_into_raw_public_keys(&encoded)354		}355	}356357	impl fg_primitives::GrandpaApi<Block> for Runtime {358		fn grandpa_authorities() -> GrandpaAuthorityList {359			Grandpa::grandpa_authorities()360		}361	}362}