use crate::traits::{
fungible::{Inspect, Unbalanced},
tokens::{Fortitude, Precision, Preservation},
};
use core::fmt::Debug;
use sp_arithmetic::{traits::AtLeast8BitUnsigned, ArithmeticError};
use sp_runtime::{traits::Bounded, TokenError};
pub fn write_balance<T, AccountId>()
where
T: Unbalanced<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let account_0_ed = AccountId::from(0);
let account_1_gt_ed = AccountId::from(1);
let account_2_empty = AccountId::from(2);
T::increase_balance(&account_0_ed, T::minimum_balance(), Precision::Exact).unwrap();
T::increase_balance(&account_1_gt_ed, T::minimum_balance() + 5.into(), Precision::Exact)
.unwrap();
let amount = T::minimum_balance() + 10.into();
assert_eq!(T::write_balance(&account_0_ed, amount), Ok(None));
assert_eq!(T::write_balance(&account_1_gt_ed, amount), Ok(None));
assert_eq!(T::write_balance(&account_2_empty, amount), Ok(None));
assert_eq!(T::balance(&account_0_ed), amount);
assert_eq!(T::balance(&account_1_gt_ed), amount);
assert_eq!(T::balance(&account_2_empty), amount);
let amount = T::minimum_balance() - 1.into();
if T::minimum_balance() == 1.into() {
assert_eq!(T::write_balance(&account_0_ed, amount), Ok(None));
assert_eq!(T::write_balance(&account_1_gt_ed, amount), Ok(None));
assert_eq!(T::write_balance(&account_2_empty, amount), Ok(None));
} else if T::minimum_balance() > 1.into() {
assert_eq!(T::write_balance(&account_0_ed, amount), Ok(Some(amount)));
assert_eq!(T::write_balance(&account_1_gt_ed, amount), Ok(Some(amount)));
assert_eq!(T::write_balance(&account_2_empty, amount), Ok(Some(amount)));
}
}
pub fn decrease_balance_expendable<T, AccountId>()
where
T: Unbalanced<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let account_0 = AccountId::from(0);
let account_0_initial_balance = T::minimum_balance() + 10.into();
T::increase_balance(&account_0, account_0_initial_balance, Precision::Exact).unwrap();
let amount = 1.into();
assert_eq!(
T::decrease_balance(
&account_0,
amount,
Precision::Exact,
Preservation::Expendable,
Fortitude::Polite,
),
Ok(amount),
);
assert_eq!(T::balance(&account_0), account_0_initial_balance - amount);
let balance_before = T::balance(&account_0);
assert_eq!(
T::decrease_balance(
&account_0,
account_0_initial_balance,
Precision::Exact,
Preservation::Expendable,
Fortitude::Polite,
),
Err(TokenError::FundsUnavailable.into())
);
assert_eq!(T::balance(&account_0), balance_before);
assert_eq!(
T::decrease_balance(
&account_0,
account_0_initial_balance,
Precision::BestEffort,
Preservation::Expendable,
Fortitude::Polite,
),
Ok(balance_before),
);
assert_eq!(T::balance(&account_0), 0.into());
}
pub fn decrease_balance_preserve<T, AccountId>()
where
T: Unbalanced<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let account_0 = AccountId::from(0);
let account_0_initial_balance = T::minimum_balance() + 10.into();
T::increase_balance(&account_0, account_0_initial_balance, Precision::Exact).unwrap();
let amount = 11.into();
assert_eq!(
T::decrease_balance(
&account_0,
amount,
Precision::Exact,
Preservation::Preserve,
Fortitude::Polite,
),
Err(TokenError::FundsUnavailable.into()),
);
assert_eq!(T::balance(&account_0), account_0_initial_balance);
let amount = 11.into();
assert_eq!(
T::decrease_balance(
&account_0,
amount,
Precision::BestEffort,
Preservation::Preserve,
Fortitude::Polite,
),
Ok(account_0_initial_balance - T::minimum_balance()),
);
assert_eq!(T::balance(&account_0), T::minimum_balance());
}
pub fn increase_balance<T, AccountId>()
where
T: Unbalanced<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
let account_0 = AccountId::from(0);
assert_eq!(T::balance(&account_0), 0.into());
if T::minimum_balance() > 0.into() {
assert_eq!(
T::increase_balance(&account_0, T::minimum_balance() - 1.into(), Precision::Exact),
Err(TokenError::BelowMinimum.into()),
);
}
assert_eq!(T::balance(&account_0), 0.into());
if T::minimum_balance() > 0.into() {
assert_eq!(
T::increase_balance(&account_0, T::minimum_balance() - 1.into(), Precision::BestEffort),
Ok(0.into()),
);
}
assert_eq!(T::balance(&account_0), 0.into());
assert_eq!(
T::increase_balance(&account_0, T::minimum_balance(), Precision::Exact),
Ok(T::minimum_balance()),
);
assert_eq!(T::balance(&account_0), T::minimum_balance());
assert_eq!(T::increase_balance(&account_0, 5.into(), Precision::Exact), Ok(5.into()),);
assert_eq!(T::balance(&account_0), T::minimum_balance() + 5.into());
assert_eq!(
T::increase_balance(&account_0, T::Balance::max_value(), Precision::Exact),
Err(ArithmeticError::Overflow.into()),
);
let balance_before = T::balance(&account_0);
assert_eq!(
T::increase_balance(&account_0, T::Balance::max_value(), Precision::BestEffort),
Ok(T::Balance::max_value() - balance_before),
);
assert_eq!(T::balance(&account_0), T::Balance::max_value());
}
pub fn set_total_issuance<T, AccountId>()
where
T: Unbalanced<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
T::set_total_issuance(1.into());
assert_eq!(T::total_issuance(), 1.into());
T::set_total_issuance(0.into());
assert_eq!(T::total_issuance(), 0.into());
T::set_total_issuance(T::minimum_balance());
assert_eq!(T::total_issuance(), T::minimum_balance());
T::set_total_issuance(T::minimum_balance() + 5.into());
assert_eq!(T::total_issuance(), T::minimum_balance() + 5.into());
if T::minimum_balance() > 0.into() {
T::set_total_issuance(T::minimum_balance() - 1.into());
assert_eq!(T::total_issuance(), T::minimum_balance() - 1.into());
}
}
pub fn deactivate_and_reactivate<T, AccountId>()
where
T: Unbalanced<AccountId>,
<T as Inspect<AccountId>>::Balance: AtLeast8BitUnsigned + Debug,
AccountId: AtLeast8BitUnsigned,
{
T::set_total_issuance(10.into());
assert_eq!(T::total_issuance(), 10.into());
assert_eq!(T::active_issuance(), 10.into());
T::deactivate(2.into());
assert_eq!(T::total_issuance(), 10.into());
assert_eq!(T::active_issuance(), 8.into());
T::reactivate(4.into());
assert_eq!(T::total_issuance(), 10.into());
assert_eq!(T::active_issuance(), 10.into());
T::deactivate(1.into());
assert_eq!(T::total_issuance(), 10.into());
assert_eq!(T::active_issuance(), 9.into());
T::deactivate(15.into());
assert_eq!(T::total_issuance(), 10.into());
assert_eq!(T::active_issuance(), 0.into());
T::reactivate(1.into());
assert_eq!(T::total_issuance(), 10.into());
assert_eq!(T::active_issuance(), 1.into());
}