git.delta.rocks / unique-network / refs/commits / 1cc33de4c839

difftreelog

added the ability to configure pallet `app-promotion` via the `configuration` palette

PraetorP2022-12-13parent: #966149d.patch.diff
in: master

14 files changed

modifiedCargo.lockdiffbeforeafterboth
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5524,13 +5524,14 @@
 
 [[package]]
 name = "pallet-app-promotion"
-version = "0.1.0"
+version = "0.1.1"
 dependencies = [
  "frame-benchmarking",
  "frame-support",
  "frame-system",
  "pallet-balances",
  "pallet-common",
+ "pallet-configuration",
  "pallet-evm",
  "pallet-evm-contract-helpers",
  "pallet-evm-migration",
@@ -5784,7 +5785,7 @@
 
 [[package]]
 name = "pallet-configuration"
-version = "0.1.1"
+version = "0.1.2"
 dependencies = [
  "fp-evm",
  "frame-support",
addedpallets/app-promotion/CHANGELOG.mddiffbeforeafterboth
--- /dev/null
+++ b/pallets/app-promotion/CHANGELOG.md
@@ -0,0 +1,11 @@
+# Change Log
+
+All notable changes to this project will be documented in this file.
+
+<!-- bureaucrate goes here -->
+
+## [0.1.1] - 2022-12-13
+
+### Added
+
+- The ability to configure pallet `app-promotion` via the `configuration` palette
modifiedpallets/app-promotion/Cargo.tomldiffbeforeafterboth
--- a/pallets/app-promotion/Cargo.toml
+++ b/pallets/app-promotion/Cargo.toml
@@ -9,7 +9,7 @@
 license = 'GPLv3'
 name = 'pallet-app-promotion'
 repository = 'https://github.com/UniqueNetwork/unique-chain'
-version = '0.1.0'
+version = '0.1.1'
 
 [package.metadata.docs.rs]
 targets = ['x86_64-unknown-linux-gnu']
@@ -68,6 +68,7 @@
 
 up-data-structs = { default-features = false, path = "../../primitives/data-structs" }
 pallet-common = { default-features = false, path = "../common" }
+pallet-configuration = { default-features = false, path = "../configuration" }
 pallet-unique = { default-features = false, path = "../unique" }
 pallet-evm-contract-helpers = { default-features = false, path = "../evm-contract-helpers" }
 pallet-evm-migration = { default-features = false, path = "../evm-migration" }
modifiedpallets/app-promotion/src/lib.rsdiffbeforeafterboth
--- a/pallets/app-promotion/src/lib.rs
+++ b/pallets/app-promotion/src/lib.rs
@@ -102,7 +102,9 @@
 	use frame_system::pallet_prelude::*;
 
 	#[pallet::config]
-	pub trait Config: frame_system::Config + pallet_evm::Config {
+	pub trait Config:
+		frame_system::Config + pallet_evm::Config + pallet_configuration::Config
+	{
 		/// Type to interact with the native token
 		type Currency: ExtendedLockableCurrency<Self::AccountId>
 			+ ReservableCurrency<Self::AccountId>;
@@ -330,6 +332,7 @@
 				amount >= <BalanceOf<T>>::from(100u128) * T::Nominal::get(),
 				ArithmeticError::Underflow
 			);
+			let config = <PalletConfiguration<T>>::get();
 
 			let balance =
 				<<T as Config>::Currency as Currency<T::AccountId>>::free_balance(&staker_id);
@@ -351,7 +354,7 @@
 			// Calculation of the number of recalculation periods,
 			// after how much the first interest calculation should be performed for the stake
 			let recalculate_after_interval: T::BlockNumber =
-				if block_number % T::RecalculationInterval::get() == 0u32.into() {
+				if block_number % config.recalculation_interval == 0u32.into() {
 					1u32.into()
 				} else {
 					2u32.into()
@@ -359,9 +362,9 @@
 
 			// Сalculation of the number of the relay block
 			// in which it is necessary to accrue remuneration for the stake.
-			let recalc_block = (block_number / T::RecalculationInterval::get()
+			let recalc_block = (block_number / config.recalculation_interval
 				+ recalculate_after_interval)
-				* T::RecalculationInterval::get();
+				* config.recalculation_interval;
 
 			<Staked<T>>::insert((&staker_id, block_number), {
 				let mut balance_and_recalc_block = <Staked<T>>::get((&staker_id, block_number));
@@ -393,9 +396,10 @@
 		#[pallet::weight(<T as Config>::WeightInfo::unstake())]
 		pub fn unstake(staker: OriginFor<T>) -> DispatchResultWithPostInfo {
 			let staker_id = ensure_signed(staker)?;
+			let config = <PalletConfiguration<T>>::get();
 
 			// calculate block number where the sum would be free
-			let block = <frame_system::Pallet<T>>::block_number() + T::PendingInterval::get();
+			let block = <frame_system::Pallet<T>>::block_number() + config.pending_interval;
 
 			let mut pendings = <PendingUnstake<T>>::get(block);
 
@@ -568,15 +572,25 @@
 				admin_id == Admin::<T>::get().ok_or(Error::<T>::AdminNotSet)?,
 				Error::<T>::NoPermission
 			);
+			let config = <PalletConfiguration<T>>::get();
 
+			let mut stakers_number = stakers_number.unwrap_or(DEFAULT_NUMBER_PAYOUTS);
+
+			ensure!(
+				stakers_number <= config.max_stakers_per_calculation,
+				Error::<T>::NoPermission
+			);
+
 			// calculate the number of the current recalculation block,
 			// this is necessary in order to understand which stakers we should calculate interest
-			let current_recalc_block =
-				Self::get_current_recalc_block(T::RelayBlockNumberProvider::current_block_number());
+			let current_recalc_block = Self::get_current_recalc_block(
+				T::RelayBlockNumberProvider::current_block_number(),
+				&config,
+			);
 
 			// calculate the number of the next recalculation block,
 			// this value is set for the stakers to whom the recalculation will be performed
-			let next_recalc_block = current_recalc_block + T::RecalculationInterval::get();
+			let next_recalc_block = current_recalc_block + config.recalculation_interval;
 
 			let mut storage_iterator = Self::get_next_calculated_key()
 				.map_or(Staked::<T>::iter(), |key| Staked::<T>::iter_from(key));
@@ -584,7 +598,6 @@
 			NextCalculatedRecord::<T>::set(None);
 
 			{
-				let mut stakers_number = stakers_number.unwrap_or(20);
 				let last_id = RefCell::new(None);
 				let income_acc = RefCell::new(BalanceOf::<T>::default());
 				let amount_acc = RefCell::new(BalanceOf::<T>::default());
@@ -644,8 +657,8 @@
 							next_recalc_block,
 							amount,
 							((current_recalc_block - next_recalc_block_for_stake)
-								/ T::RecalculationInterval::get())
-							.into() + 1,
+								/ config.recalculation_interval)
+								.into() + 1,
 							&mut *income_acc.borrow_mut(),
 						);
 					}
@@ -810,15 +823,19 @@
 	where
 		I: EncodeLike<BalanceOf<T>> + Balance,
 	{
+		let config = <PalletConfiguration<T>>::get();
 		let mut income = base;
 
-		(0..iters).for_each(|_| income += T::IntervalIncome::get() * income);
+		(0..iters).for_each(|_| income += config.interval_income * income);
 
 		income - base
 	}
 
-	fn get_current_recalc_block(current_relay_block: T::BlockNumber) -> T::BlockNumber {
-		(current_relay_block / T::RecalculationInterval::get()) * T::RecalculationInterval::get()
+	fn get_current_recalc_block(
+		current_relay_block: T::BlockNumber,
+		config: &PalletConfiguration<T>,
+	) -> T::BlockNumber {
+		(current_relay_block / config.recalculation_interval) * config.recalculation_interval
 	}
 
 	fn get_next_calculated_key() -> Option<Vec<u8>> {
modifiedpallets/app-promotion/src/types.rsdiffbeforeafterboth
--- a/pallets/app-promotion/src/types.rs
+++ b/pallets/app-promotion/src/types.rs
@@ -4,10 +4,15 @@
 use pallet_balances::{BalanceLock, Config as BalancesConfig, Pallet as PalletBalances};
 use pallet_common::CollectionHandle;
 
-use sp_runtime::DispatchError;
+use sp_runtime::{DispatchError, Perbill};
 use up_data_structs::{CollectionId};
 use sp_std::borrow::ToOwned;
 use pallet_evm_contract_helpers::{Pallet as EvmHelpersPallet, Config as EvmHelpersConfig};
+use pallet_configuration::{AppPromomotionConfigurationOverride};
+use sp_core::Get;
+
+const MAX_NUMBER_PAYOUTS: u8 = 100;
+pub(crate) const DEFAULT_NUMBER_PAYOUTS: u8 = 20;
 
 /// This trait was defined because `LockableCurrency`
 /// has no way to know the state of the lock for an account.
@@ -128,3 +133,24 @@
 		Ok(Self::get_sponsor(contract_address))
 	}
 }
+pub(crate) struct PalletConfiguration<T: crate::Config> {
+	/// In relay blocks.
+	pub recalculation_interval: T::BlockNumber,
+	/// In parachain blocks.
+	pub pending_interval: T::BlockNumber,
+	/// Value for `RecalculationInterval` based on 0.05% per 24h.
+	pub interval_income: Perbill,
+	/// Maximum allowable number of stakers calculated per call of the `app-promotion::PayoutStakers` extrinsic.
+	pub max_stakers_per_calculation: u8,
+}
+impl<T: crate::Config> PalletConfiguration<T> {
+	pub fn get() -> Self {
+		let config = <AppPromomotionConfigurationOverride<T>>::get().unwrap_or_default();
+		Self {
+			recalculation_interval: config.0.unwrap_or(T::RecalculationInterval::get()),
+			pending_interval: config.2.unwrap_or(T::PendingInterval::get()),
+			interval_income: config.1.unwrap_or(T::IntervalIncome::get()),
+			max_stakers_per_calculation: config.3.unwrap_or(MAX_NUMBER_PAYOUTS),
+		}
+	}
+}
modifiedpallets/configuration/CHANGELOG.mddiffbeforeafterboth
--- a/pallets/configuration/CHANGELOG.md
+++ b/pallets/configuration/CHANGELOG.md
@@ -1,4 +1,10 @@
 <!-- bureaucrate goes here -->
+## [0.1.2] - 2022-12-13
+
+### Added
+
+- The ability to configure pallet `app-promotion` via the `configuration` palette
+
 ## [v0.1.1] 2022-08-16
 
 ### Other changes
modifiedpallets/configuration/Cargo.tomldiffbeforeafterboth
--- a/pallets/configuration/Cargo.toml
+++ b/pallets/configuration/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "pallet-configuration"
-version = "0.1.1"
+version = "0.1.2"
 edition = "2021"
 
 [dependencies]
modifiedpallets/configuration/src/lib.rsdiffbeforeafterboth
--- a/pallets/configuration/src/lib.rs
+++ b/pallets/configuration/src/lib.rs
@@ -51,6 +51,10 @@
 
 		#[pallet::constant]
 		type MaxOverridedAllowedLocations: Get<u32>;
+		#[pallet::constant]
+		type AppPromotionDailyRate: Get<Perbill>;
+		#[pallet::constant]
+		type DayRelayBlocks: Get<Self::BlockNumber>;
 	}
 
 	#[pallet::storage]
@@ -70,6 +74,17 @@
 		QueryKind = OptionQuery,
 	>;
 
+	#[pallet::storage]
+	pub type AppPromomotionConfigurationOverride<T: Config> = StorageValue<
+		Value = (
+			Option<T::BlockNumber>,
+			Option<Perbill>,
+			Option<T::BlockNumber>,
+			Option<u8>,
+		),
+		QueryKind = OptionQuery,
+	>;
+
 	#[pallet::call]
 	impl<T: Config> Pallet<T> {
 		#[pallet::weight(T::DbWeight::get().writes(1))]
@@ -109,6 +124,39 @@
 			<XcmAllowedLocationsOverride<T>>::set(locations);
 			Ok(())
 		}
+
+		#[pallet::weight(T::DbWeight::get().writes(1))]
+		pub fn set_app_promotion_configuration_override(
+			origin: OriginFor<T>,
+			recalculation_interval: Option<T::BlockNumber>,
+			pending_interval: Option<T::BlockNumber>,
+			stakers_payout_limit: Option<u8>,
+		) -> DispatchResult {
+			let _sender = ensure_root(origin)?;
+
+			if recalculation_interval.is_none()
+				&& pending_interval.is_none()
+				&& stakers_payout_limit.is_none()
+			{
+				<AppPromomotionConfigurationOverride<T>>::kill();
+			} else {
+				let mut current_config =
+					<AppPromomotionConfigurationOverride<T>>::take().unwrap_or_default();
+
+				recalculation_interval.map(|b| {
+					current_config.0 = Some(b);
+					current_config.1 = Some(
+						Perbill::from_rational(b, T::DayRelayBlocks::get())
+							* T::AppPromotionDailyRate::get(),
+					)
+				});
+				pending_interval.map(|b| current_config.2 = Some(b));
+				stakers_payout_limit.map(|p| current_config.3 = Some(p));
+				<AppPromomotionConfigurationOverride<T>>::set(Some(current_config));
+			}
+
+			Ok(())
+		}
 	}
 
 	#[pallet::pallet]
modifiedruntime/common/config/pallets/app_promotion.rsdiffbeforeafterboth
--- a/runtime/common/config/pallets/app_promotion.rs
+++ b/runtime/common/config/pallets/app_promotion.rs
@@ -26,16 +26,6 @@
 	types::Balance,
 };
 
-#[cfg(all(not(feature = "unique-runtime"), not(feature = "quartz-runtime")))]
-parameter_types! {
-	pub const AppPromotionId: PalletId = PalletId(*b"appstake");
-	pub const RecalculationInterval: BlockNumber = 8;
-	pub const PendingInterval: BlockNumber = 4;
-	pub const Nominal: Balance = UNIQUE;
-	pub IntervalIncome: Perbill = Perbill::from_rational(RecalculationInterval::get(), RELAY_DAYS) * Perbill::from_rational(5u32, 10_000);
-}
-
-#[cfg(any(feature = "unique-runtime", feature = "quartz-runtime"))]
 parameter_types! {
 	pub const AppPromotionId: PalletId = PalletId(*b"appstake");
 	pub const RecalculationInterval: BlockNumber = RELAY_DAYS;
modifiedruntime/common/config/pallets/mod.rsdiffbeforeafterboth
--- a/runtime/common/config/pallets/mod.rs
+++ b/runtime/common/config/pallets/mod.rs
@@ -33,6 +33,7 @@
 use up_data_structs::{
 	mapping::{EvmTokenAddressMapping, CrossTokenAddressMapping},
 };
+use sp_arithmetic::Perbill;
 
 #[cfg(feature = "rmrk")]
 pub mod rmrk;
@@ -98,10 +99,16 @@
 	type RefungibleExtensionsWeightInfo = CommonWeights<Self>;
 }
 
+parameter_types! {
+	pub AppPromotionDailyRate: Perbill = Perbill::from_rational(5u32, 10_000);
+	pub const DayRelayBlocks: BlockNumber = RELAY_DAYS;
+}
 impl pallet_configuration::Config for Runtime {
 	type DefaultWeightToFeeCoefficient = ConstU32<{ up_common::constants::WEIGHT_TO_FEE_COEFF }>;
 	type DefaultMinGasPrice = ConstU64<{ up_common::constants::MIN_GAS_PRICE }>;
 	type MaxOverridedAllowedLocations = ConstU32<16>;
+	type AppPromotionDailyRate = AppPromotionDailyRate;
+	type DayRelayBlocks = DayRelayBlocks;
 }
 
 impl pallet_maintenance::Config for Runtime {
modifiedtests/src/app-promotion.test.tsdiffbeforeafterboth
--- a/tests/src/app-promotion.test.ts
+++ b/tests/src/app-promotion.test.ts
@@ -31,11 +31,14 @@
   before(async function () {
     await usingPlaygrounds(async (helper, privateKey) => {
       requirePalletsOrSkip(this, helper, [Pallets.AppPromotion]);
+      const alice = await privateKey('//Alice');
       donor = await privateKey({filename: __filename});
       palletAddress = helper.arrange.calculatePalletAddress('appstake');
       palletAdmin = await privateKey('//PromotionAdmin');
       nominal = helper.balance.getOneTokenNominal();
       accounts = await helper.arrange.createCrowd(100, 1000n, donor); // create accounts-pool to speed up tests
+      const api = helper.getApi();
+      await helper.signTransaction(alice, api.tx.sudo.sudo(api.tx.configuration.setAppPromotionConfigurationOverride(LOCKING_PERIOD, UNLOCKING_PERIOD, null)));
     });
   });
 
modifiedtests/src/interfaces/augment-api-consts.tsdiffbeforeafterboth
before · tests/src/interfaces/augment-api-consts.ts
1// Auto-generated via `yarn polkadot-types-from-chain`, do not edit2/* eslint-disable */34// import type lookup before we augment - in some environments5// this is required to allow for ambient/previous definitions6import '@polkadot/api-base/types/consts';78import type { ApiTypes, AugmentedConst } from '@polkadot/api-base/types';9import type { Option, u128, u16, u32, u64, u8 } from '@polkadot/types-codec';10import type { Codec } from '@polkadot/types-codec/types';11import type { H160, Perbill, Permill } from '@polkadot/types/interfaces/runtime';12import type { FrameSupportPalletId, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, SpVersionRuntimeVersion, SpWeightsRuntimeDbWeight, SpWeightsWeightV2Weight, UpDataStructsCollectionLimits, XcmV1MultiLocation } from '@polkadot/types/lookup';1314export type __AugmentedConst<ApiType extends ApiTypes> = AugmentedConst<ApiType>;1516declare module '@polkadot/api-base/types/consts' {17  interface AugmentedConsts<ApiType extends ApiTypes> {18    appPromotion: {19      /**20       * Rate of return for interval in blocks defined in `RecalculationInterval`.21       **/22      intervalIncome: Perbill & AugmentedConst<ApiType>;23      /**24       * Decimals for the `Currency`.25       **/26      nominal: u128 & AugmentedConst<ApiType>;27      /**28       * The app's pallet id, used for deriving its sovereign account address.29       **/30      palletId: FrameSupportPalletId & AugmentedConst<ApiType>;31      /**32       * In parachain blocks.33       **/34      pendingInterval: u32 & AugmentedConst<ApiType>;35      /**36       * In relay blocks.37       **/38      recalculationInterval: u32 & AugmentedConst<ApiType>;39      /**40       * Generic const41       **/42      [key: string]: Codec;43    };44    balances: {45      /**46       * The minimum amount required to keep an account open.47       **/48      existentialDeposit: u128 & AugmentedConst<ApiType>;49      /**50       * The maximum number of locks that should exist on an account.51       * Not strictly enforced, but used for weight estimation.52       **/53      maxLocks: u32 & AugmentedConst<ApiType>;54      /**55       * The maximum number of named reserves that can exist on an account.56       **/57      maxReserves: u32 & AugmentedConst<ApiType>;58      /**59       * Generic const60       **/61      [key: string]: Codec;62    };63    common: {64      /**65       * Maximum admins per collection.66       **/67      collectionAdminsLimit: u32 & AugmentedConst<ApiType>;68      /**69       * Set price to create a collection.70       **/71      collectionCreationPrice: u128 & AugmentedConst<ApiType>;72      /**73       * Address under which the CollectionHelper contract would be available.74       **/75      contractAddress: H160 & AugmentedConst<ApiType>;76      /**77       * Generic const78       **/79      [key: string]: Codec;80    };81    configuration: {82      defaultMinGasPrice: u64 & AugmentedConst<ApiType>;83      defaultWeightToFeeCoefficient: u32 & AugmentedConst<ApiType>;84      maxOverridedAllowedLocations: u32 & AugmentedConst<ApiType>;85      /**86       * Generic const87       **/88      [key: string]: Codec;89    };90    evmContractHelpers: {91      /**92       * Address, under which magic contract will be available93       **/94      contractAddress: H160 & AugmentedConst<ApiType>;95      /**96       * Generic const97       **/98      [key: string]: Codec;99    };100    inflation: {101      /**102       * Number of blocks that pass between treasury balance updates due to inflation103       **/104      inflationBlockInterval: u32 & AugmentedConst<ApiType>;105      /**106       * Generic const107       **/108      [key: string]: Codec;109    };110    scheduler: {111      /**112       * The maximum weight that may be scheduled per block for any dispatchables.113       **/114      maximumWeight: SpWeightsWeightV2Weight & AugmentedConst<ApiType>;115      /**116       * The maximum number of scheduled calls in the queue for a single block.117       **/118      maxScheduledPerBlock: u32 & AugmentedConst<ApiType>;119      /**120       * Generic const121       **/122      [key: string]: Codec;123    };124    system: {125      /**126       * Maximum number of block number to block hash mappings to keep (oldest pruned first).127       **/128      blockHashCount: u32 & AugmentedConst<ApiType>;129      /**130       * The maximum length of a block (in bytes).131       **/132      blockLength: FrameSystemLimitsBlockLength & AugmentedConst<ApiType>;133      /**134       * Block & extrinsics weights: base values and limits.135       **/136      blockWeights: FrameSystemLimitsBlockWeights & AugmentedConst<ApiType>;137      /**138       * The weight of runtime database operations the runtime can invoke.139       **/140      dbWeight: SpWeightsRuntimeDbWeight & AugmentedConst<ApiType>;141      /**142       * The designated SS58 prefix of this chain.143       * 144       * This replaces the "ss58Format" property declared in the chain spec. Reason is145       * that the runtime should know about the prefix in order to make use of it as146       * an identifier of the chain.147       **/148      ss58Prefix: u16 & AugmentedConst<ApiType>;149      /**150       * Get the chain's current version.151       **/152      version: SpVersionRuntimeVersion & AugmentedConst<ApiType>;153      /**154       * Generic const155       **/156      [key: string]: Codec;157    };158    timestamp: {159      /**160       * The minimum period between blocks. Beware that this is different to the *expected*161       * period that the block production apparatus provides. Your chosen consensus system will162       * generally work with this to determine a sensible block time. e.g. For Aura, it will be163       * double this period on default settings.164       **/165      minimumPeriod: u64 & AugmentedConst<ApiType>;166      /**167       * Generic const168       **/169      [key: string]: Codec;170    };171    tokens: {172      maxLocks: u32 & AugmentedConst<ApiType>;173      /**174       * The maximum number of named reserves that can exist on an account.175       **/176      maxReserves: u32 & AugmentedConst<ApiType>;177      /**178       * Generic const179       **/180      [key: string]: Codec;181    };182    transactionPayment: {183      /**184       * A fee mulitplier for `Operational` extrinsics to compute "virtual tip" to boost their185       * `priority`186       * 187       * This value is multipled by the `final_fee` to obtain a "virtual tip" that is later188       * added to a tip component in regular `priority` calculations.189       * It means that a `Normal` transaction can front-run a similarly-sized `Operational`190       * extrinsic (with no tip), by including a tip value greater than the virtual tip.191       * 192       * ```rust,ignore193       * // For `Normal`194       * let priority = priority_calc(tip);195       * 196       * // For `Operational`197       * let virtual_tip = (inclusion_fee + tip) * OperationalFeeMultiplier;198       * let priority = priority_calc(tip + virtual_tip);199       * ```200       * 201       * Note that since we use `final_fee` the multiplier applies also to the regular `tip`202       * sent with the transaction. So, not only does the transaction get a priority bump based203       * on the `inclusion_fee`, but we also amplify the impact of tips applied to `Operational`204       * transactions.205       **/206      operationalFeeMultiplier: u8 & AugmentedConst<ApiType>;207      /**208       * Generic const209       **/210      [key: string]: Codec;211    };212    treasury: {213      /**214       * Percentage of spare funds (if any) that are burnt per spend period.215       **/216      burn: Permill & AugmentedConst<ApiType>;217      /**218       * The maximum number of approvals that can wait in the spending queue.219       * 220       * NOTE: This parameter is also used within the Bounties Pallet extension if enabled.221       **/222      maxApprovals: u32 & AugmentedConst<ApiType>;223      /**224       * The treasury's pallet id, used for deriving its sovereign account ID.225       **/226      palletId: FrameSupportPalletId & AugmentedConst<ApiType>;227      /**228       * Fraction of a proposal's value that should be bonded in order to place the proposal.229       * An accepted proposal gets these back. A rejected proposal does not.230       **/231      proposalBond: Permill & AugmentedConst<ApiType>;232      /**233       * Maximum amount of funds that should be placed in a deposit for making a proposal.234       **/235      proposalBondMaximum: Option<u128> & AugmentedConst<ApiType>;236      /**237       * Minimum amount of funds that should be placed in a deposit for making a proposal.238       **/239      proposalBondMinimum: u128 & AugmentedConst<ApiType>;240      /**241       * Period between successive spends.242       **/243      spendPeriod: u32 & AugmentedConst<ApiType>;244      /**245       * Generic const246       **/247      [key: string]: Codec;248    };249    unique: {250      /**251       * Maximum admins per collection.252       **/253      collectionAdminsLimit: u32 & AugmentedConst<ApiType>;254      /**255       * Default FT collection limit.256       **/257      ftDefaultCollectionLimits: UpDataStructsCollectionLimits & AugmentedConst<ApiType>;258      /**259       * Maximal length of a collection description.260       **/261      maxCollectionDescriptionLength: u32 & AugmentedConst<ApiType>;262      /**263       * Maximal length of a collection name.264       **/265      maxCollectionNameLength: u32 & AugmentedConst<ApiType>;266      /**267       * Maximum size for all collection properties.268       **/269      maxCollectionPropertiesSize: u32 & AugmentedConst<ApiType>;270      /**271       * A maximum number of token properties.272       **/273      maxPropertiesPerItem: u32 & AugmentedConst<ApiType>;274      /**275       * Maximal length of a property key.276       **/277      maxPropertyKeyLength: u32 & AugmentedConst<ApiType>;278      /**279       * Maximal length of a property value.280       **/281      maxPropertyValueLength: u32 & AugmentedConst<ApiType>;282      /**283       * Maximal length of a token prefix.284       **/285      maxTokenPrefixLength: u32 & AugmentedConst<ApiType>;286      /**287       * Maximum size of all token properties.288       **/289      maxTokenPropertiesSize: u32 & AugmentedConst<ApiType>;290      /**291       * A maximum number of levels of depth in the token nesting tree.292       **/293      nestingBudget: u32 & AugmentedConst<ApiType>;294      /**295       * Default NFT collection limit.296       **/297      nftDefaultCollectionLimits: UpDataStructsCollectionLimits & AugmentedConst<ApiType>;298      /**299       * Default RFT collection limit.300       **/301      rftDefaultCollectionLimits: UpDataStructsCollectionLimits & AugmentedConst<ApiType>;302      /**303       * Generic const304       **/305      [key: string]: Codec;306    };307    vesting: {308      /**309       * The minimum amount transferred to call `vested_transfer`.310       **/311      minVestedTransfer: u128 & AugmentedConst<ApiType>;312      /**313       * Generic const314       **/315      [key: string]: Codec;316    };317    xTokens: {318      /**319       * Base XCM weight.320       * 321       * The actually weight for an XCM message is `T::BaseXcmWeight +322       * T::Weigher::weight(&msg)`.323       **/324      baseXcmWeight: u64 & AugmentedConst<ApiType>;325      /**326       * Self chain location.327       **/328      selfLocation: XcmV1MultiLocation & AugmentedConst<ApiType>;329      /**330       * Generic const331       **/332      [key: string]: Codec;333    };334  } // AugmentedConsts335} // declare module
after · tests/src/interfaces/augment-api-consts.ts
1// Auto-generated via `yarn polkadot-types-from-chain`, do not edit2/* eslint-disable */34// import type lookup before we augment - in some environments5// this is required to allow for ambient/previous definitions6import '@polkadot/api-base/types/consts';78import type { ApiTypes, AugmentedConst } from '@polkadot/api-base/types';9import type { Option, u128, u16, u32, u64, u8 } from '@polkadot/types-codec';10import type { Codec } from '@polkadot/types-codec/types';11import type { H160, Perbill, Permill } from '@polkadot/types/interfaces/runtime';12import type { FrameSupportPalletId, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, SpVersionRuntimeVersion, SpWeightsRuntimeDbWeight, SpWeightsWeightV2Weight, UpDataStructsCollectionLimits, XcmV1MultiLocation } from '@polkadot/types/lookup';1314export type __AugmentedConst<ApiType extends ApiTypes> = AugmentedConst<ApiType>;1516declare module '@polkadot/api-base/types/consts' {17  interface AugmentedConsts<ApiType extends ApiTypes> {18    appPromotion: {19      /**20       * Rate of return for interval in blocks defined in `RecalculationInterval`.21       **/22      intervalIncome: Perbill & AugmentedConst<ApiType>;23      /**24       * Decimals for the `Currency`.25       **/26      nominal: u128 & AugmentedConst<ApiType>;27      /**28       * The app's pallet id, used for deriving its sovereign account address.29       **/30      palletId: FrameSupportPalletId & AugmentedConst<ApiType>;31      /**32       * In parachain blocks.33       **/34      pendingInterval: u32 & AugmentedConst<ApiType>;35      /**36       * In relay blocks.37       **/38      recalculationInterval: u32 & AugmentedConst<ApiType>;39      /**40       * Generic const41       **/42      [key: string]: Codec;43    };44    balances: {45      /**46       * The minimum amount required to keep an account open.47       **/48      existentialDeposit: u128 & AugmentedConst<ApiType>;49      /**50       * The maximum number of locks that should exist on an account.51       * Not strictly enforced, but used for weight estimation.52       **/53      maxLocks: u32 & AugmentedConst<ApiType>;54      /**55       * The maximum number of named reserves that can exist on an account.56       **/57      maxReserves: u32 & AugmentedConst<ApiType>;58      /**59       * Generic const60       **/61      [key: string]: Codec;62    };63    common: {64      /**65       * Maximum admins per collection.66       **/67      collectionAdminsLimit: u32 & AugmentedConst<ApiType>;68      /**69       * Set price to create a collection.70       **/71      collectionCreationPrice: u128 & AugmentedConst<ApiType>;72      /**73       * Address under which the CollectionHelper contract would be available.74       **/75      contractAddress: H160 & AugmentedConst<ApiType>;76      /**77       * Generic const78       **/79      [key: string]: Codec;80    };81    configuration: {82      appPromotionDailyRate: Perbill & AugmentedConst<ApiType>;83      dayRelayBlocks: u32 & AugmentedConst<ApiType>;84      defaultMinGasPrice: u64 & AugmentedConst<ApiType>;85      defaultWeightToFeeCoefficient: u32 & AugmentedConst<ApiType>;86      maxOverridedAllowedLocations: u32 & AugmentedConst<ApiType>;87      /**88       * Generic const89       **/90      [key: string]: Codec;91    };92    evmContractHelpers: {93      /**94       * Address, under which magic contract will be available95       **/96      contractAddress: H160 & AugmentedConst<ApiType>;97      /**98       * Generic const99       **/100      [key: string]: Codec;101    };102    inflation: {103      /**104       * Number of blocks that pass between treasury balance updates due to inflation105       **/106      inflationBlockInterval: u32 & AugmentedConst<ApiType>;107      /**108       * Generic const109       **/110      [key: string]: Codec;111    };112    scheduler: {113      /**114       * The maximum weight that may be scheduled per block for any dispatchables.115       **/116      maximumWeight: SpWeightsWeightV2Weight & AugmentedConst<ApiType>;117      /**118       * The maximum number of scheduled calls in the queue for a single block.119       **/120      maxScheduledPerBlock: u32 & AugmentedConst<ApiType>;121      /**122       * Generic const123       **/124      [key: string]: Codec;125    };126    system: {127      /**128       * Maximum number of block number to block hash mappings to keep (oldest pruned first).129       **/130      blockHashCount: u32 & AugmentedConst<ApiType>;131      /**132       * The maximum length of a block (in bytes).133       **/134      blockLength: FrameSystemLimitsBlockLength & AugmentedConst<ApiType>;135      /**136       * Block & extrinsics weights: base values and limits.137       **/138      blockWeights: FrameSystemLimitsBlockWeights & AugmentedConst<ApiType>;139      /**140       * The weight of runtime database operations the runtime can invoke.141       **/142      dbWeight: SpWeightsRuntimeDbWeight & AugmentedConst<ApiType>;143      /**144       * The designated SS58 prefix of this chain.145       * 146       * This replaces the "ss58Format" property declared in the chain spec. Reason is147       * that the runtime should know about the prefix in order to make use of it as148       * an identifier of the chain.149       **/150      ss58Prefix: u16 & AugmentedConst<ApiType>;151      /**152       * Get the chain's current version.153       **/154      version: SpVersionRuntimeVersion & AugmentedConst<ApiType>;155      /**156       * Generic const157       **/158      [key: string]: Codec;159    };160    timestamp: {161      /**162       * The minimum period between blocks. Beware that this is different to the *expected*163       * period that the block production apparatus provides. Your chosen consensus system will164       * generally work with this to determine a sensible block time. e.g. For Aura, it will be165       * double this period on default settings.166       **/167      minimumPeriod: u64 & AugmentedConst<ApiType>;168      /**169       * Generic const170       **/171      [key: string]: Codec;172    };173    tokens: {174      maxLocks: u32 & AugmentedConst<ApiType>;175      /**176       * The maximum number of named reserves that can exist on an account.177       **/178      maxReserves: u32 & AugmentedConst<ApiType>;179      /**180       * Generic const181       **/182      [key: string]: Codec;183    };184    transactionPayment: {185      /**186       * A fee mulitplier for `Operational` extrinsics to compute "virtual tip" to boost their187       * `priority`188       * 189       * This value is multipled by the `final_fee` to obtain a "virtual tip" that is later190       * added to a tip component in regular `priority` calculations.191       * It means that a `Normal` transaction can front-run a similarly-sized `Operational`192       * extrinsic (with no tip), by including a tip value greater than the virtual tip.193       * 194       * ```rust,ignore195       * // For `Normal`196       * let priority = priority_calc(tip);197       * 198       * // For `Operational`199       * let virtual_tip = (inclusion_fee + tip) * OperationalFeeMultiplier;200       * let priority = priority_calc(tip + virtual_tip);201       * ```202       * 203       * Note that since we use `final_fee` the multiplier applies also to the regular `tip`204       * sent with the transaction. So, not only does the transaction get a priority bump based205       * on the `inclusion_fee`, but we also amplify the impact of tips applied to `Operational`206       * transactions.207       **/208      operationalFeeMultiplier: u8 & AugmentedConst<ApiType>;209      /**210       * Generic const211       **/212      [key: string]: Codec;213    };214    treasury: {215      /**216       * Percentage of spare funds (if any) that are burnt per spend period.217       **/218      burn: Permill & AugmentedConst<ApiType>;219      /**220       * The maximum number of approvals that can wait in the spending queue.221       * 222       * NOTE: This parameter is also used within the Bounties Pallet extension if enabled.223       **/224      maxApprovals: u32 & AugmentedConst<ApiType>;225      /**226       * The treasury's pallet id, used for deriving its sovereign account ID.227       **/228      palletId: FrameSupportPalletId & AugmentedConst<ApiType>;229      /**230       * Fraction of a proposal's value that should be bonded in order to place the proposal.231       * An accepted proposal gets these back. A rejected proposal does not.232       **/233      proposalBond: Permill & AugmentedConst<ApiType>;234      /**235       * Maximum amount of funds that should be placed in a deposit for making a proposal.236       **/237      proposalBondMaximum: Option<u128> & AugmentedConst<ApiType>;238      /**239       * Minimum amount of funds that should be placed in a deposit for making a proposal.240       **/241      proposalBondMinimum: u128 & AugmentedConst<ApiType>;242      /**243       * Period between successive spends.244       **/245      spendPeriod: u32 & AugmentedConst<ApiType>;246      /**247       * Generic const248       **/249      [key: string]: Codec;250    };251    unique: {252      /**253       * Maximum admins per collection.254       **/255      collectionAdminsLimit: u32 & AugmentedConst<ApiType>;256      /**257       * Default FT collection limit.258       **/259      ftDefaultCollectionLimits: UpDataStructsCollectionLimits & AugmentedConst<ApiType>;260      /**261       * Maximal length of a collection description.262       **/263      maxCollectionDescriptionLength: u32 & AugmentedConst<ApiType>;264      /**265       * Maximal length of a collection name.266       **/267      maxCollectionNameLength: u32 & AugmentedConst<ApiType>;268      /**269       * Maximum size for all collection properties.270       **/271      maxCollectionPropertiesSize: u32 & AugmentedConst<ApiType>;272      /**273       * A maximum number of token properties.274       **/275      maxPropertiesPerItem: u32 & AugmentedConst<ApiType>;276      /**277       * Maximal length of a property key.278       **/279      maxPropertyKeyLength: u32 & AugmentedConst<ApiType>;280      /**281       * Maximal length of a property value.282       **/283      maxPropertyValueLength: u32 & AugmentedConst<ApiType>;284      /**285       * Maximal length of a token prefix.286       **/287      maxTokenPrefixLength: u32 & AugmentedConst<ApiType>;288      /**289       * Maximum size of all token properties.290       **/291      maxTokenPropertiesSize: u32 & AugmentedConst<ApiType>;292      /**293       * A maximum number of levels of depth in the token nesting tree.294       **/295      nestingBudget: u32 & AugmentedConst<ApiType>;296      /**297       * Default NFT collection limit.298       **/299      nftDefaultCollectionLimits: UpDataStructsCollectionLimits & AugmentedConst<ApiType>;300      /**301       * Default RFT collection limit.302       **/303      rftDefaultCollectionLimits: UpDataStructsCollectionLimits & AugmentedConst<ApiType>;304      /**305       * Generic const306       **/307      [key: string]: Codec;308    };309    vesting: {310      /**311       * The minimum amount transferred to call `vested_transfer`.312       **/313      minVestedTransfer: u128 & AugmentedConst<ApiType>;314      /**315       * Generic const316       **/317      [key: string]: Codec;318    };319    xTokens: {320      /**321       * Base XCM weight.322       * 323       * The actually weight for an XCM message is `T::BaseXcmWeight +324       * T::Weigher::weight(&msg)`.325       **/326      baseXcmWeight: u64 & AugmentedConst<ApiType>;327      /**328       * Self chain location.329       **/330      selfLocation: XcmV1MultiLocation & AugmentedConst<ApiType>;331      /**332       * Generic const333       **/334      [key: string]: Codec;335    };336  } // AugmentedConsts337} // declare module
modifiedtests/src/interfaces/augment-api-query.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-query.ts
+++ b/tests/src/interfaces/augment-api-query.ts
@@ -8,8 +8,13 @@
 import type { ApiTypes, AugmentedQuery, QueryableStorageEntry } from '@polkadot/api-base/types';
 import type { BTreeMap, Bytes, Option, U256, U8aFixed, Vec, bool, u128, u16, u32, u64, u8 } from '@polkadot/types-codec';
 import type { AnyNumber, ITuple } from '@polkadot/types-codec/types';
+<<<<<<< HEAD
 import type { AccountId32, H160, H256 } from '@polkadot/types/interfaces/runtime';
 import type { CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueQueueConfigData, EthereumBlock, EthereumLog, EthereumReceiptReceiptV3, EthereumTransactionTransactionV2, FpRpcTransactionStatus, FrameSupportDispatchPerDispatchClassWeight, FrameSystemAccountInfo, FrameSystemEventRecord, FrameSystemLastRuntimeUpgradeInfo, FrameSystemPhase, OrmlTokensAccountData, OrmlTokensBalanceLock, OrmlTokensReserveData, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesReleases, PalletBalancesReserveData, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmContractHelpersSponsoringModeT, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletNonfungibleItemData, PalletRefungibleItemData, PalletTransactionPaymentReleases, PalletTreasuryProposal, PalletUniqueSchedulerV2BlockAgenda, PhantomTypeUpDataStructs, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, SpRuntimeDigest, SpTrieStorageProof, SpWeightsWeightV2Weight, UpDataStructsCollection, UpDataStructsCollectionStats, UpDataStructsProperties, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, XcmV1MultiLocation } from '@polkadot/types/lookup';
+=======
+import type { AccountId32, H160, H256, Perbill, Weight } from '@polkadot/types/interfaces/runtime';
+import type { CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueQueueConfigData, EthereumBlock, EthereumLog, EthereumReceiptReceiptV3, EthereumTransactionTransactionV2, FpRpcTransactionStatus, FrameSupportDispatchPerDispatchClassWeight, FrameSystemAccountInfo, FrameSystemEventRecord, FrameSystemLastRuntimeUpgradeInfo, FrameSystemPhase, OrmlTokensAccountData, OrmlTokensBalanceLock, OrmlTokensReserveData, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesReleases, PalletBalancesReserveData, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmContractHelpersSponsoringModeT, PalletForeignAssetsAssetIds, PalletForeignAssetsModuleAssetMetadata, PalletNonfungibleItemData, PalletRefungibleItemData, PalletTransactionPaymentReleases, PalletTreasuryProposal, PalletUniqueSchedulerV2BlockAgenda, PhantomTypeUpDataStructs, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, SpRuntimeDigest, SpTrieStorageProof, UpDataStructsCollection, UpDataStructsCollectionStats, UpDataStructsProperties, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsPropertyPermission, UpDataStructsPropertyScope, UpDataStructsSponsorshipStateBasicCrossAccountIdRepr, UpDataStructsTokenChild, XcmV1MultiLocation } from '@polkadot/types/lookup';
+>>>>>>> added the  ability to configure pallet `app-promotion` via the `configuration` palette
 import type { Observable } from '@polkadot/types/types';
 
 export type __AugmentedQuery<ApiType extends ApiTypes> = AugmentedQuery<ApiType, () => unknown>;
@@ -160,6 +165,7 @@
       [key: string]: QueryableStorageEntry<ApiType>;
     };
     configuration: {
+      appPromomotionConfigurationOverride: AugmentedQuery<ApiType, () => Observable<Option<ITuple<[Option<u32>, Option<Perbill>, Option<u32>, Option<u8>]>>>, []> & QueryableStorageEntry<ApiType, []>;
       minGasPriceOverride: AugmentedQuery<ApiType, () => Observable<u64>, []> & QueryableStorageEntry<ApiType, []>;
       weightToFeeCoefficientOverride: AugmentedQuery<ApiType, () => Observable<u32>, []> & QueryableStorageEntry<ApiType, []>;
       xcmAllowedLocationsOverride: AugmentedQuery<ApiType, () => Observable<Option<Vec<XcmV1MultiLocation>>>, []> & QueryableStorageEntry<ApiType, []>;
modifiedtests/src/interfaces/augment-api-tx.tsdiffbeforeafterboth
--- a/tests/src/interfaces/augment-api-tx.ts
+++ b/tests/src/interfaces/augment-api-tx.ts
@@ -215,6 +215,7 @@
       [key: string]: SubmittableExtrinsicFunction<ApiType>;
     };
     configuration: {
+      setAppPromotionConfigurationOverride: AugmentedSubmittable<(recalculationInterval: Option<u32> | null | Uint8Array | u32 | AnyNumber, pendingInterval: Option<u32> | null | Uint8Array | u32 | AnyNumber, stakersPayoutLimit: Option<u8> | null | Uint8Array | u8 | AnyNumber) => SubmittableExtrinsic<ApiType>, [Option<u32>, Option<u32>, Option<u8>]>;
       setMinGasPriceOverride: AugmentedSubmittable<(coeff: Option<u64> | null | Uint8Array | u64 | AnyNumber) => SubmittableExtrinsic<ApiType>, [Option<u64>]>;
       setWeightToFeeCoefficientOverride: AugmentedSubmittable<(coeff: Option<u32> | null | Uint8Array | u32 | AnyNumber) => SubmittableExtrinsic<ApiType>, [Option<u32>]>;
       setXcmAllowedLocations: AugmentedSubmittable<(locations: Option<Vec<XcmV1MultiLocation>> | null | Uint8Array | Vec<XcmV1MultiLocation> | (XcmV1MultiLocation | { parents?: any; interior?: any } | string | Uint8Array)[]) => SubmittableExtrinsic<ApiType>, [Option<Vec<XcmV1MultiLocation>>]>;