use super::*;
use sp_staking::{DelegationInterface, DelegationMigrator, OnStakingUpdate};
impl<T: Config> DelegationInterface for Pallet<T> {
type Balance = BalanceOf<T>;
type AccountId = T::AccountId;
fn agent_balance(agent: Agent<Self::AccountId>) -> Option<Self::Balance> {
AgentLedgerOuter::<T>::get(&agent.get())
.map(|a| a.ledger.effective_balance())
.ok()
}
fn agent_transferable_balance(agent: Agent<Self::AccountId>) -> Option<Self::Balance> {
AgentLedgerOuter::<T>::get(&agent.get())
.map(|a| a.ledger.unclaimed_withdrawals)
.ok()
}
fn delegator_balance(delegator: Delegator<Self::AccountId>) -> Option<Self::Balance> {
Delegation::<T>::get(&delegator.get()).map(|d| d.amount)
}
fn register_agent(
agent: Agent<Self::AccountId>,
reward_account: &Self::AccountId,
) -> DispatchResult {
Pallet::<T>::register_agent(
RawOrigin::Signed(agent.clone().get()).into(),
reward_account.clone(),
)
}
fn remove_agent(agent: Agent<Self::AccountId>) -> DispatchResult {
Pallet::<T>::remove_agent(RawOrigin::Signed(agent.clone().get()).into())
}
fn delegate(
who: Delegator<Self::AccountId>,
agent: Agent<Self::AccountId>,
amount: Self::Balance,
) -> DispatchResult {
Pallet::<T>::delegate_to_agent(RawOrigin::Signed(who.get()).into(), agent.get(), amount)
}
fn withdraw_delegation(
delegator: Delegator<Self::AccountId>,
agent: Agent<Self::AccountId>,
amount: Self::Balance,
num_slashing_spans: u32,
) -> DispatchResult {
Pallet::<T>::release_delegation(
RawOrigin::Signed(agent.get()).into(),
delegator.get(),
amount,
num_slashing_spans,
)
}
fn pending_slash(agent: Agent<Self::AccountId>) -> Option<Self::Balance> {
AgentLedgerOuter::<T>::get(&agent.get()).map(|d| d.ledger.pending_slash).ok()
}
fn delegator_slash(
agent: Agent<Self::AccountId>,
delegator: Delegator<Self::AccountId>,
value: Self::Balance,
maybe_reporter: Option<Self::AccountId>,
) -> sp_runtime::DispatchResult {
Pallet::<T>::do_slash(agent, delegator, value, maybe_reporter)
}
}
impl<T: Config> DelegationMigrator for Pallet<T> {
type Balance = BalanceOf<T>;
type AccountId = T::AccountId;
fn migrate_nominator_to_agent(
agent: Agent<Self::AccountId>,
reward_account: &Self::AccountId,
) -> DispatchResult {
Pallet::<T>::migrate_to_agent(RawOrigin::Signed(agent.get()).into(), reward_account.clone())
}
fn migrate_delegation(
agent: Agent<Self::AccountId>,
delegator: Delegator<Self::AccountId>,
value: Self::Balance,
) -> DispatchResult {
Pallet::<T>::migrate_delegation(
RawOrigin::Signed(agent.get()).into(),
delegator.get(),
value,
)
}
#[cfg(feature = "runtime-benchmarks")]
fn force_kill_agent(agent: Agent<Self::AccountId>) {
<Agents<T>>::remove(agent.clone().get());
<Delegators<T>>::iter()
.filter(|(_, delegation)| delegation.agent == agent.clone().get())
.for_each(|(delegator, _)| {
let _ = T::Currency::release_all(
&HoldReason::StakingDelegation.into(),
&delegator,
Precision::BestEffort,
);
<Delegators<T>>::remove(&delegator);
});
}
}
impl<T: Config> OnStakingUpdate<T::AccountId, BalanceOf<T>> for Pallet<T> {
fn on_slash(
who: &T::AccountId,
_slashed_active: BalanceOf<T>,
_slashed_unlocking: &alloc::collections::btree_map::BTreeMap<EraIndex, BalanceOf<T>>,
slashed_total: BalanceOf<T>,
) {
<Agents<T>>::mutate(who, |maybe_register| match maybe_register {
Some(register) => register.pending_slash.saturating_accrue(slashed_total),
None => {
},
});
}
fn on_withdraw(stash: &T::AccountId, amount: BalanceOf<T>) {
let _ = AgentLedgerOuter::<T>::get(stash)
.and_then(|agent| agent.add_unclaimed_withdraw(amount).defensive())
.map(|agent| agent.save());
}
}