#![cfg_attr(not(feature = "std"), no_std)]
use crate::currency_to_vote::CurrencyToVote;
use codec::{FullCodec, MaxEncodedLen};
use scale_info::TypeInfo;
use sp_core::RuntimeDebug;
use sp_runtime::{DispatchError, DispatchResult, Saturating};
use sp_std::{collections::btree_map::BTreeMap, ops::Sub, vec::Vec};
pub mod offence;
pub mod currency_to_vote;
pub type SessionIndex = u32;
pub type EraIndex = u32;
#[derive(RuntimeDebug, TypeInfo)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize, PartialEq, Eq, Clone))]
pub enum StakerStatus<AccountId> {
Idle,
Validator,
Nominator(Vec<AccountId>),
}
#[derive(RuntimeDebug, Clone, Copy, Eq, PartialEq, Default)]
pub struct Stake<Balance> {
pub total: Balance,
pub active: Balance,
}
#[impl_trait_for_tuples::impl_for_tuples(10)]
pub trait OnStakingUpdate<AccountId, Balance> {
fn on_stake_update(_who: &AccountId, _prev_stake: Option<Stake<Balance>>) {}
fn on_nominator_add(_who: &AccountId) {}
fn on_nominator_update(_who: &AccountId, _prev_nominations: Vec<AccountId>) {}
fn on_nominator_remove(_who: &AccountId, _nominations: Vec<AccountId>) {}
fn on_validator_add(_who: &AccountId) {}
fn on_validator_update(_who: &AccountId) {}
fn on_validator_remove(_who: &AccountId) {}
fn on_unstake(_who: &AccountId) {}
fn on_slash(
_stash: &AccountId,
_slashed_active: Balance,
_slashed_unlocking: &BTreeMap<EraIndex, Balance>,
) {
}
}
pub trait StakingInterface {
type Balance: Sub<Output = Self::Balance>
+ Ord
+ PartialEq
+ Default
+ Copy
+ MaxEncodedLen
+ FullCodec
+ TypeInfo
+ Saturating;
type AccountId: Clone + sp_std::fmt::Debug;
type CurrencyToVote: CurrencyToVote<Self::Balance>;
fn minimum_nominator_bond() -> Self::Balance;
fn minimum_validator_bond() -> Self::Balance;
fn stash_by_ctrl(controller: &Self::AccountId) -> Result<Self::AccountId, DispatchError>;
fn bonding_duration() -> EraIndex;
fn current_era() -> EraIndex;
fn stake(who: &Self::AccountId) -> Result<Stake<Self::Balance>, DispatchError>;
fn total_stake(who: &Self::AccountId) -> Result<Self::Balance, DispatchError> {
Self::stake(who).map(|s| s.total)
}
fn active_stake(who: &Self::AccountId) -> Result<Self::Balance, DispatchError> {
Self::stake(who).map(|s| s.active)
}
fn is_unbonding(who: &Self::AccountId) -> Result<bool, DispatchError> {
Self::stake(who).map(|s| s.active != s.total)
}
fn fully_unbond(who: &Self::AccountId) -> DispatchResult {
Self::unbond(who, Self::stake(who)?.active)
}
fn bond(who: &Self::AccountId, value: Self::Balance, payee: &Self::AccountId)
-> DispatchResult;
fn nominate(who: &Self::AccountId, validators: Vec<Self::AccountId>) -> DispatchResult;
fn chill(who: &Self::AccountId) -> DispatchResult;
fn bond_extra(who: &Self::AccountId, extra: Self::Balance) -> DispatchResult;
fn unbond(stash: &Self::AccountId, value: Self::Balance) -> DispatchResult;
fn withdraw_unbonded(
stash: Self::AccountId,
num_slashing_spans: u32,
) -> Result<bool, DispatchError>;
fn desired_validator_count() -> u32;
fn election_ongoing() -> bool;
fn force_unstake(who: Self::AccountId) -> DispatchResult;
fn is_exposed_in_era(who: &Self::AccountId, era: &EraIndex) -> bool;
fn status(who: &Self::AccountId) -> Result<StakerStatus<Self::AccountId>, DispatchError>;
fn is_validator(who: &Self::AccountId) -> bool {
Self::status(who).map(|s| matches!(s, StakerStatus::Validator)).unwrap_or(false)
}
fn nominations(who: &Self::AccountId) -> Option<Vec<Self::AccountId>> {
match Self::status(who) {
Ok(StakerStatus::Nominator(t)) => Some(t),
_ => None,
}
}
#[cfg(feature = "runtime-benchmarks")]
fn add_era_stakers(
current_era: &EraIndex,
stash: &Self::AccountId,
exposures: Vec<(Self::AccountId, Self::Balance)>,
);
#[cfg(feature = "runtime-benchmarks")]
fn set_current_era(era: EraIndex);
}
sp_core::generate_feature_enabled_macro!(runtime_benchmarks_enabled, feature = "runtime-benchmarks", $);