pub mod conformance_tests;
pub mod freeze;
pub mod hold;
pub(crate) mod imbalance;
mod item_of;
mod regular;
mod union_of;
use codec::{Decode, Encode, MaxEncodedLen};
use frame_support_procedural::{CloneNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound};
use scale_info::TypeInfo;
use sp_std::marker::PhantomData;
use super::{
Fortitude::{Force, Polite},
Precision::BestEffort,
};
pub use freeze::{Inspect as InspectFreeze, Mutate as MutateFreeze};
pub use hold::{
Balanced as BalancedHold, Inspect as InspectHold, Mutate as MutateHold,
Unbalanced as UnbalancedHold,
};
pub use imbalance::{Credit, Debt, HandleImbalanceDrop, Imbalance};
pub use item_of::ItemOf;
pub use regular::{
Balanced, DecreaseIssuance, Dust, IncreaseIssuance, Inspect, Mutate, Unbalanced,
};
use sp_arithmetic::traits::Zero;
use sp_core::Get;
use sp_runtime::{traits::Convert, DispatchError};
pub use union_of::{NativeFromLeft, NativeOrWithId, UnionOf};
use crate::{
ensure,
traits::{Consideration, Footprint},
};
#[derive(
CloneNoBound,
EqNoBound,
PartialEqNoBound,
Encode,
Decode,
TypeInfo,
MaxEncodedLen,
RuntimeDebugNoBound,
)]
#[scale_info(skip_type_params(A, F, R, D))]
#[codec(mel_bound())]
pub struct FreezeConsideration<A, F, R, D>(F::Balance, PhantomData<fn() -> (A, R, D)>)
where
F: MutateFreeze<A>;
impl<
A: 'static,
F: 'static + MutateFreeze<A>,
R: 'static + Get<F::Id>,
D: 'static + Convert<Footprint, F::Balance>,
> Consideration<A> for FreezeConsideration<A, F, R, D>
{
fn new(who: &A, footprint: Footprint) -> Result<Self, DispatchError> {
let new = D::convert(footprint);
F::increase_frozen(&R::get(), who, new)?;
Ok(Self(new, PhantomData))
}
fn update(self, who: &A, footprint: Footprint) -> Result<Self, DispatchError> {
let new = D::convert(footprint);
if self.0 > new {
F::decrease_frozen(&R::get(), who, self.0 - new)?;
} else if new > self.0 {
F::increase_frozen(&R::get(), who, new - self.0)?;
}
Ok(Self(new, PhantomData))
}
fn drop(self, who: &A) -> Result<(), DispatchError> {
F::decrease_frozen(&R::get(), who, self.0).map(|_| ())
}
}
#[derive(
CloneNoBound,
EqNoBound,
PartialEqNoBound,
Encode,
Decode,
TypeInfo,
MaxEncodedLen,
RuntimeDebugNoBound,
)]
#[scale_info(skip_type_params(A, F, R, D))]
#[codec(mel_bound())]
pub struct HoldConsideration<A, F, R, D>(F::Balance, PhantomData<fn() -> (A, R, D)>)
where
F: MutateHold<A>;
impl<
A: 'static,
F: 'static + MutateHold<A>,
R: 'static + Get<F::Reason>,
D: 'static + Convert<Footprint, F::Balance>,
> Consideration<A> for HoldConsideration<A, F, R, D>
{
fn new(who: &A, footprint: Footprint) -> Result<Self, DispatchError> {
let new = D::convert(footprint);
F::hold(&R::get(), who, new)?;
Ok(Self(new, PhantomData))
}
fn update(self, who: &A, footprint: Footprint) -> Result<Self, DispatchError> {
let new = D::convert(footprint);
if self.0 > new {
F::release(&R::get(), who, self.0 - new, BestEffort)?;
} else if new > self.0 {
F::hold(&R::get(), who, new - self.0)?;
}
Ok(Self(new, PhantomData))
}
fn drop(self, who: &A) -> Result<(), DispatchError> {
F::release(&R::get(), who, self.0, BestEffort).map(|_| ())
}
fn burn(self, who: &A) {
let _ = F::burn_held(&R::get(), who, self.0, BestEffort, Force);
}
}
#[derive(
CloneNoBound,
EqNoBound,
PartialEqNoBound,
Encode,
Decode,
TypeInfo,
MaxEncodedLen,
RuntimeDebugNoBound,
)]
#[scale_info(skip_type_params(A, Fx, Rx, D))]
#[codec(mel_bound())]
pub struct LoneFreezeConsideration<A, Fx, Rx, D>(PhantomData<fn() -> (A, Fx, Rx, D)>);
impl<
A: 'static,
Fx: 'static + MutateFreeze<A>,
Rx: 'static + Get<Fx::Id>,
D: 'static + Convert<Footprint, Fx::Balance>,
> Consideration<A> for LoneFreezeConsideration<A, Fx, Rx, D>
{
fn new(who: &A, footprint: Footprint) -> Result<Self, DispatchError> {
ensure!(Fx::balance_frozen(&Rx::get(), who).is_zero(), DispatchError::Unavailable);
Fx::set_frozen(&Rx::get(), who, D::convert(footprint), Polite).map(|_| Self(PhantomData))
}
fn update(self, who: &A, footprint: Footprint) -> Result<Self, DispatchError> {
Fx::set_frozen(&Rx::get(), who, D::convert(footprint), Polite).map(|_| Self(PhantomData))
}
fn drop(self, who: &A) -> Result<(), DispatchError> {
Fx::thaw(&Rx::get(), who).map(|_| ())
}
}
#[derive(
CloneNoBound,
EqNoBound,
PartialEqNoBound,
Encode,
Decode,
TypeInfo,
MaxEncodedLen,
RuntimeDebugNoBound,
)]
#[scale_info(skip_type_params(A, Fx, Rx, D))]
#[codec(mel_bound())]
pub struct LoneHoldConsideration<A, Fx, Rx, D>(PhantomData<fn() -> (A, Fx, Rx, D)>);
impl<
A: 'static,
F: 'static + MutateHold<A>,
R: 'static + Get<F::Reason>,
D: 'static + Convert<Footprint, F::Balance>,
> Consideration<A> for LoneHoldConsideration<A, F, R, D>
{
fn new(who: &A, footprint: Footprint) -> Result<Self, DispatchError> {
ensure!(F::balance_on_hold(&R::get(), who).is_zero(), DispatchError::Unavailable);
F::set_on_hold(&R::get(), who, D::convert(footprint)).map(|_| Self(PhantomData))
}
fn update(self, who: &A, footprint: Footprint) -> Result<Self, DispatchError> {
F::set_on_hold(&R::get(), who, D::convert(footprint)).map(|_| Self(PhantomData))
}
fn drop(self, who: &A) -> Result<(), DispatchError> {
F::release_all(&R::get(), who, BestEffort).map(|_| ())
}
fn burn(self, who: &A) {
let _ = F::burn_all_held(&R::get(), who, BestEffort, Force);
}
}