difftreelog
Substrate nft v2. 4 tests added
in: master
16 files changed
Cargo.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",
Cargo.tomldiffbeforeafterboth--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
[workspace]
members = [
'node',
- 'pallets/template',
+ 'pallets/nft',
'runtime',
]
[profile.release]
node/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'
node/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
};
node/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
)
}
}
node/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()))
pallets/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',
+]
pallets/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
pallets/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()
+}
pallets/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
+// );
+// });
+// }
pallets/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',
-]
pallets/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
pallets/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()
-}
pallets/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
-// );
-// });
-// }
runtime/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',
]
runtime/src/lib.rsdiffbeforeafterboth1//! 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}