// This file is part of Bizinikiwi. // Copyright (C) Parity Technologies (UK) Ltd. // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #![recursion_limit = "128"] use pezframe_support::{ derive_impl, inherent::{InherentData, InherentIdentifier, MakeFatalError, ProvideInherent}, traits::ConstU32, }; use pezframe_system::pezpallet_prelude::BlockNumberFor; use pezsp_core::sr25519; use pezsp_metadata_ir::{ PalletStorageMetadataIR, StorageEntryMetadataIR, StorageEntryModifierIR, StorageEntryTypeIR, StorageHasherIR, }; use pezsp_runtime::{ generic, traits::{BlakeTwo256, Verify}, BuildStorage, }; pub trait Currency {} // Test for: // * No default instance // * Origin, Inherent, Event #[pezframe_support::pezpallet(dev_mode)] mod module1 { use super::*; use pezframe_support::pezpallet_prelude::*; use pezframe_system::pezpallet_prelude::*; #[pezpallet::pezpallet] pub struct Pezpallet(_); #[pezpallet::config] pub trait Config: pezframe_system::Config { #[allow(deprecated)] type RuntimeEvent: From> + IsType<::RuntimeEvent>; type RuntimeOrigin: From>; type SomeParameter: Get; type GenericType: Parameter + Member + MaybeSerializeDeserialize + Default + MaxEncodedLen; } #[pezpallet::call] impl, I: 'static> Pezpallet { #[pezpallet::weight(0)] pub fn one(origin: OriginFor) -> DispatchResult { ensure_root(origin)?; Self::deposit_event(Event::AnotherVariant(3)); Ok(()) } } #[pezpallet::storage] #[pezpallet::getter(fn value)] pub type Value, I: 'static = ()> = StorageValue<_, T::GenericType, ValueQuery>; #[pezpallet::storage] #[pezpallet::getter(fn map)] pub type Map, I: 'static = ()> = StorageMap<_, Identity, u32, u64, ValueQuery>; #[pezpallet::genesis_config] pub struct GenesisConfig, I: 'static = ()> { pub value: >::GenericType, pub test: BlockNumberFor, } impl, I: 'static> Default for GenesisConfig { fn default() -> Self { Self { value: Default::default(), test: Default::default() } } } #[pezpallet::genesis_build] impl, I: 'static> BuildGenesisConfig for GenesisConfig where BlockNumberFor: std::fmt::Display, { fn build(&self) { >::put(self.value.clone()); println!("{}", self.test); } } #[pezpallet::error] pub enum Error { /// Test Test, } #[pezpallet::event] #[pezpallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event, I: 'static = ()> { _Phantom(PhantomData), AnotherVariant(u32), } #[pezpallet::origin] #[derive( Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, DecodeWithMemTracking, MaxEncodedLen, TypeInfo, )] #[scale_info(skip_type_params(I))] pub enum Origin { Members(u32), _Phantom(PhantomData<(T, I)>), } pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"12345678"; #[pezpallet::inherent] impl, I: 'static> ProvideInherent for Pezpallet where BlockNumberFor: From, { type Call = Call; type Error = MakeFatalError<()>; const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; fn create_inherent(_data: &InherentData) -> Option { unimplemented!(); } fn check_inherent(_: &Self::Call, _: &InherentData) -> Result<(), Self::Error> { unimplemented!(); } fn is_inherent(_call: &Self::Call) -> bool { unimplemented!(); } } } // Test for: // * default instance // * use of no_genesis_config_phantom_data #[pezframe_support::pezpallet] mod module2 { use super::*; use pezframe_support::pezpallet_prelude::*; #[pezpallet::pezpallet] pub struct Pezpallet(PhantomData<(T, I)>); #[pezpallet::config] pub trait Config: pezframe_system::Config { type Amount: Parameter + MaybeSerializeDeserialize + Default + MaxEncodedLen; #[allow(deprecated)] type RuntimeEvent: From> + IsType<::RuntimeEvent>; type RuntimeOrigin: From>; } impl, I: 'static> Currency for Pezpallet {} #[pezpallet::call] impl, I: 'static> Pezpallet {} #[pezpallet::storage] pub type Value, I: 'static = ()> = StorageValue<_, T::Amount, ValueQuery>; #[pezpallet::storage] pub type Map, I: 'static = ()> = StorageMap<_, Identity, u64, u64, ValueQuery>; #[pezpallet::storage] pub type DoubleMap, I: 'static = ()> = StorageDoubleMap<_, Identity, u64, Identity, u64, u64, ValueQuery>; #[pezpallet::genesis_config] pub struct GenesisConfig, I: 'static = ()> { pub value: T::Amount, pub map: Vec<(u64, u64)>, pub double_map: Vec<(u64, u64, u64)>, } impl, I: 'static> Default for GenesisConfig { fn default() -> Self { Self { value: Default::default(), map: Default::default(), double_map: Default::default(), } } } #[pezpallet::genesis_build] impl, I: 'static> BuildGenesisConfig for GenesisConfig where BlockNumberFor: std::fmt::Display, { fn build(&self) { >::put(self.value.clone()); for (k, v) in &self.map { >::insert(k, v); } for (k1, k2, v) in &self.double_map { >::insert(k1, k2, v); } } } #[pezpallet::event] pub enum Event, I: 'static = ()> { Variant(T::Amount), } #[pezpallet::origin] #[derive( Clone, PartialEq, Eq, RuntimeDebug, Encode, Decode, DecodeWithMemTracking, MaxEncodedLen, TypeInfo, )] #[scale_info(skip_type_params(I))] pub enum Origin { Members(u32), _Phantom(PhantomData<(T, I)>), } pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"12345678"; #[pezpallet::inherent] impl, I: 'static> ProvideInherent for Pezpallet { type Call = Call; type Error = MakeFatalError<()>; const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; fn create_inherent(_data: &InherentData) -> Option { unimplemented!(); } fn check_inherent(_call: &Self::Call, _data: &InherentData) -> Result<(), Self::Error> { unimplemented!(); } fn is_inherent(_call: &Self::Call) -> bool { unimplemented!(); } } } // Test for: // * Depends on multiple instances of a module with instances #[pezframe_support::pezpallet] mod module3 { use super::*; use pezframe_support::pezpallet_prelude::*; #[pezpallet::pezpallet] pub struct Pezpallet(PhantomData<(T, I)>); #[pezpallet::config] pub trait Config: pezframe_system::Config + module2::Config + module2::Config { type Currency: Currency; type Currency2: Currency; } #[pezpallet::call] impl, I: 'static> Pezpallet {} } pub type BlockNumber = u32; pub type Signature = sr25519::Signature; pub type AccountId = ::Signer; pub type Header = generic::Header; pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; pub type Block = generic::Block; pezframe_support::construct_runtime!( pub enum Runtime { System: pezframe_system, Module1_1: module1::, Module1_2: module1::, Module2: module2, Module2_1: module2::, Module2_2: module2::, Module2_3: module2::, Module3: module3, } ); #[derive_impl(pezframe_system::config_preludes::TestDefaultConfig)] impl pezframe_system::Config for Runtime { type BaseCallFilter = pezframe_support::traits::Everything; type Block = Block; type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; type RuntimeEvent = RuntimeEvent; type PalletInfo = PalletInfo; type OnSetCode = (); } impl module1::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; type SomeParameter = ConstU32<100>; type GenericType = u32; } impl module1::Config for Runtime { type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; type SomeParameter = ConstU32<100>; type GenericType = u32; } impl module2::Config for Runtime { type Amount = u16; type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; } impl module2::Config for Runtime { type Amount = u32; type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; } impl module2::Config for Runtime { type Amount = u32; type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; } impl module2::Config for Runtime { type Amount = u64; type RuntimeEvent = RuntimeEvent; type RuntimeOrigin = RuntimeOrigin; } impl module3::Config for Runtime { type Currency = Module2_2; type Currency2 = Module2_3; } fn new_test_ext() -> pezsp_io::TestExternalities { RuntimeGenesisConfig { system: Default::default(), module_1_1: module1::GenesisConfig { value: 3, test: 2 }, module_1_2: module1::GenesisConfig { value: 4, test: 5 }, module_2: module2::GenesisConfig { value: 4, map: vec![(0, 0)], double_map: vec![(0, 0, 0)], }, module_2_1: module2::GenesisConfig { value: 4, map: vec![(0, 0)], double_map: vec![(0, 0, 0)], }, module_2_2: Default::default(), module_2_3: Default::default(), } .build_storage() .unwrap() .into() } #[test] fn storage_instance_independence() { let mut storage = pezsp_core::storage::Storage { top: std::collections::BTreeMap::new(), children_default: std::collections::HashMap::new(), }; pezsp_state_machine::BasicExternalities::execute_with_storage(&mut storage, || { module2::Value::::put(0); module2::Value::::put(0); module2::Value::::put(0); module2::Value::::put(0); module2::Map::::insert(0, 0); module2::Map::::insert(0, 0); module2::Map::::insert(0, 0); module2::Map::::insert(0, 0); module2::DoubleMap::::insert(&0, &0, &0); module2::DoubleMap::::insert(&0, &0, &0); module2::DoubleMap::::insert(&0, &0, &0); module2::DoubleMap::::insert(&0, &0, &0); }); // 12 storage values. assert_eq!(storage.top.len(), 12); } #[test] fn storage_with_instance_basic_operation() { new_test_ext().execute_with(|| { type Value = module2::Value; type Map = module2::Map; type DoubleMap = module2::DoubleMap; assert_eq!(Value::exists(), true); assert_eq!(Value::get(), 4); Value::put(1); assert_eq!(Value::get(), 1); assert_eq!(Value::take(), 1); assert_eq!(Value::get(), 0); Value::mutate(|a| *a = 2); assert_eq!(Value::get(), 2); Value::kill(); assert_eq!(Value::exists(), false); assert_eq!(Value::get(), 0); let key = 1; assert_eq!(Map::contains_key(0), true); assert_eq!(Map::contains_key(key), false); Map::insert(key, 1); assert_eq!(Map::get(key), 1); assert_eq!(Map::take(key), 1); assert_eq!(Map::get(key), 0); Map::mutate(key, |a| *a = 2); assert_eq!(Map::get(key), 2); Map::remove(key); assert_eq!(Map::contains_key(key), false); assert_eq!(Map::get(key), 0); let key1 = 1; let key2 = 1; assert_eq!(DoubleMap::contains_key(&0, &0), true); assert_eq!(DoubleMap::contains_key(&key1, &key2), false); DoubleMap::insert(&key1, &key2, &1); assert_eq!(DoubleMap::get(&key1, &key2), 1); assert_eq!(DoubleMap::take(&key1, &key2), 1); assert_eq!(DoubleMap::get(&key1, &key2), 0); DoubleMap::mutate(&key1, &key2, |a| *a = 2); assert_eq!(DoubleMap::get(&key1, &key2), 2); DoubleMap::remove(&key1, &key2); assert_eq!(DoubleMap::get(&key1, &key2), 0); }); } fn expected_metadata() -> PalletStorageMetadataIR { PalletStorageMetadataIR { prefix: "Module2_2", entries: vec![ StorageEntryMetadataIR { name: "Value", modifier: StorageEntryModifierIR::Default, ty: StorageEntryTypeIR::Plain(scale_info::meta_type::()), default: vec![0, 0, 0, 0], docs: vec![], deprecation_info: pezsp_metadata_ir::ItemDeprecationInfoIR::NotDeprecated, }, StorageEntryMetadataIR { name: "Map", modifier: StorageEntryModifierIR::Default, ty: StorageEntryTypeIR::Map { hashers: vec![StorageHasherIR::Identity], key: scale_info::meta_type::(), value: scale_info::meta_type::(), }, default: [0u8; 8].to_vec(), docs: vec![], deprecation_info: pezsp_metadata_ir::ItemDeprecationInfoIR::NotDeprecated, }, StorageEntryMetadataIR { name: "DoubleMap", modifier: StorageEntryModifierIR::Default, ty: StorageEntryTypeIR::Map { hashers: vec![StorageHasherIR::Identity, StorageHasherIR::Identity], key: scale_info::meta_type::<(u64, u64)>(), value: scale_info::meta_type::(), }, default: [0u8; 8].to_vec(), docs: vec![], deprecation_info: pezsp_metadata_ir::ItemDeprecationInfoIR::NotDeprecated, }, ], } } #[test] fn test_instance_storage_metadata() { let metadata = Module2_2::storage_metadata(); pretty_assertions::assert_eq!(expected_metadata(), metadata); }