use frame_support::pallet_prelude::RuntimeDebug;
use pallet_loans::entities::changes::Change as LoansChange;
use pallet_oracle_collection::types::Change as OracleCollectionChange;
use pallet_pool_fees::types::Change as PoolFeesChange;
use pallet_pool_system::pool_types::changes::{PoolChangeProposal, Requirement};
use parity_scale_codec::{Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
use sp_runtime::DispatchError;
use sp_std::{marker::PhantomData, vec::Vec};
pub trait Changeable:
pallet_loans::Config + pallet_oracle_collection::Config + pallet_pool_fees::Config
{
}
impl<T: pallet_loans::Config + pallet_oracle_collection::Config + pallet_pool_fees::Config>
Changeable for T
{
}
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
pub enum RuntimeChange<T: Changeable, Options: Clone = ()> {
Loans(LoansChange<T>),
OracleCollection(OracleCollectionChange<T>),
PoolFee(PoolFeesChange<T>),
_Unreachable(PhantomData<Options>),
}
impl<T: Changeable, Options: Clone> RuntimeChange<T, Options> {
#[cfg(feature = "runtime-benchmarks")]
fn requirement_list(self) -> Vec<Requirement> {
Vec::default()
}
#[cfg(not(feature = "runtime-benchmarks"))]
fn requirement_list(self) -> Vec<Requirement> {
use cfg_primitives::SECONDS_PER_WEEK;
use pallet_loans::entities::changes::{InternalMutation, LoanMutation};
use sp_std::vec;
let epoch = Requirement::NextEpoch;
let week = Requirement::DelayTime(SECONDS_PER_WEEK as u32);
let blocked = Requirement::BlockedByLockedRedemptions;
match self {
RuntimeChange::Loans(change) => match change {
LoansChange::<T>::Loan(_, loan_mutation) => match loan_mutation {
LoanMutation::Maturity(_) => vec![week, blocked],
LoanMutation::MaturityExtension(_) => vec![],
LoanMutation::InterestPayments(_) => vec![week, blocked],
LoanMutation::PayDownSchedule(_) => vec![week, blocked],
LoanMutation::InterestRate(_) => vec![epoch],
LoanMutation::Internal(mutation) => match mutation {
InternalMutation::ValuationMethod(_) => vec![week, blocked],
InternalMutation::ProbabilityOfDefault(_) => vec![epoch],
InternalMutation::LossGivenDefault(_) => vec![epoch],
InternalMutation::DiscountRate(_) => vec![epoch],
},
},
LoansChange::<T>::Policy(_) => vec![week, blocked],
LoansChange::<T>::TransferDebt(_, _, _, _) => vec![],
},
RuntimeChange::OracleCollection(change) => match change {
OracleCollectionChange::CollectionInfo(_) => vec![],
},
RuntimeChange::PoolFee(pool_fees_change) => match pool_fees_change {
PoolFeesChange::AppendFee(_, _, _) => vec![week],
},
RuntimeChange::_Unreachable(_) => vec![],
}
}
}
impl<T: Changeable> From<RuntimeChange<T>> for PoolChangeProposal {
fn from(runtime_change: RuntimeChange<T>) -> Self {
PoolChangeProposal::new(runtime_change.requirement_list())
}
}
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, TypeInfo, MaxEncodedLen)]
pub struct FastDelay;
impl<T: Changeable> From<RuntimeChange<T, FastDelay>> for PoolChangeProposal {
fn from(runtime_change: RuntimeChange<T, FastDelay>) -> Self {
let new_requirements = runtime_change
.requirement_list()
.into_iter()
.map(|req| match req {
Requirement::DelayTime(_) => Requirement::DelayTime(60), req => req,
});
PoolChangeProposal::new(new_requirements)
}
}
macro_rules! runtime_change_support {
($change:ident, $variant:ident) => {
impl<T: Changeable, Option: Clone> From<$change<T>> for RuntimeChange<T, Option> {
fn from(change: $change<T>) -> RuntimeChange<T, Option> {
RuntimeChange::$variant(change)
}
}
impl<T: Changeable, Option: Clone> TryInto<$change<T>> for RuntimeChange<T, Option> {
type Error = DispatchError;
fn try_into(self) -> Result<$change<T>, DispatchError> {
match self {
RuntimeChange::$variant(change) => Ok(change),
_ => Err(DispatchError::Other("Expected another RuntimeChange")),
}
}
}
};
}
runtime_change_support!(LoansChange, Loans);
runtime_change_support!(OracleCollectionChange, OracleCollection);
runtime_change_support!(PoolFeesChange, PoolFee);