use codec::{FullCodec, MaxEncodedLen};
use core::fmt::Debug;
use scale_info::TypeInfo;
use subsoil::core::TypedGet;
use subsoil::runtime::DispatchError;
use super::{fungible, fungibles, Balance, Preservation::Expendable};
pub trait Pay {
type Balance: Balance;
type Beneficiary;
type AssetKind;
type Id: FullCodec + MaxEncodedLen + TypeInfo + Clone + Eq + PartialEq + Debug + Copy;
type Error: Debug;
fn pay(
who: &Self::Beneficiary,
asset_kind: Self::AssetKind,
amount: Self::Balance,
) -> Result<Self::Id, Self::Error>;
fn check_payment(id: Self::Id) -> PaymentStatus;
#[cfg(feature = "runtime-benchmarks")]
fn ensure_successful(
who: &Self::Beneficiary,
asset_kind: Self::AssetKind,
amount: Self::Balance,
);
#[cfg(feature = "runtime-benchmarks")]
fn ensure_concluded(id: Self::Id);
}
pub type PaymentStatus = super::transfer::TransferStatus;
pub struct PayFromAccount<F, A>(core::marker::PhantomData<(F, A)>);
impl<A, F> Pay for PayFromAccount<F, A>
where
A: TypedGet,
F: fungible::Mutate<A::Type>,
A::Type: Eq,
{
type Balance = F::Balance;
type Beneficiary = A::Type;
type AssetKind = ();
type Id = ();
type Error = DispatchError;
fn pay(
who: &Self::Beneficiary,
_: Self::AssetKind,
amount: Self::Balance,
) -> Result<Self::Id, Self::Error> {
<F as fungible::Mutate<_>>::transfer(&A::get(), who, amount, Expendable)?;
Ok(())
}
fn check_payment(_: ()) -> PaymentStatus {
PaymentStatus::Success
}
#[cfg(feature = "runtime-benchmarks")]
fn ensure_successful(_: &Self::Beneficiary, _: Self::AssetKind, amount: Self::Balance) {
<F as fungible::Mutate<_>>::mint_into(&A::get(), amount).unwrap();
}
#[cfg(feature = "runtime-benchmarks")]
fn ensure_concluded(_: Self::Id) {}
}
pub struct PayAssetFromAccount<F, A>(core::marker::PhantomData<(F, A)>);
impl<A, F> topsoil_core::traits::tokens::Pay for PayAssetFromAccount<F, A>
where
A: TypedGet,
F: fungibles::Mutate<A::Type> + fungibles::Create<A::Type>,
A::Type: Eq,
{
type Balance = F::Balance;
type Beneficiary = A::Type;
type AssetKind = F::AssetId;
type Id = ();
type Error = DispatchError;
fn pay(
who: &Self::Beneficiary,
asset: Self::AssetKind,
amount: Self::Balance,
) -> Result<Self::Id, Self::Error> {
<F as fungibles::Mutate<_>>::transfer(asset, &A::get(), who, amount, Expendable)?;
Ok(())
}
fn check_payment(_: ()) -> PaymentStatus {
PaymentStatus::Success
}
#[cfg(feature = "runtime-benchmarks")]
fn ensure_successful(_: &Self::Beneficiary, asset: Self::AssetKind, amount: Self::Balance) {
<F as fungibles::Create<_>>::create(asset.clone(), A::get(), true, amount).unwrap();
<F as fungibles::Mutate<_>>::mint_into(asset, &A::get(), amount).unwrap();
}
#[cfg(feature = "runtime-benchmarks")]
fn ensure_concluded(_: Self::Id) {}
}
pub trait PayWithSource {
type Balance: Balance;
type Source;
type Beneficiary;
type AssetKind;
type Id: FullCodec + MaxEncodedLen + TypeInfo + Clone + Eq + PartialEq + Debug + Copy;
type Error: Debug;
fn pay(
source: &Self::Source,
beneficiary: &Self::Beneficiary,
asset_kind: Self::AssetKind,
amount: Self::Balance,
) -> Result<Self::Id, Self::Error>;
fn check_payment(id: Self::Id) -> PaymentStatus;
#[cfg(feature = "runtime-benchmarks")]
fn ensure_successful(
source: &Self::Source,
beneficiary: &Self::Beneficiary,
asset_kind: Self::AssetKind,
amount: Self::Balance,
);
#[cfg(feature = "runtime-benchmarks")]
fn ensure_concluded(id: Self::Id);
}
pub struct PayWithFungibles<F, A>(core::marker::PhantomData<(F, A)>);
impl<A, F> topsoil_core::traits::tokens::PayWithSource for PayWithFungibles<F, A>
where
A: Eq + Clone,
F: fungibles::Mutate<A> + fungibles::Create<A>,
{
type Balance = F::Balance;
type Source = A;
type Beneficiary = A;
type AssetKind = F::AssetId;
type Id = ();
type Error = DispatchError;
fn pay(
source: &Self::Source,
beneficiary: &Self::Beneficiary,
asset: Self::AssetKind,
amount: Self::Balance,
) -> Result<Self::Id, Self::Error> {
<F as fungibles::Mutate<_>>::transfer(asset, source, beneficiary, amount, Expendable)?;
Ok(())
}
fn check_payment(_: ()) -> PaymentStatus {
PaymentStatus::Success
}
#[cfg(feature = "runtime-benchmarks")]
fn ensure_successful(
source: &Self::Source,
_: &Self::Beneficiary,
asset: Self::AssetKind,
amount: Self::Balance,
) {
use subsoil::runtime::traits::Zero;
if F::total_issuance(asset.clone()).is_zero() {
let _ = <F as fungibles::Create<_>>::create(
asset.clone(),
source.clone(),
true,
1u32.into(),
);
}
<F as fungibles::Mutate<_>>::mint_into(asset, &source, amount).unwrap();
}
#[cfg(feature = "runtime-benchmarks")]
fn ensure_concluded(_: Self::Id) {}
}