use frame_support::traits::{
fungible::hold::Mutate,
tokens::fungible::{Inspect, MutateHold},
};
use sp_runtime::DispatchError;
use sp_std::vec::Vec;
use crate::deposit::{free_deposit, reserve_deposit, Deposit};
pub trait CallSources<S, P> {
fn sender(&self) -> S;
fn subject(&self) -> P;
}
impl<S: Clone> CallSources<S, S> for S {
fn sender(&self) -> S {
self.clone()
}
fn subject(&self) -> S {
self.clone()
}
}
impl<S: Clone, P: Clone> CallSources<S, P> for (S, P) {
fn sender(&self) -> S {
self.0.clone()
}
fn subject(&self) -> P {
self.1.clone()
}
}
pub trait VersionMigratorTrait<T>: Sized {
#[cfg(feature = "try-runtime")]
fn pre_migrate(&self) -> Result<(), &'static str>;
fn migrate(&self) -> frame_support::weights::Weight;
#[cfg(feature = "try-runtime")]
fn post_migrate(&self) -> Result<(), &'static str>;
}
#[cfg(feature = "runtime-benchmarks")]
pub trait GenerateBenchmarkOrigin<OuterOrigin, AccountId, SubjectId> {
fn generate_origin(sender: AccountId, subject: SubjectId) -> OuterOrigin;
}
#[cfg(feature = "runtime-benchmarks")]
pub trait GetWorstCase<Context = ()> {
type Output;
fn worst_case(context: Context) -> Self::Output;
}
#[cfg(feature = "runtime-benchmarks")]
impl<T> GetWorstCase<T> for u32 {
type Output = Self;
fn worst_case(_context: T) -> Self::Output {
u32::MAX
}
}
#[cfg(feature = "runtime-benchmarks")]
impl<T> GetWorstCase<T> for () {
type Output = Self;
fn worst_case(_context: T) -> Self::Output {}
}
#[cfg(feature = "runtime-benchmarks")]
impl<T> GetWorstCase<T> for bool {
type Output = Self;
fn worst_case(_context: T) -> Self::Output {
true
}
}
#[cfg(feature = "runtime-benchmarks")]
pub trait Instanciate {
fn new(instance: u32) -> Self;
}
#[cfg(feature = "runtime-benchmarks")]
impl Instanciate for sp_runtime::AccountId32 {
fn new(instance: u32) -> Self {
use sp_runtime::traits::Hash;
sp_runtime::AccountId32::from(<[u8; 32]>::from(sp_runtime::traits::BlakeTwo256::hash(
&instance.to_be_bytes(),
)))
}
}
pub trait ItemFilter<Item> {
fn should_include(&self, credential: &Item) -> bool;
}
pub trait BalanceMigrationManager<AccountId, Balance> {
fn release_reserved_deposit(user: &AccountId, balance: &Balance);
fn exclude_key_from_migration(key: &[u8]);
fn is_key_migrated(key: &[u8]) -> bool;
}
impl<AccountId, Balance> BalanceMigrationManager<AccountId, Balance> for () {
fn exclude_key_from_migration(_key: &[u8]) {}
fn is_key_migrated(_key: &[u8]) -> bool {
true
}
fn release_reserved_deposit(_user: &AccountId, _balance: &Balance) {}
}
pub trait StorageDepositCollector<AccountId, Key, RuntimeHoldReason> {
type Currency: MutateHold<AccountId, Reason = RuntimeHoldReason>;
type Reason: Into<RuntimeHoldReason> + Clone;
fn reason() -> Self::Reason;
fn deposit(key: &Key)
-> Result<Deposit<AccountId, <Self::Currency as Inspect<AccountId>>::Balance>, DispatchError>;
fn deposit_amount(key: &Key) -> <Self::Currency as Inspect<AccountId>>::Balance;
fn get_hashed_key(key: &Key) -> Result<Vec<u8>, DispatchError>;
fn store_deposit(
key: &Key,
deposit: Deposit<AccountId, <Self::Currency as Inspect<AccountId>>::Balance>,
) -> Result<(), DispatchError>;
fn free_deposit(
deposit: Deposit<AccountId, <Self::Currency as Inspect<AccountId>>::Balance>,
) -> Result<<Self::Currency as Inspect<AccountId>>::Balance, DispatchError> {
free_deposit::<AccountId, Self::Currency>(&deposit, &Self::reason().into())
}
fn create_deposit(
who: AccountId,
amount: <Self::Currency as Inspect<AccountId>>::Balance,
) -> Result<Deposit<AccountId, <Self::Currency as Inspect<AccountId>>::Balance>, DispatchError> {
let reason = Self::reason();
reserve_deposit::<AccountId, Self::Currency>(who, amount, &reason.into())
}
fn change_deposit_owner<DepositBalanceMigrationManager>(
key: &Key,
new_owner: AccountId,
) -> Result<(), DispatchError>
where
DepositBalanceMigrationManager:
BalanceMigrationManager<AccountId, <Self::Currency as Inspect<AccountId>>::Balance>,
{
let hashed_key = Self::get_hashed_key(key)?;
let is_key_migrated = DepositBalanceMigrationManager::is_key_migrated(&hashed_key);
let deposit = Self::deposit(key)?;
let reason = Self::reason();
if is_key_migrated {
free_deposit::<AccountId, Self::Currency>(&deposit, &reason.clone().into())?;
} else {
DepositBalanceMigrationManager::release_reserved_deposit(&deposit.owner, &deposit.amount);
DepositBalanceMigrationManager::exclude_key_from_migration(&hashed_key);
}
let deposit = Deposit {
owner: new_owner,
..deposit
};
Self::Currency::hold(&reason.into(), &deposit.owner, deposit.amount)?;
Self::store_deposit(key, deposit)?;
Ok(())
}
fn update_deposit<DepositBalanceMigrationManager>(key: &Key) -> Result<(), DispatchError>
where
DepositBalanceMigrationManager:
BalanceMigrationManager<AccountId, <Self::Currency as Inspect<AccountId>>::Balance>,
{
let deposit = Self::deposit(key)?;
let reason = Self::reason();
let hashed_key = Self::get_hashed_key(key)?;
let is_key_migrated = DepositBalanceMigrationManager::is_key_migrated(&hashed_key);
if is_key_migrated {
free_deposit::<AccountId, Self::Currency>(&deposit, &reason.clone().into())?;
} else {
DepositBalanceMigrationManager::release_reserved_deposit(&deposit.owner, &deposit.amount);
DepositBalanceMigrationManager::exclude_key_from_migration(&hashed_key);
}
let deposit = Deposit {
amount: Self::deposit_amount(key),
..deposit
};
Self::Currency::hold(&reason.into(), &deposit.owner, deposit.amount)?;
Self::store_deposit(key, deposit)?;
Ok(())
}
}