mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 09:57:56 +00:00
UnionOf types for merged fungible and fungibles implementations (#2033)
Introduces `UnionOf` types, crafted to merge `fungible` and `fungibles` implementations or two `fungibles` implementations into a single type implementing `fungibles`. This also addresses an issue where `ItemOf` initiates a double drop for an imbalance type, leading to inaccurate total issuance accounting. Find the application of these types in this PR - [link](https://github.com/paritytech/polkadot-sdk/pull/2031), places in code - [1](https://github.com/paritytech/polkadot-sdk/blob/4ec7496fa2632385b08fae860fcf28a523a7b5de/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs#L327), [2](https://github.com/paritytech/polkadot-sdk/blob/4ec7496fa2632385b08fae860fcf28a523a7b5de/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs#L343). --------- Co-authored-by: Liam Aharon <liam.aharon@hotmail.com> Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: joepetrowski <joe@parity.io>
This commit is contained in:
@@ -1170,17 +1170,26 @@ impl<Hash> PreimageRecipient<Hash> for () {
|
||||
fn unnote_preimage(_: &Hash) {}
|
||||
}
|
||||
|
||||
/// Trait for creating an asset account with a deposit taken from a designated depositor specified
|
||||
/// by the client.
|
||||
/// Trait for touching/creating an asset account with a deposit taken from a designated depositor
|
||||
/// specified by the client.
|
||||
///
|
||||
/// Ensures that transfers to the touched account will succeed without being denied by the account
|
||||
/// creation requirements. For example, it is useful for the account creation of non-sufficient
|
||||
/// assets when its system account may not have the free consumer reference required for it. If
|
||||
/// there is no risk of failing to meet those requirements, the touch operation can be a no-op, as
|
||||
/// is common for native assets.
|
||||
pub trait AccountTouch<AssetId, AccountId> {
|
||||
/// The type for currency units of the deposit.
|
||||
type Balance;
|
||||
|
||||
/// The deposit amount of a native currency required for creating an account of the `asset`.
|
||||
/// The deposit amount of a native currency required for touching an account of the `asset`.
|
||||
fn deposit_required(asset: AssetId) -> Self::Balance;
|
||||
|
||||
/// Check if an account for a given asset should be touched to meet the existence requirements.
|
||||
fn should_touch(asset: AssetId, who: &AccountId) -> bool;
|
||||
|
||||
/// Create an account for `who` of the `asset` with a deposit taken from the `depositor`.
|
||||
fn touch(asset: AssetId, who: AccountId, depositor: AccountId) -> DispatchResult;
|
||||
fn touch(asset: AssetId, who: &AccountId, depositor: &AccountId) -> DispatchResult;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -20,8 +20,9 @@
|
||||
|
||||
use super::{super::Imbalance as ImbalanceT, Balanced, *};
|
||||
use crate::traits::{
|
||||
fungibles,
|
||||
misc::{SameOrOther, TryDrop},
|
||||
tokens::Balance,
|
||||
tokens::{AssetId, Balance},
|
||||
};
|
||||
use frame_support_procedural::{EqNoBound, PartialEqNoBound, RuntimeDebugNoBound};
|
||||
use sp_runtime::traits::Zero;
|
||||
@@ -87,6 +88,11 @@ impl<B: Balance, OnDrop: HandleImbalanceDrop<B>, OppositeOnDrop: HandleImbalance
|
||||
pub(crate) fn new(amount: B) -> Self {
|
||||
Self { amount, _phantom: PhantomData }
|
||||
}
|
||||
|
||||
/// Forget the imbalance without invoking the on-drop handler.
|
||||
pub(crate) fn forget(imbalance: Self) {
|
||||
sp_std::mem::forget(imbalance);
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Balance, OnDrop: HandleImbalanceDrop<B>, OppositeOnDrop: HandleImbalanceDrop<B>>
|
||||
@@ -149,6 +155,27 @@ impl<B: Balance, OnDrop: HandleImbalanceDrop<B>, OppositeOnDrop: HandleImbalance
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a `fungibles` `imbalance` instance to an instance of a `fungible` imbalance type.
|
||||
///
|
||||
/// This function facilitates imbalance conversions within the implementations of
|
||||
/// [`frame_support::traits::fungibles::UnionOf`], [`frame_support::traits::fungible::UnionOf`], and
|
||||
/// [`frame_support::traits::fungible::ItemOf`] adapters. It is intended only for internal use
|
||||
/// within the current crate.
|
||||
pub(crate) fn from_fungibles<
|
||||
A: AssetId,
|
||||
B: Balance,
|
||||
OnDropIn: fungibles::HandleImbalanceDrop<A, B>,
|
||||
OppositeIn: fungibles::HandleImbalanceDrop<A, B>,
|
||||
OnDropOut: HandleImbalanceDrop<B>,
|
||||
OppositeOut: HandleImbalanceDrop<B>,
|
||||
>(
|
||||
imbalance: fungibles::Imbalance<A, B, OnDropIn, OppositeIn>,
|
||||
) -> Imbalance<B, OnDropOut, OppositeOut> {
|
||||
let new = Imbalance::new(imbalance.peek());
|
||||
fungibles::Imbalance::forget(imbalance);
|
||||
new
|
||||
}
|
||||
|
||||
/// Imbalance implying that the total_issuance value is less than the sum of all account balances.
|
||||
pub type Debt<AccountId, B> = Imbalance<
|
||||
<B as Inspect<AccountId>>::Balance,
|
||||
|
||||
@@ -17,15 +17,17 @@
|
||||
|
||||
//! Adapter to use `fungibles::*` implementations as `fungible::*`.
|
||||
|
||||
use super::*;
|
||||
use crate::traits::{
|
||||
fungible::imbalance,
|
||||
tokens::{
|
||||
fungibles, DepositConsequence, Fortitude, Precision, Preservation, Provenance, Restriction,
|
||||
WithdrawConsequence,
|
||||
},
|
||||
};
|
||||
use sp_core::Get;
|
||||
use sp_runtime::{DispatchError, DispatchResult};
|
||||
|
||||
use super::*;
|
||||
use crate::traits::tokens::{
|
||||
fungibles, DepositConsequence, Fortitude, Imbalance as ImbalanceT, Precision, Preservation,
|
||||
Provenance, Restriction, WithdrawConsequence,
|
||||
};
|
||||
|
||||
/// Convert a `fungibles` trait implementation into a `fungible` trait implementation by identifying
|
||||
/// a single item.
|
||||
pub struct ItemOf<
|
||||
@@ -381,35 +383,38 @@ impl<
|
||||
precision: Precision,
|
||||
) -> Result<Debt<AccountId, Self>, DispatchError> {
|
||||
<F as fungibles::Balanced<AccountId>>::deposit(A::get(), who, value, precision)
|
||||
.map(|debt| Imbalance::new(debt.peek()))
|
||||
.map(imbalance::from_fungibles)
|
||||
}
|
||||
fn issue(amount: Self::Balance) -> Credit<AccountId, Self> {
|
||||
Imbalance::new(<F as fungibles::Balanced<AccountId>>::issue(A::get(), amount).peek())
|
||||
let credit = <F as fungibles::Balanced<AccountId>>::issue(A::get(), amount);
|
||||
imbalance::from_fungibles(credit)
|
||||
}
|
||||
fn pair(amount: Self::Balance) -> (Debt<AccountId, Self>, Credit<AccountId, Self>) {
|
||||
let (a, b) = <F as fungibles::Balanced<AccountId>>::pair(A::get(), amount);
|
||||
(Imbalance::new(a.peek()), Imbalance::new(b.peek()))
|
||||
(imbalance::from_fungibles(a), imbalance::from_fungibles(b))
|
||||
}
|
||||
fn rescind(amount: Self::Balance) -> Debt<AccountId, Self> {
|
||||
Imbalance::new(<F as fungibles::Balanced<AccountId>>::rescind(A::get(), amount).peek())
|
||||
let debt = <F as fungibles::Balanced<AccountId>>::rescind(A::get(), amount);
|
||||
imbalance::from_fungibles(debt)
|
||||
}
|
||||
fn resolve(
|
||||
who: &AccountId,
|
||||
credit: Credit<AccountId, Self>,
|
||||
) -> Result<(), Credit<AccountId, Self>> {
|
||||
let credit = fungibles::Imbalance::new(A::get(), credit.peek());
|
||||
let credit = fungibles::imbalance::from_fungible(credit, A::get());
|
||||
<F as fungibles::Balanced<AccountId>>::resolve(who, credit)
|
||||
.map_err(|credit| Imbalance::new(credit.peek()))
|
||||
.map_err(imbalance::from_fungibles)
|
||||
}
|
||||
fn settle(
|
||||
who: &AccountId,
|
||||
debt: Debt<AccountId, Self>,
|
||||
preservation: Preservation,
|
||||
) -> Result<Credit<AccountId, Self>, Debt<AccountId, Self>> {
|
||||
let debt = fungibles::Imbalance::new(A::get(), debt.peek());
|
||||
<F as fungibles::Balanced<AccountId>>::settle(who, debt, preservation)
|
||||
.map(|credit| Imbalance::new(credit.peek()))
|
||||
.map_err(|debt| Imbalance::new(debt.peek()))
|
||||
let debt = fungibles::imbalance::from_fungible(debt, A::get());
|
||||
<F as fungibles::Balanced<AccountId>>::settle(who, debt, preservation).map_or_else(
|
||||
|d| Err(imbalance::from_fungibles(d)),
|
||||
|c| Ok(imbalance::from_fungibles(c)),
|
||||
)
|
||||
}
|
||||
fn withdraw(
|
||||
who: &AccountId,
|
||||
@@ -426,7 +431,7 @@ impl<
|
||||
preservation,
|
||||
force,
|
||||
)
|
||||
.map(|credit| Imbalance::new(credit.peek()))
|
||||
.map(imbalance::from_fungibles)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,7 +448,7 @@ impl<
|
||||
) -> (Credit<AccountId, Self>, Self::Balance) {
|
||||
let (credit, amount) =
|
||||
<F as fungibles::BalancedHold<AccountId>>::slash(A::get(), reason, who, amount);
|
||||
(Imbalance::new(credit.peek()), amount)
|
||||
(imbalance::from_fungibles(credit), amount)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,9 +41,10 @@
|
||||
pub mod conformance_tests;
|
||||
pub mod freeze;
|
||||
pub mod hold;
|
||||
mod imbalance;
|
||||
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};
|
||||
@@ -67,6 +68,7 @@ pub use regular::{
|
||||
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,
|
||||
|
||||
@@ -0,0 +1,924 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (Criterion) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Types to combine some `fungible::*` and `fungibles::*` implementations into one union
|
||||
//! `fungibles::*` implementation.
|
||||
|
||||
use codec::{Decode, Encode, MaxEncodedLen};
|
||||
use frame_support::traits::{
|
||||
fungible::imbalance,
|
||||
tokens::{
|
||||
fungible, fungibles, AssetId, DepositConsequence, Fortitude, Precision, Preservation,
|
||||
Provenance, Restriction, WithdrawConsequence,
|
||||
},
|
||||
AccountTouch,
|
||||
};
|
||||
use scale_info::TypeInfo;
|
||||
use sp_runtime::{
|
||||
traits::Convert,
|
||||
DispatchError, DispatchResult, Either,
|
||||
Either::{Left, Right},
|
||||
RuntimeDebug,
|
||||
};
|
||||
use sp_std::cmp::Ordering;
|
||||
|
||||
/// The `NativeOrWithId` enum classifies an asset as either `Native` to the current chain or as an
|
||||
/// asset with a specific ID.
|
||||
#[derive(Decode, Encode, Default, MaxEncodedLen, TypeInfo, Clone, RuntimeDebug, Eq)]
|
||||
pub enum NativeOrWithId<AssetId>
|
||||
where
|
||||
AssetId: Ord,
|
||||
{
|
||||
/// Represents the native asset of the current chain.
|
||||
///
|
||||
/// E.g., DOT for the Polkadot Asset Hub.
|
||||
#[default]
|
||||
Native,
|
||||
/// Represents an asset identified by its underlying `AssetId`.
|
||||
WithId(AssetId),
|
||||
}
|
||||
impl<AssetId: Ord> From<AssetId> for NativeOrWithId<AssetId> {
|
||||
fn from(asset: AssetId) -> Self {
|
||||
Self::WithId(asset)
|
||||
}
|
||||
}
|
||||
impl<AssetId: Ord> Ord for NativeOrWithId<AssetId> {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
match (self, other) {
|
||||
(Self::Native, Self::Native) => Ordering::Equal,
|
||||
(Self::Native, Self::WithId(_)) => Ordering::Less,
|
||||
(Self::WithId(_), Self::Native) => Ordering::Greater,
|
||||
(Self::WithId(id1), Self::WithId(id2)) => <AssetId as Ord>::cmp(id1, id2),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<AssetId: Ord> PartialOrd for NativeOrWithId<AssetId> {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(<Self as Ord>::cmp(self, other))
|
||||
}
|
||||
}
|
||||
impl<AssetId: Ord> PartialEq for NativeOrWithId<AssetId> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.cmp(other) == Ordering::Equal
|
||||
}
|
||||
}
|
||||
|
||||
/// Criterion for [`UnionOf`] where a set for [`NativeOrWithId::Native`] asset located from the left
|
||||
/// and for [`NativeOrWithId::WithId`] from the right.
|
||||
pub struct NativeFromLeft;
|
||||
impl<AssetId: Ord> Convert<NativeOrWithId<AssetId>, Either<(), AssetId>> for NativeFromLeft {
|
||||
fn convert(asset: NativeOrWithId<AssetId>) -> Either<(), AssetId> {
|
||||
match asset {
|
||||
NativeOrWithId::Native => Either::Left(()),
|
||||
NativeOrWithId::WithId(id) => Either::Right(id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Type to combine some `fungible::*` and `fungibles::*` implementations into one union
|
||||
/// `fungibles::*` implementation.
|
||||
///
|
||||
/// ### Parameters:
|
||||
/// - `Left` is `fungible::*` implementation that is incorporated into the resulting union.
|
||||
/// - `Right` is `fungibles::*` implementation that is incorporated into the resulting union.
|
||||
/// - `Criterion` determines whether the `AssetKind` belongs to the `Left` or `Right` set.
|
||||
/// - `AssetKind` is a superset type encompassing asset kinds from `Left` and `Right` sets.
|
||||
/// - `AccountId` is an account identifier type.
|
||||
pub struct UnionOf<Left, Right, Criterion, AssetKind, AccountId>(
|
||||
sp_std::marker::PhantomData<(Left, Right, Criterion, AssetKind, AccountId)>,
|
||||
);
|
||||
|
||||
impl<
|
||||
Left: fungible::Inspect<AccountId>,
|
||||
Right: fungibles::Inspect<AccountId, Balance = Left::Balance>,
|
||||
Criterion: Convert<AssetKind, Either<(), Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> fungibles::Inspect<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
type AssetId = AssetKind;
|
||||
type Balance = Left::Balance;
|
||||
|
||||
fn total_issuance(asset: Self::AssetId) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::Inspect<AccountId>>::total_issuance(),
|
||||
Right(a) => <Right as fungibles::Inspect<AccountId>>::total_issuance(a),
|
||||
}
|
||||
}
|
||||
fn active_issuance(asset: Self::AssetId) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::Inspect<AccountId>>::active_issuance(),
|
||||
Right(a) => <Right as fungibles::Inspect<AccountId>>::active_issuance(a),
|
||||
}
|
||||
}
|
||||
fn minimum_balance(asset: Self::AssetId) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::Inspect<AccountId>>::minimum_balance(),
|
||||
Right(a) => <Right as fungibles::Inspect<AccountId>>::minimum_balance(a),
|
||||
}
|
||||
}
|
||||
fn balance(asset: Self::AssetId, who: &AccountId) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::Inspect<AccountId>>::balance(who),
|
||||
Right(a) => <Right as fungibles::Inspect<AccountId>>::balance(a, who),
|
||||
}
|
||||
}
|
||||
fn total_balance(asset: Self::AssetId, who: &AccountId) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::Inspect<AccountId>>::total_balance(who),
|
||||
Right(a) => <Right as fungibles::Inspect<AccountId>>::total_balance(a, who),
|
||||
}
|
||||
}
|
||||
fn reducible_balance(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
preservation: Preservation,
|
||||
force: Fortitude,
|
||||
) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) =>
|
||||
<Left as fungible::Inspect<AccountId>>::reducible_balance(who, preservation, force),
|
||||
Right(a) => <Right as fungibles::Inspect<AccountId>>::reducible_balance(
|
||||
a,
|
||||
who,
|
||||
preservation,
|
||||
force,
|
||||
),
|
||||
}
|
||||
}
|
||||
fn can_deposit(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
provenance: Provenance,
|
||||
) -> DepositConsequence {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) =>
|
||||
<Left as fungible::Inspect<AccountId>>::can_deposit(who, amount, provenance),
|
||||
Right(a) =>
|
||||
<Right as fungibles::Inspect<AccountId>>::can_deposit(a, who, amount, provenance),
|
||||
}
|
||||
}
|
||||
fn can_withdraw(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> WithdrawConsequence<Self::Balance> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::Inspect<AccountId>>::can_withdraw(who, amount),
|
||||
Right(a) => <Right as fungibles::Inspect<AccountId>>::can_withdraw(a, who, amount),
|
||||
}
|
||||
}
|
||||
fn asset_exists(asset: Self::AssetId) -> bool {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => true,
|
||||
Right(a) => <Right as fungibles::Inspect<AccountId>>::asset_exists(a),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungible::InspectHold<AccountId>,
|
||||
Right: fungibles::InspectHold<AccountId, Balance = Left::Balance, Reason = Left::Reason>,
|
||||
Criterion: Convert<AssetKind, Either<(), Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> fungibles::InspectHold<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
type Reason = Left::Reason;
|
||||
|
||||
fn reducible_total_balance_on_hold(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
force: Fortitude,
|
||||
) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) =>
|
||||
<Left as fungible::InspectHold<AccountId>>::reducible_total_balance_on_hold(
|
||||
who, force,
|
||||
),
|
||||
Right(a) =>
|
||||
<Right as fungibles::InspectHold<AccountId>>::reducible_total_balance_on_hold(
|
||||
a, who, force,
|
||||
),
|
||||
}
|
||||
}
|
||||
fn hold_available(asset: Self::AssetId, reason: &Self::Reason, who: &AccountId) -> bool {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::InspectHold<AccountId>>::hold_available(reason, who),
|
||||
Right(a) =>
|
||||
<Right as fungibles::InspectHold<AccountId>>::hold_available(a, reason, who),
|
||||
}
|
||||
}
|
||||
fn total_balance_on_hold(asset: Self::AssetId, who: &AccountId) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::InspectHold<AccountId>>::total_balance_on_hold(who),
|
||||
Right(a) => <Right as fungibles::InspectHold<AccountId>>::total_balance_on_hold(a, who),
|
||||
}
|
||||
}
|
||||
fn balance_on_hold(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &AccountId,
|
||||
) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::InspectHold<AccountId>>::balance_on_hold(reason, who),
|
||||
Right(a) =>
|
||||
<Right as fungibles::InspectHold<AccountId>>::balance_on_hold(a, reason, who),
|
||||
}
|
||||
}
|
||||
fn can_hold(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> bool {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::InspectHold<AccountId>>::can_hold(reason, who, amount),
|
||||
Right(a) =>
|
||||
<Right as fungibles::InspectHold<AccountId>>::can_hold(a, reason, who, amount),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungible::InspectFreeze<AccountId>,
|
||||
Right: fungibles::InspectFreeze<AccountId, Balance = Left::Balance, Id = Left::Id>,
|
||||
Criterion: Convert<AssetKind, Either<(), Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> fungibles::InspectFreeze<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
type Id = Left::Id;
|
||||
fn balance_frozen(asset: Self::AssetId, id: &Self::Id, who: &AccountId) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::InspectFreeze<AccountId>>::balance_frozen(id, who),
|
||||
Right(a) => <Right as fungibles::InspectFreeze<AccountId>>::balance_frozen(a, id, who),
|
||||
}
|
||||
}
|
||||
fn balance_freezable(asset: Self::AssetId, who: &AccountId) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::InspectFreeze<AccountId>>::balance_freezable(who),
|
||||
Right(a) => <Right as fungibles::InspectFreeze<AccountId>>::balance_freezable(a, who),
|
||||
}
|
||||
}
|
||||
fn can_freeze(asset: Self::AssetId, id: &Self::Id, who: &AccountId) -> bool {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::InspectFreeze<AccountId>>::can_freeze(id, who),
|
||||
Right(a) => <Right as fungibles::InspectFreeze<AccountId>>::can_freeze(a, id, who),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungible::Unbalanced<AccountId>,
|
||||
Right: fungibles::Unbalanced<AccountId, Balance = Left::Balance>,
|
||||
Criterion: Convert<AssetKind, Either<(), Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> fungibles::Unbalanced<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
fn handle_dust(dust: fungibles::Dust<AccountId, Self>)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
match Criterion::convert(dust.0) {
|
||||
Left(()) =>
|
||||
<Left as fungible::Unbalanced<AccountId>>::handle_dust(fungible::Dust(dust.1)),
|
||||
Right(a) =>
|
||||
<Right as fungibles::Unbalanced<AccountId>>::handle_dust(fungibles::Dust(a, dust.1)),
|
||||
}
|
||||
}
|
||||
fn write_balance(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> Result<Option<Self::Balance>, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::Unbalanced<AccountId>>::write_balance(who, amount),
|
||||
Right(a) => <Right as fungibles::Unbalanced<AccountId>>::write_balance(a, who, amount),
|
||||
}
|
||||
}
|
||||
fn set_total_issuance(asset: Self::AssetId, amount: Self::Balance) -> () {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::Unbalanced<AccountId>>::set_total_issuance(amount),
|
||||
Right(a) => <Right as fungibles::Unbalanced<AccountId>>::set_total_issuance(a, amount),
|
||||
}
|
||||
}
|
||||
fn decrease_balance(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
precision: Precision,
|
||||
preservation: Preservation,
|
||||
force: Fortitude,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::Unbalanced<AccountId>>::decrease_balance(
|
||||
who,
|
||||
amount,
|
||||
precision,
|
||||
preservation,
|
||||
force,
|
||||
),
|
||||
Right(a) => <Right as fungibles::Unbalanced<AccountId>>::decrease_balance(
|
||||
a,
|
||||
who,
|
||||
amount,
|
||||
precision,
|
||||
preservation,
|
||||
force,
|
||||
),
|
||||
}
|
||||
}
|
||||
fn increase_balance(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
precision: Precision,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) =>
|
||||
<Left as fungible::Unbalanced<AccountId>>::increase_balance(who, amount, precision),
|
||||
Right(a) => <Right as fungibles::Unbalanced<AccountId>>::increase_balance(
|
||||
a, who, amount, precision,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungible::UnbalancedHold<AccountId>,
|
||||
Right: fungibles::UnbalancedHold<AccountId, Balance = Left::Balance, Reason = Left::Reason>,
|
||||
Criterion: Convert<AssetKind, Either<(), Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> fungibles::UnbalancedHold<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
fn set_balance_on_hold(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> DispatchResult {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::UnbalancedHold<AccountId>>::set_balance_on_hold(
|
||||
reason, who, amount,
|
||||
),
|
||||
Right(a) => <Right as fungibles::UnbalancedHold<AccountId>>::set_balance_on_hold(
|
||||
a, reason, who, amount,
|
||||
),
|
||||
}
|
||||
}
|
||||
fn decrease_balance_on_hold(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
precision: Precision,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::UnbalancedHold<AccountId>>::decrease_balance_on_hold(
|
||||
reason, who, amount, precision,
|
||||
),
|
||||
Right(a) => <Right as fungibles::UnbalancedHold<AccountId>>::decrease_balance_on_hold(
|
||||
a, reason, who, amount, precision,
|
||||
),
|
||||
}
|
||||
}
|
||||
fn increase_balance_on_hold(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
precision: Precision,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::UnbalancedHold<AccountId>>::increase_balance_on_hold(
|
||||
reason, who, amount, precision,
|
||||
),
|
||||
Right(a) => <Right as fungibles::UnbalancedHold<AccountId>>::increase_balance_on_hold(
|
||||
a, reason, who, amount, precision,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungible::Mutate<AccountId>,
|
||||
Right: fungibles::Mutate<AccountId, Balance = Left::Balance>,
|
||||
Criterion: Convert<AssetKind, Either<(), Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId: Eq,
|
||||
> fungibles::Mutate<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
fn mint_into(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::Mutate<AccountId>>::mint_into(who, amount),
|
||||
Right(a) => <Right as fungibles::Mutate<AccountId>>::mint_into(a, who, amount),
|
||||
}
|
||||
}
|
||||
fn burn_from(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
precision: Precision,
|
||||
force: Fortitude,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) =>
|
||||
<Left as fungible::Mutate<AccountId>>::burn_from(who, amount, precision, force),
|
||||
Right(a) =>
|
||||
<Right as fungibles::Mutate<AccountId>>::burn_from(a, who, amount, precision, force),
|
||||
}
|
||||
}
|
||||
fn shelve(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::Mutate<AccountId>>::shelve(who, amount),
|
||||
Right(a) => <Right as fungibles::Mutate<AccountId>>::shelve(a, who, amount),
|
||||
}
|
||||
}
|
||||
fn restore(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::Mutate<AccountId>>::restore(who, amount),
|
||||
Right(a) => <Right as fungibles::Mutate<AccountId>>::restore(a, who, amount),
|
||||
}
|
||||
}
|
||||
fn transfer(
|
||||
asset: Self::AssetId,
|
||||
source: &AccountId,
|
||||
dest: &AccountId,
|
||||
amount: Self::Balance,
|
||||
preservation: Preservation,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) =>
|
||||
<Left as fungible::Mutate<AccountId>>::transfer(source, dest, amount, preservation),
|
||||
Right(a) => <Right as fungibles::Mutate<AccountId>>::transfer(
|
||||
a,
|
||||
source,
|
||||
dest,
|
||||
amount,
|
||||
preservation,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_balance(asset: Self::AssetId, who: &AccountId, amount: Self::Balance) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::Mutate<AccountId>>::set_balance(who, amount),
|
||||
Right(a) => <Right as fungibles::Mutate<AccountId>>::set_balance(a, who, amount),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungible::MutateHold<AccountId>,
|
||||
Right: fungibles::MutateHold<AccountId, Balance = Left::Balance, Reason = Left::Reason>,
|
||||
Criterion: Convert<AssetKind, Either<(), Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> fungibles::MutateHold<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
fn hold(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> DispatchResult {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::MutateHold<AccountId>>::hold(reason, who, amount),
|
||||
Right(a) => <Right as fungibles::MutateHold<AccountId>>::hold(a, reason, who, amount),
|
||||
}
|
||||
}
|
||||
fn release(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
precision: Precision,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) =>
|
||||
<Left as fungible::MutateHold<AccountId>>::release(reason, who, amount, precision),
|
||||
Right(a) => <Right as fungibles::MutateHold<AccountId>>::release(
|
||||
a, reason, who, amount, precision,
|
||||
),
|
||||
}
|
||||
}
|
||||
fn burn_held(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
precision: Precision,
|
||||
force: Fortitude,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::MutateHold<AccountId>>::burn_held(
|
||||
reason, who, amount, precision, force,
|
||||
),
|
||||
Right(a) => <Right as fungibles::MutateHold<AccountId>>::burn_held(
|
||||
a, reason, who, amount, precision, force,
|
||||
),
|
||||
}
|
||||
}
|
||||
fn transfer_on_hold(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
source: &AccountId,
|
||||
dest: &AccountId,
|
||||
amount: Self::Balance,
|
||||
precision: Precision,
|
||||
mode: Restriction,
|
||||
force: Fortitude,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::MutateHold<AccountId>>::transfer_on_hold(
|
||||
reason, source, dest, amount, precision, mode, force,
|
||||
),
|
||||
Right(a) => <Right as fungibles::MutateHold<AccountId>>::transfer_on_hold(
|
||||
a, reason, source, dest, amount, precision, mode, force,
|
||||
),
|
||||
}
|
||||
}
|
||||
fn transfer_and_hold(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
source: &AccountId,
|
||||
dest: &AccountId,
|
||||
amount: Self::Balance,
|
||||
precision: Precision,
|
||||
preservation: Preservation,
|
||||
force: Fortitude,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::MutateHold<AccountId>>::transfer_and_hold(
|
||||
reason,
|
||||
source,
|
||||
dest,
|
||||
amount,
|
||||
precision,
|
||||
preservation,
|
||||
force,
|
||||
),
|
||||
Right(a) => <Right as fungibles::MutateHold<AccountId>>::transfer_and_hold(
|
||||
a,
|
||||
reason,
|
||||
source,
|
||||
dest,
|
||||
amount,
|
||||
precision,
|
||||
preservation,
|
||||
force,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungible::MutateFreeze<AccountId>,
|
||||
Right: fungibles::MutateFreeze<AccountId, Balance = Left::Balance, Id = Left::Id>,
|
||||
Criterion: Convert<AssetKind, Either<(), Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> fungibles::MutateFreeze<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
fn set_freeze(
|
||||
asset: Self::AssetId,
|
||||
id: &Self::Id,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> DispatchResult {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::MutateFreeze<AccountId>>::set_freeze(id, who, amount),
|
||||
Right(a) =>
|
||||
<Right as fungibles::MutateFreeze<AccountId>>::set_freeze(a, id, who, amount),
|
||||
}
|
||||
}
|
||||
fn extend_freeze(
|
||||
asset: Self::AssetId,
|
||||
id: &Self::Id,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> DispatchResult {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::MutateFreeze<AccountId>>::extend_freeze(id, who, amount),
|
||||
Right(a) =>
|
||||
<Right as fungibles::MutateFreeze<AccountId>>::extend_freeze(a, id, who, amount),
|
||||
}
|
||||
}
|
||||
fn thaw(asset: Self::AssetId, id: &Self::Id, who: &AccountId) -> DispatchResult {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as fungible::MutateFreeze<AccountId>>::thaw(id, who),
|
||||
Right(a) => <Right as fungibles::MutateFreeze<AccountId>>::thaw(a, id, who),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ConvertImbalanceDropHandler<
|
||||
Left,
|
||||
Right,
|
||||
Criterion,
|
||||
AssetKind,
|
||||
Balance,
|
||||
AssetId,
|
||||
AccountId,
|
||||
>(sp_std::marker::PhantomData<(Left, Right, Criterion, AssetKind, Balance, AssetId, AccountId)>);
|
||||
|
||||
impl<
|
||||
Left: fungible::HandleImbalanceDrop<Balance>,
|
||||
Right: fungibles::HandleImbalanceDrop<AssetId, Balance>,
|
||||
Criterion: Convert<AssetKind, Either<(), AssetId>>,
|
||||
AssetKind,
|
||||
Balance,
|
||||
AssetId,
|
||||
AccountId,
|
||||
> fungibles::HandleImbalanceDrop<AssetKind, Balance>
|
||||
for ConvertImbalanceDropHandler<Left, Right, Criterion, AssetKind, Balance, AssetId, AccountId>
|
||||
{
|
||||
fn handle(asset: AssetKind, amount: Balance) {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => Left::handle(amount),
|
||||
Right(a) => Right::handle(a, amount),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungible::Balanced<AccountId>,
|
||||
Right: fungibles::Balanced<AccountId, Balance = Left::Balance>,
|
||||
Criterion: Convert<AssetKind, Either<(), Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> fungibles::Balanced<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
type OnDropDebt = ConvertImbalanceDropHandler<
|
||||
Left::OnDropDebt,
|
||||
Right::OnDropDebt,
|
||||
Criterion,
|
||||
AssetKind,
|
||||
Left::Balance,
|
||||
Right::AssetId,
|
||||
AccountId,
|
||||
>;
|
||||
type OnDropCredit = ConvertImbalanceDropHandler<
|
||||
Left::OnDropCredit,
|
||||
Right::OnDropCredit,
|
||||
Criterion,
|
||||
AssetKind,
|
||||
Left::Balance,
|
||||
Right::AssetId,
|
||||
AccountId,
|
||||
>;
|
||||
|
||||
fn deposit(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
value: Self::Balance,
|
||||
precision: Precision,
|
||||
) -> Result<fungibles::Debt<AccountId, Self>, DispatchError> {
|
||||
match Criterion::convert(asset.clone()) {
|
||||
Left(()) => <Left as fungible::Balanced<AccountId>>::deposit(who, value, precision)
|
||||
.map(|d| fungibles::imbalance::from_fungible(d, asset)),
|
||||
Right(a) =>
|
||||
<Right as fungibles::Balanced<AccountId>>::deposit(a, who, value, precision)
|
||||
.map(|d| fungibles::imbalance::from_fungibles(d, asset)),
|
||||
}
|
||||
}
|
||||
fn issue(asset: Self::AssetId, amount: Self::Balance) -> fungibles::Credit<AccountId, Self> {
|
||||
match Criterion::convert(asset.clone()) {
|
||||
Left(()) => {
|
||||
let credit = <Left as fungible::Balanced<AccountId>>::issue(amount);
|
||||
fungibles::imbalance::from_fungible(credit, asset)
|
||||
},
|
||||
Right(a) => {
|
||||
let credit = <Right as fungibles::Balanced<AccountId>>::issue(a, amount);
|
||||
fungibles::imbalance::from_fungibles(credit, asset)
|
||||
},
|
||||
}
|
||||
}
|
||||
fn pair(
|
||||
asset: Self::AssetId,
|
||||
amount: Self::Balance,
|
||||
) -> (fungibles::Debt<AccountId, Self>, fungibles::Credit<AccountId, Self>) {
|
||||
match Criterion::convert(asset.clone()) {
|
||||
Left(()) => {
|
||||
let (a, b) = <Left as fungible::Balanced<AccountId>>::pair(amount);
|
||||
(
|
||||
fungibles::imbalance::from_fungible(a, asset.clone()),
|
||||
fungibles::imbalance::from_fungible(b, asset),
|
||||
)
|
||||
},
|
||||
Right(a) => {
|
||||
let (a, b) = <Right as fungibles::Balanced<AccountId>>::pair(a, amount);
|
||||
(
|
||||
fungibles::imbalance::from_fungibles(a, asset.clone()),
|
||||
fungibles::imbalance::from_fungibles(b, asset),
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
fn rescind(asset: Self::AssetId, amount: Self::Balance) -> fungibles::Debt<AccountId, Self> {
|
||||
match Criterion::convert(asset.clone()) {
|
||||
Left(()) => {
|
||||
let debt = <Left as fungible::Balanced<AccountId>>::rescind(amount);
|
||||
fungibles::imbalance::from_fungible(debt, asset)
|
||||
},
|
||||
Right(a) => {
|
||||
let debt = <Right as fungibles::Balanced<AccountId>>::rescind(a, amount);
|
||||
fungibles::imbalance::from_fungibles(debt, asset)
|
||||
},
|
||||
}
|
||||
}
|
||||
fn resolve(
|
||||
who: &AccountId,
|
||||
credit: fungibles::Credit<AccountId, Self>,
|
||||
) -> Result<(), fungibles::Credit<AccountId, Self>> {
|
||||
let asset = credit.asset();
|
||||
match Criterion::convert(asset.clone()) {
|
||||
Left(()) => {
|
||||
let credit = imbalance::from_fungibles(credit);
|
||||
<Left as fungible::Balanced<AccountId>>::resolve(who, credit)
|
||||
.map_err(|credit| fungibles::imbalance::from_fungible(credit, asset))
|
||||
},
|
||||
Right(a) => {
|
||||
let credit = fungibles::imbalance::from_fungibles(credit, a);
|
||||
<Right as fungibles::Balanced<AccountId>>::resolve(who, credit)
|
||||
.map_err(|credit| fungibles::imbalance::from_fungibles(credit, asset))
|
||||
},
|
||||
}
|
||||
}
|
||||
fn settle(
|
||||
who: &AccountId,
|
||||
debt: fungibles::Debt<AccountId, Self>,
|
||||
preservation: Preservation,
|
||||
) -> Result<fungibles::Credit<AccountId, Self>, fungibles::Debt<AccountId, Self>> {
|
||||
let asset = debt.asset();
|
||||
match Criterion::convert(asset.clone()) {
|
||||
Left(()) => {
|
||||
let debt = imbalance::from_fungibles(debt);
|
||||
match <Left as fungible::Balanced<AccountId>>::settle(who, debt, preservation) {
|
||||
Ok(c) => Ok(fungibles::imbalance::from_fungible(c, asset)),
|
||||
Err(d) => Err(fungibles::imbalance::from_fungible(d, asset)),
|
||||
}
|
||||
},
|
||||
Right(a) => {
|
||||
let debt = fungibles::imbalance::from_fungibles(debt, a);
|
||||
match <Right as fungibles::Balanced<AccountId>>::settle(who, debt, preservation) {
|
||||
Ok(c) => Ok(fungibles::imbalance::from_fungibles(c, asset)),
|
||||
Err(d) => Err(fungibles::imbalance::from_fungibles(d, asset)),
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
fn withdraw(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
value: Self::Balance,
|
||||
precision: Precision,
|
||||
preservation: Preservation,
|
||||
force: Fortitude,
|
||||
) -> Result<fungibles::Credit<AccountId, Self>, DispatchError> {
|
||||
match Criterion::convert(asset.clone()) {
|
||||
Left(()) => <Left as fungible::Balanced<AccountId>>::withdraw(
|
||||
who,
|
||||
value,
|
||||
precision,
|
||||
preservation,
|
||||
force,
|
||||
)
|
||||
.map(|c| fungibles::imbalance::from_fungible(c, asset)),
|
||||
Right(a) => <Right as fungibles::Balanced<AccountId>>::withdraw(
|
||||
a,
|
||||
who,
|
||||
value,
|
||||
precision,
|
||||
preservation,
|
||||
force,
|
||||
)
|
||||
.map(|c| fungibles::imbalance::from_fungibles(c, asset)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungible::BalancedHold<AccountId>,
|
||||
Right: fungibles::BalancedHold<AccountId, Balance = Left::Balance, Reason = Left::Reason>,
|
||||
Criterion: Convert<AssetKind, Either<(), Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> fungibles::BalancedHold<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
fn slash(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> (fungibles::Credit<AccountId, Self>, Self::Balance) {
|
||||
match Criterion::convert(asset.clone()) {
|
||||
Left(()) => {
|
||||
let (credit, amount) =
|
||||
<Left as fungible::BalancedHold<AccountId>>::slash(reason, who, amount);
|
||||
(fungibles::imbalance::from_fungible(credit, asset), amount)
|
||||
},
|
||||
Right(a) => {
|
||||
let (credit, amount) =
|
||||
<Right as fungibles::BalancedHold<AccountId>>::slash(a, reason, who, amount);
|
||||
(fungibles::imbalance::from_fungibles(credit, asset), amount)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungible::Inspect<AccountId>,
|
||||
Right: fungibles::Inspect<AccountId, Balance = Left::Balance> + fungibles::Create<AccountId>,
|
||||
Criterion: Convert<AssetKind, Either<(), Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> fungibles::Create<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
fn create(
|
||||
asset: AssetKind,
|
||||
admin: AccountId,
|
||||
is_sufficient: bool,
|
||||
min_balance: Self::Balance,
|
||||
) -> DispatchResult {
|
||||
match Criterion::convert(asset) {
|
||||
// no-op for `Left` since `Create` trait is not defined within `fungible::*`.
|
||||
Left(()) => Ok(()),
|
||||
Right(a) => <Right as fungibles::Create<AccountId>>::create(
|
||||
a,
|
||||
admin,
|
||||
is_sufficient,
|
||||
min_balance,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungible::Inspect<AccountId>
|
||||
+ AccountTouch<(), AccountId, Balance = <Left as fungible::Inspect<AccountId>>::Balance>,
|
||||
Right: fungibles::Inspect<AccountId>
|
||||
+ AccountTouch<
|
||||
Right::AssetId,
|
||||
AccountId,
|
||||
Balance = <Left as fungible::Inspect<AccountId>>::Balance,
|
||||
>,
|
||||
Criterion: Convert<AssetKind, Either<(), Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> AccountTouch<AssetKind, AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
type Balance = <Left as fungible::Inspect<AccountId>>::Balance;
|
||||
|
||||
fn deposit_required(asset: AssetKind) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as AccountTouch<(), AccountId>>::deposit_required(()),
|
||||
Right(a) => <Right as AccountTouch<Right::AssetId, AccountId>>::deposit_required(a),
|
||||
}
|
||||
}
|
||||
|
||||
fn should_touch(asset: AssetKind, who: &AccountId) -> bool {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as AccountTouch<(), AccountId>>::should_touch((), who),
|
||||
Right(a) => <Right as AccountTouch<Right::AssetId, AccountId>>::should_touch(a, who),
|
||||
}
|
||||
}
|
||||
|
||||
fn touch(asset: AssetKind, who: &AccountId, depositor: &AccountId) -> DispatchResult {
|
||||
match Criterion::convert(asset) {
|
||||
Left(()) => <Left as AccountTouch<(), AccountId>>::touch((), who, depositor),
|
||||
Right(a) =>
|
||||
<Right as AccountTouch<Right::AssetId, AccountId>>::touch(a, who, depositor),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,8 +20,9 @@
|
||||
|
||||
use super::*;
|
||||
use crate::traits::{
|
||||
fungible,
|
||||
misc::{SameOrOther, TryDrop},
|
||||
tokens::{AssetId, Balance},
|
||||
tokens::{imbalance::Imbalance as ImbalanceT, AssetId, Balance},
|
||||
};
|
||||
use frame_support_procedural::{EqNoBound, PartialEqNoBound, RuntimeDebugNoBound};
|
||||
use sp_runtime::traits::Zero;
|
||||
@@ -93,6 +94,11 @@ impl<
|
||||
Self { asset, amount, _phantom: PhantomData }
|
||||
}
|
||||
|
||||
/// Forget the imbalance without invoking the on-drop handler.
|
||||
pub(crate) fn forget(imbalance: Self) {
|
||||
sp_std::mem::forget(imbalance);
|
||||
}
|
||||
|
||||
pub fn drop_zero(self) -> Result<(), Self> {
|
||||
if self.amount.is_zero() {
|
||||
sp_std::mem::forget(self);
|
||||
@@ -168,6 +174,52 @@ impl<
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a `fungible` `imbalance` instance to an instance of a `fungibles` imbalance type using
|
||||
/// a specified `asset`.
|
||||
///
|
||||
/// This function facilitates imbalance conversions within the implementations of
|
||||
/// [`frame_support::traits::fungibles::UnionOf`], [`frame_support::traits::fungible::UnionOf`], and
|
||||
/// [`frame_support::traits::fungible::ItemOf`] adapters. It is intended only for internal use
|
||||
/// within the current crate.
|
||||
pub(crate) fn from_fungible<
|
||||
A: AssetId,
|
||||
B: Balance,
|
||||
OnDropIn: fungible::HandleImbalanceDrop<B>,
|
||||
OppositeIn: fungible::HandleImbalanceDrop<B>,
|
||||
OnDropOut: HandleImbalanceDrop<A, B>,
|
||||
OppositeOut: HandleImbalanceDrop<A, B>,
|
||||
>(
|
||||
imbalance: fungible::Imbalance<B, OnDropIn, OppositeIn>,
|
||||
asset: A,
|
||||
) -> Imbalance<A, B, OnDropOut, OppositeOut> {
|
||||
let new = Imbalance::new(asset, imbalance.peek());
|
||||
fungible::Imbalance::forget(imbalance);
|
||||
new
|
||||
}
|
||||
|
||||
/// Converts a `fungibles` `imbalance` instance of one type to another using a specified `asset`.
|
||||
///
|
||||
/// This function facilitates imbalance conversions within the implementations of
|
||||
/// [`frame_support::traits::fungibles::UnionOf`], [`frame_support::traits::fungible::UnionOf`], and
|
||||
/// [`frame_support::traits::fungible::ItemOf`] adapters. It is intended only for internal use
|
||||
/// within the current crate.
|
||||
pub(crate) fn from_fungibles<
|
||||
A: AssetId,
|
||||
B: Balance,
|
||||
OnDropIn: HandleImbalanceDrop<A, B>,
|
||||
OppositeIn: HandleImbalanceDrop<A, B>,
|
||||
AssetOut: AssetId,
|
||||
OnDropOut: HandleImbalanceDrop<AssetOut, B>,
|
||||
OppositeOut: HandleImbalanceDrop<AssetOut, B>,
|
||||
>(
|
||||
imbalance: Imbalance<A, B, OnDropIn, OppositeIn>,
|
||||
asset: AssetOut,
|
||||
) -> Imbalance<AssetOut, B, OnDropOut, OppositeOut> {
|
||||
let new = Imbalance::new(asset, imbalance.peek());
|
||||
Imbalance::forget(imbalance);
|
||||
new
|
||||
}
|
||||
|
||||
/// Imbalance implying that the total_issuance value is less than the sum of all account balances.
|
||||
pub type Debt<AccountId, B> = Imbalance<
|
||||
<B as Inspect<AccountId>>::AssetId,
|
||||
|
||||
@@ -21,11 +21,12 @@ pub mod approvals;
|
||||
mod enumerable;
|
||||
pub mod freeze;
|
||||
pub mod hold;
|
||||
mod imbalance;
|
||||
pub(crate) mod imbalance;
|
||||
mod lifetime;
|
||||
pub mod metadata;
|
||||
mod regular;
|
||||
pub mod roles;
|
||||
mod union_of;
|
||||
|
||||
pub use enumerable::Inspect as InspectEnumerable;
|
||||
pub use freeze::{Inspect as InspectFreeze, Mutate as MutateFreeze};
|
||||
@@ -38,3 +39,4 @@ pub use lifetime::{Create, Destroy};
|
||||
pub use regular::{
|
||||
Balanced, DecreaseIssuance, Dust, IncreaseIssuance, Inspect, Mutate, Unbalanced,
|
||||
};
|
||||
pub use union_of::UnionOf;
|
||||
|
||||
@@ -0,0 +1,897 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (Criterion) Parity Technologies (UK) Ltd.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//! Type to combine two `fungibles::*` implementations into one union `fungibles::*` implementation.
|
||||
|
||||
use frame_support::traits::{
|
||||
tokens::{
|
||||
fungibles, fungibles::imbalance, AssetId, DepositConsequence, Fortitude, Precision,
|
||||
Preservation, Provenance, Restriction, WithdrawConsequence,
|
||||
},
|
||||
AccountTouch,
|
||||
};
|
||||
use sp_runtime::{
|
||||
traits::Convert,
|
||||
DispatchError, DispatchResult, Either,
|
||||
Either::{Left, Right},
|
||||
};
|
||||
|
||||
/// Type to combine two `fungibles::*` implementations into one union `fungibles::*` implementation.
|
||||
///
|
||||
/// ### Parameters:
|
||||
/// - `Left` is `fungibles::*` implementation that is incorporated into the resulting union.
|
||||
/// - `Right` is `fungibles::*` implementation that is incorporated into the resulting union.
|
||||
/// - `Criterion` determines whether the `AssetKind` belongs to the `Left` or `Right` set.
|
||||
/// - `AssetKind` is a superset type encompassing asset kinds from `Left` and `Right` sets.
|
||||
/// - `AccountId` is an account identifier type.
|
||||
pub struct UnionOf<Left, Right, Criterion, AssetKind, AccountId>(
|
||||
sp_std::marker::PhantomData<(Left, Right, Criterion, AssetKind, AccountId)>,
|
||||
);
|
||||
|
||||
impl<
|
||||
Left: fungibles::Inspect<AccountId>,
|
||||
Right: fungibles::Inspect<AccountId, Balance = Left::Balance>,
|
||||
Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> fungibles::Inspect<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
type AssetId = AssetKind;
|
||||
type Balance = Left::Balance;
|
||||
|
||||
fn total_issuance(asset: Self::AssetId) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::Inspect<AccountId>>::total_issuance(a),
|
||||
Right(a) => <Right as fungibles::Inspect<AccountId>>::total_issuance(a),
|
||||
}
|
||||
}
|
||||
fn active_issuance(asset: Self::AssetId) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::Inspect<AccountId>>::active_issuance(a),
|
||||
Right(a) => <Right as fungibles::Inspect<AccountId>>::active_issuance(a),
|
||||
}
|
||||
}
|
||||
fn minimum_balance(asset: Self::AssetId) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::Inspect<AccountId>>::minimum_balance(a),
|
||||
Right(a) => <Right as fungibles::Inspect<AccountId>>::minimum_balance(a),
|
||||
}
|
||||
}
|
||||
fn balance(asset: Self::AssetId, who: &AccountId) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::Inspect<AccountId>>::balance(a, who),
|
||||
Right(a) => <Right as fungibles::Inspect<AccountId>>::balance(a, who),
|
||||
}
|
||||
}
|
||||
fn total_balance(asset: Self::AssetId, who: &AccountId) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::Inspect<AccountId>>::total_balance(a, who),
|
||||
Right(a) => <Right as fungibles::Inspect<AccountId>>::total_balance(a, who),
|
||||
}
|
||||
}
|
||||
fn reducible_balance(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
preservation: Preservation,
|
||||
force: Fortitude,
|
||||
) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::Inspect<AccountId>>::reducible_balance(
|
||||
a,
|
||||
who,
|
||||
preservation,
|
||||
force,
|
||||
),
|
||||
Right(a) => <Right as fungibles::Inspect<AccountId>>::reducible_balance(
|
||||
a,
|
||||
who,
|
||||
preservation,
|
||||
force,
|
||||
),
|
||||
}
|
||||
}
|
||||
fn can_deposit(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
provenance: Provenance,
|
||||
) -> DepositConsequence {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) =>
|
||||
<Left as fungibles::Inspect<AccountId>>::can_deposit(a, who, amount, provenance),
|
||||
Right(a) =>
|
||||
<Right as fungibles::Inspect<AccountId>>::can_deposit(a, who, amount, provenance),
|
||||
}
|
||||
}
|
||||
fn can_withdraw(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> WithdrawConsequence<Self::Balance> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::Inspect<AccountId>>::can_withdraw(a, who, amount),
|
||||
Right(a) => <Right as fungibles::Inspect<AccountId>>::can_withdraw(a, who, amount),
|
||||
}
|
||||
}
|
||||
fn asset_exists(asset: Self::AssetId) -> bool {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::Inspect<AccountId>>::asset_exists(a),
|
||||
Right(a) => <Right as fungibles::Inspect<AccountId>>::asset_exists(a),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungibles::InspectHold<AccountId>,
|
||||
Right: fungibles::InspectHold<AccountId, Balance = Left::Balance, Reason = Left::Reason>,
|
||||
Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> fungibles::InspectHold<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
type Reason = Left::Reason;
|
||||
|
||||
fn reducible_total_balance_on_hold(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
force: Fortitude,
|
||||
) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) =>
|
||||
<Left as fungibles::InspectHold<AccountId>>::reducible_total_balance_on_hold(
|
||||
a, who, force,
|
||||
),
|
||||
Right(a) =>
|
||||
<Right as fungibles::InspectHold<AccountId>>::reducible_total_balance_on_hold(
|
||||
a, who, force,
|
||||
),
|
||||
}
|
||||
}
|
||||
fn hold_available(asset: Self::AssetId, reason: &Self::Reason, who: &AccountId) -> bool {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::InspectHold<AccountId>>::hold_available(a, reason, who),
|
||||
Right(a) =>
|
||||
<Right as fungibles::InspectHold<AccountId>>::hold_available(a, reason, who),
|
||||
}
|
||||
}
|
||||
fn total_balance_on_hold(asset: Self::AssetId, who: &AccountId) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::InspectHold<AccountId>>::total_balance_on_hold(a, who),
|
||||
Right(a) => <Right as fungibles::InspectHold<AccountId>>::total_balance_on_hold(a, who),
|
||||
}
|
||||
}
|
||||
fn balance_on_hold(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &AccountId,
|
||||
) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::InspectHold<AccountId>>::balance_on_hold(a, reason, who),
|
||||
Right(a) =>
|
||||
<Right as fungibles::InspectHold<AccountId>>::balance_on_hold(a, reason, who),
|
||||
}
|
||||
}
|
||||
fn can_hold(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> bool {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) =>
|
||||
<Left as fungibles::InspectHold<AccountId>>::can_hold(a, reason, who, amount),
|
||||
Right(a) =>
|
||||
<Right as fungibles::InspectHold<AccountId>>::can_hold(a, reason, who, amount),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungibles::InspectFreeze<AccountId>,
|
||||
Right: fungibles::InspectFreeze<AccountId, Balance = Left::Balance, Id = Left::Id>,
|
||||
Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> fungibles::InspectFreeze<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
type Id = Left::Id;
|
||||
fn balance_frozen(asset: Self::AssetId, id: &Self::Id, who: &AccountId) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::InspectFreeze<AccountId>>::balance_frozen(a, id, who),
|
||||
Right(a) => <Right as fungibles::InspectFreeze<AccountId>>::balance_frozen(a, id, who),
|
||||
}
|
||||
}
|
||||
fn balance_freezable(asset: Self::AssetId, who: &AccountId) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::InspectFreeze<AccountId>>::balance_freezable(a, who),
|
||||
Right(a) => <Right as fungibles::InspectFreeze<AccountId>>::balance_freezable(a, who),
|
||||
}
|
||||
}
|
||||
fn can_freeze(asset: Self::AssetId, id: &Self::Id, who: &AccountId) -> bool {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::InspectFreeze<AccountId>>::can_freeze(a, id, who),
|
||||
Right(a) => <Right as fungibles::InspectFreeze<AccountId>>::can_freeze(a, id, who),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungibles::Unbalanced<AccountId>,
|
||||
Right: fungibles::Unbalanced<AccountId, Balance = Left::Balance>,
|
||||
Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> fungibles::Unbalanced<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
fn handle_dust(dust: fungibles::Dust<AccountId, Self>)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
match Criterion::convert(dust.0) {
|
||||
Left(a) =>
|
||||
<Left as fungibles::Unbalanced<AccountId>>::handle_dust(fungibles::Dust(a, dust.1)),
|
||||
Right(a) =>
|
||||
<Right as fungibles::Unbalanced<AccountId>>::handle_dust(fungibles::Dust(a, dust.1)),
|
||||
}
|
||||
}
|
||||
fn write_balance(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> Result<Option<Self::Balance>, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::Unbalanced<AccountId>>::write_balance(a, who, amount),
|
||||
Right(a) => <Right as fungibles::Unbalanced<AccountId>>::write_balance(a, who, amount),
|
||||
}
|
||||
}
|
||||
fn set_total_issuance(asset: Self::AssetId, amount: Self::Balance) -> () {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::Unbalanced<AccountId>>::set_total_issuance(a, amount),
|
||||
Right(a) => <Right as fungibles::Unbalanced<AccountId>>::set_total_issuance(a, amount),
|
||||
}
|
||||
}
|
||||
fn decrease_balance(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
precision: Precision,
|
||||
preservation: Preservation,
|
||||
force: Fortitude,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::Unbalanced<AccountId>>::decrease_balance(
|
||||
a,
|
||||
who,
|
||||
amount,
|
||||
precision,
|
||||
preservation,
|
||||
force,
|
||||
),
|
||||
Right(a) => <Right as fungibles::Unbalanced<AccountId>>::decrease_balance(
|
||||
a,
|
||||
who,
|
||||
amount,
|
||||
precision,
|
||||
preservation,
|
||||
force,
|
||||
),
|
||||
}
|
||||
}
|
||||
fn increase_balance(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
precision: Precision,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::Unbalanced<AccountId>>::increase_balance(
|
||||
a, who, amount, precision,
|
||||
),
|
||||
Right(a) => <Right as fungibles::Unbalanced<AccountId>>::increase_balance(
|
||||
a, who, amount, precision,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungibles::UnbalancedHold<AccountId>,
|
||||
Right: fungibles::UnbalancedHold<AccountId, Balance = Left::Balance, Reason = Left::Reason>,
|
||||
Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> fungibles::UnbalancedHold<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
fn set_balance_on_hold(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> DispatchResult {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::UnbalancedHold<AccountId>>::set_balance_on_hold(
|
||||
a, reason, who, amount,
|
||||
),
|
||||
Right(a) => <Right as fungibles::UnbalancedHold<AccountId>>::set_balance_on_hold(
|
||||
a, reason, who, amount,
|
||||
),
|
||||
}
|
||||
}
|
||||
fn decrease_balance_on_hold(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
precision: Precision,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::UnbalancedHold<AccountId>>::decrease_balance_on_hold(
|
||||
a, reason, who, amount, precision,
|
||||
),
|
||||
Right(a) => <Right as fungibles::UnbalancedHold<AccountId>>::decrease_balance_on_hold(
|
||||
a, reason, who, amount, precision,
|
||||
),
|
||||
}
|
||||
}
|
||||
fn increase_balance_on_hold(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
precision: Precision,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::UnbalancedHold<AccountId>>::increase_balance_on_hold(
|
||||
a, reason, who, amount, precision,
|
||||
),
|
||||
Right(a) => <Right as fungibles::UnbalancedHold<AccountId>>::increase_balance_on_hold(
|
||||
a, reason, who, amount, precision,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungibles::Mutate<AccountId>,
|
||||
Right: fungibles::Mutate<AccountId, Balance = Left::Balance>,
|
||||
Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId: Eq,
|
||||
> fungibles::Mutate<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
fn mint_into(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::Mutate<AccountId>>::mint_into(a, who, amount),
|
||||
Right(a) => <Right as fungibles::Mutate<AccountId>>::mint_into(a, who, amount),
|
||||
}
|
||||
}
|
||||
fn burn_from(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
precision: Precision,
|
||||
force: Fortitude,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) =>
|
||||
<Left as fungibles::Mutate<AccountId>>::burn_from(a, who, amount, precision, force),
|
||||
Right(a) =>
|
||||
<Right as fungibles::Mutate<AccountId>>::burn_from(a, who, amount, precision, force),
|
||||
}
|
||||
}
|
||||
fn shelve(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::Mutate<AccountId>>::shelve(a, who, amount),
|
||||
Right(a) => <Right as fungibles::Mutate<AccountId>>::shelve(a, who, amount),
|
||||
}
|
||||
}
|
||||
fn restore(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::Mutate<AccountId>>::restore(a, who, amount),
|
||||
Right(a) => <Right as fungibles::Mutate<AccountId>>::restore(a, who, amount),
|
||||
}
|
||||
}
|
||||
fn transfer(
|
||||
asset: Self::AssetId,
|
||||
source: &AccountId,
|
||||
dest: &AccountId,
|
||||
amount: Self::Balance,
|
||||
preservation: Preservation,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::Mutate<AccountId>>::transfer(
|
||||
a,
|
||||
source,
|
||||
dest,
|
||||
amount,
|
||||
preservation,
|
||||
),
|
||||
Right(a) => <Right as fungibles::Mutate<AccountId>>::transfer(
|
||||
a,
|
||||
source,
|
||||
dest,
|
||||
amount,
|
||||
preservation,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn set_balance(asset: Self::AssetId, who: &AccountId, amount: Self::Balance) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::Mutate<AccountId>>::set_balance(a, who, amount),
|
||||
Right(a) => <Right as fungibles::Mutate<AccountId>>::set_balance(a, who, amount),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungibles::MutateHold<AccountId>,
|
||||
Right: fungibles::MutateHold<AccountId, Balance = Left::Balance, Reason = Left::Reason>,
|
||||
Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> fungibles::MutateHold<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
fn hold(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> DispatchResult {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::MutateHold<AccountId>>::hold(a, reason, who, amount),
|
||||
Right(a) => <Right as fungibles::MutateHold<AccountId>>::hold(a, reason, who, amount),
|
||||
}
|
||||
}
|
||||
fn release(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
precision: Precision,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::MutateHold<AccountId>>::release(
|
||||
a, reason, who, amount, precision,
|
||||
),
|
||||
Right(a) => <Right as fungibles::MutateHold<AccountId>>::release(
|
||||
a, reason, who, amount, precision,
|
||||
),
|
||||
}
|
||||
}
|
||||
fn burn_held(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
precision: Precision,
|
||||
force: Fortitude,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::MutateHold<AccountId>>::burn_held(
|
||||
a, reason, who, amount, precision, force,
|
||||
),
|
||||
Right(a) => <Right as fungibles::MutateHold<AccountId>>::burn_held(
|
||||
a, reason, who, amount, precision, force,
|
||||
),
|
||||
}
|
||||
}
|
||||
fn transfer_on_hold(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
source: &AccountId,
|
||||
dest: &AccountId,
|
||||
amount: Self::Balance,
|
||||
precision: Precision,
|
||||
mode: Restriction,
|
||||
force: Fortitude,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::MutateHold<AccountId>>::transfer_on_hold(
|
||||
a, reason, source, dest, amount, precision, mode, force,
|
||||
),
|
||||
Right(a) => <Right as fungibles::MutateHold<AccountId>>::transfer_on_hold(
|
||||
a, reason, source, dest, amount, precision, mode, force,
|
||||
),
|
||||
}
|
||||
}
|
||||
fn transfer_and_hold(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
source: &AccountId,
|
||||
dest: &AccountId,
|
||||
amount: Self::Balance,
|
||||
precision: Precision,
|
||||
preservation: Preservation,
|
||||
force: Fortitude,
|
||||
) -> Result<Self::Balance, DispatchError> {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::MutateHold<AccountId>>::transfer_and_hold(
|
||||
a,
|
||||
reason,
|
||||
source,
|
||||
dest,
|
||||
amount,
|
||||
precision,
|
||||
preservation,
|
||||
force,
|
||||
),
|
||||
Right(a) => <Right as fungibles::MutateHold<AccountId>>::transfer_and_hold(
|
||||
a,
|
||||
reason,
|
||||
source,
|
||||
dest,
|
||||
amount,
|
||||
precision,
|
||||
preservation,
|
||||
force,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungibles::MutateFreeze<AccountId>,
|
||||
Right: fungibles::MutateFreeze<AccountId, Balance = Left::Balance, Id = Left::Id>,
|
||||
Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> fungibles::MutateFreeze<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
fn set_freeze(
|
||||
asset: Self::AssetId,
|
||||
id: &Self::Id,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> DispatchResult {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::MutateFreeze<AccountId>>::set_freeze(a, id, who, amount),
|
||||
Right(a) =>
|
||||
<Right as fungibles::MutateFreeze<AccountId>>::set_freeze(a, id, who, amount),
|
||||
}
|
||||
}
|
||||
fn extend_freeze(
|
||||
asset: Self::AssetId,
|
||||
id: &Self::Id,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> DispatchResult {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) =>
|
||||
<Left as fungibles::MutateFreeze<AccountId>>::extend_freeze(a, id, who, amount),
|
||||
Right(a) =>
|
||||
<Right as fungibles::MutateFreeze<AccountId>>::extend_freeze(a, id, who, amount),
|
||||
}
|
||||
}
|
||||
fn thaw(asset: Self::AssetId, id: &Self::Id, who: &AccountId) -> DispatchResult {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as fungibles::MutateFreeze<AccountId>>::thaw(a, id, who),
|
||||
Right(a) => <Right as fungibles::MutateFreeze<AccountId>>::thaw(a, id, who),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ConvertImbalanceDropHandler<
|
||||
Left,
|
||||
Right,
|
||||
LeftAssetId,
|
||||
RightAssetId,
|
||||
Criterion,
|
||||
AssetKind,
|
||||
Balance,
|
||||
AccountId,
|
||||
>(
|
||||
sp_std::marker::PhantomData<(
|
||||
Left,
|
||||
Right,
|
||||
LeftAssetId,
|
||||
RightAssetId,
|
||||
Criterion,
|
||||
AssetKind,
|
||||
Balance,
|
||||
AccountId,
|
||||
)>,
|
||||
);
|
||||
|
||||
impl<
|
||||
Left: fungibles::HandleImbalanceDrop<LeftAssetId, Balance>,
|
||||
Right: fungibles::HandleImbalanceDrop<RightAssetId, Balance>,
|
||||
LeftAssetId,
|
||||
RightAssetId,
|
||||
Criterion: Convert<AssetKind, Either<LeftAssetId, RightAssetId>>,
|
||||
AssetKind,
|
||||
Balance,
|
||||
AccountId,
|
||||
> fungibles::HandleImbalanceDrop<AssetKind, Balance>
|
||||
for ConvertImbalanceDropHandler<
|
||||
Left,
|
||||
Right,
|
||||
LeftAssetId,
|
||||
RightAssetId,
|
||||
Criterion,
|
||||
AssetKind,
|
||||
Balance,
|
||||
AccountId,
|
||||
>
|
||||
{
|
||||
fn handle(asset: AssetKind, amount: Balance) {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => Left::handle(a, amount),
|
||||
Right(a) => Right::handle(a, amount),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungibles::Balanced<AccountId>,
|
||||
Right: fungibles::Balanced<AccountId, Balance = Left::Balance>,
|
||||
Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> fungibles::Balanced<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
type OnDropDebt = ConvertImbalanceDropHandler<
|
||||
Left::OnDropDebt,
|
||||
Right::OnDropDebt,
|
||||
Left::AssetId,
|
||||
Right::AssetId,
|
||||
Criterion,
|
||||
AssetKind,
|
||||
Left::Balance,
|
||||
AccountId,
|
||||
>;
|
||||
type OnDropCredit = ConvertImbalanceDropHandler<
|
||||
Left::OnDropCredit,
|
||||
Right::OnDropCredit,
|
||||
Left::AssetId,
|
||||
Right::AssetId,
|
||||
Criterion,
|
||||
AssetKind,
|
||||
Left::Balance,
|
||||
AccountId,
|
||||
>;
|
||||
|
||||
fn deposit(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
value: Self::Balance,
|
||||
precision: Precision,
|
||||
) -> Result<fungibles::Debt<AccountId, Self>, DispatchError> {
|
||||
match Criterion::convert(asset.clone()) {
|
||||
Left(a) => <Left as fungibles::Balanced<AccountId>>::deposit(a, who, value, precision)
|
||||
.map(|debt| imbalance::from_fungibles(debt, asset)),
|
||||
Right(a) =>
|
||||
<Right as fungibles::Balanced<AccountId>>::deposit(a, who, value, precision)
|
||||
.map(|debt| imbalance::from_fungibles(debt, asset)),
|
||||
}
|
||||
}
|
||||
fn issue(asset: Self::AssetId, amount: Self::Balance) -> fungibles::Credit<AccountId, Self> {
|
||||
match Criterion::convert(asset.clone()) {
|
||||
Left(a) => {
|
||||
let credit = <Left as fungibles::Balanced<AccountId>>::issue(a, amount);
|
||||
imbalance::from_fungibles(credit, asset)
|
||||
},
|
||||
Right(a) => {
|
||||
let credit = <Right as fungibles::Balanced<AccountId>>::issue(a, amount);
|
||||
imbalance::from_fungibles(credit, asset)
|
||||
},
|
||||
}
|
||||
}
|
||||
fn pair(
|
||||
asset: Self::AssetId,
|
||||
amount: Self::Balance,
|
||||
) -> (fungibles::Debt<AccountId, Self>, fungibles::Credit<AccountId, Self>) {
|
||||
match Criterion::convert(asset.clone()) {
|
||||
Left(a) => {
|
||||
let (a, b) = <Left as fungibles::Balanced<AccountId>>::pair(a, amount);
|
||||
(imbalance::from_fungibles(a, asset.clone()), imbalance::from_fungibles(b, asset))
|
||||
},
|
||||
Right(a) => {
|
||||
let (a, b) = <Right as fungibles::Balanced<AccountId>>::pair(a, amount);
|
||||
(imbalance::from_fungibles(a, asset.clone()), imbalance::from_fungibles(b, asset))
|
||||
},
|
||||
}
|
||||
}
|
||||
fn rescind(asset: Self::AssetId, amount: Self::Balance) -> fungibles::Debt<AccountId, Self> {
|
||||
match Criterion::convert(asset.clone()) {
|
||||
Left(a) => {
|
||||
let debt = <Left as fungibles::Balanced<AccountId>>::rescind(a, amount);
|
||||
imbalance::from_fungibles(debt, asset)
|
||||
},
|
||||
Right(a) => {
|
||||
let debt = <Right as fungibles::Balanced<AccountId>>::rescind(a, amount);
|
||||
imbalance::from_fungibles(debt, asset)
|
||||
},
|
||||
}
|
||||
}
|
||||
fn resolve(
|
||||
who: &AccountId,
|
||||
credit: fungibles::Credit<AccountId, Self>,
|
||||
) -> Result<(), fungibles::Credit<AccountId, Self>> {
|
||||
let asset = credit.asset();
|
||||
match Criterion::convert(asset.clone()) {
|
||||
Left(a) => {
|
||||
let credit = imbalance::from_fungibles(credit, a);
|
||||
<Left as fungibles::Balanced<AccountId>>::resolve(who, credit)
|
||||
.map_err(|credit| imbalance::from_fungibles(credit, asset))
|
||||
},
|
||||
Right(a) => {
|
||||
let credit = imbalance::from_fungibles(credit, a);
|
||||
<Right as fungibles::Balanced<AccountId>>::resolve(who, credit)
|
||||
.map_err(|credit| imbalance::from_fungibles(credit, asset))
|
||||
},
|
||||
}
|
||||
}
|
||||
fn settle(
|
||||
who: &AccountId,
|
||||
debt: fungibles::Debt<AccountId, Self>,
|
||||
preservation: Preservation,
|
||||
) -> Result<fungibles::Credit<AccountId, Self>, fungibles::Debt<AccountId, Self>> {
|
||||
let asset = debt.asset();
|
||||
match Criterion::convert(asset.clone()) {
|
||||
Left(a) => {
|
||||
let debt = imbalance::from_fungibles(debt, a);
|
||||
match <Left as fungibles::Balanced<AccountId>>::settle(who, debt, preservation) {
|
||||
Ok(credit) => Ok(imbalance::from_fungibles(credit, asset)),
|
||||
Err(debt) => Err(imbalance::from_fungibles(debt, asset)),
|
||||
}
|
||||
},
|
||||
Right(a) => {
|
||||
let debt = imbalance::from_fungibles(debt, a);
|
||||
match <Right as fungibles::Balanced<AccountId>>::settle(who, debt, preservation) {
|
||||
Ok(credit) => Ok(imbalance::from_fungibles(credit, asset)),
|
||||
Err(debt) => Err(imbalance::from_fungibles(debt, asset)),
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
fn withdraw(
|
||||
asset: Self::AssetId,
|
||||
who: &AccountId,
|
||||
value: Self::Balance,
|
||||
precision: Precision,
|
||||
preservation: Preservation,
|
||||
force: Fortitude,
|
||||
) -> Result<fungibles::Credit<AccountId, Self>, DispatchError> {
|
||||
match Criterion::convert(asset.clone()) {
|
||||
Left(a) => <Left as fungibles::Balanced<AccountId>>::withdraw(
|
||||
a,
|
||||
who,
|
||||
value,
|
||||
precision,
|
||||
preservation,
|
||||
force,
|
||||
)
|
||||
.map(|credit| imbalance::from_fungibles(credit, asset)),
|
||||
Right(a) => <Right as fungibles::Balanced<AccountId>>::withdraw(
|
||||
a,
|
||||
who,
|
||||
value,
|
||||
precision,
|
||||
preservation,
|
||||
force,
|
||||
)
|
||||
.map(|credit| imbalance::from_fungibles(credit, asset)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungibles::BalancedHold<AccountId>,
|
||||
Right: fungibles::BalancedHold<AccountId, Balance = Left::Balance, Reason = Left::Reason>,
|
||||
Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> fungibles::BalancedHold<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
fn slash(
|
||||
asset: Self::AssetId,
|
||||
reason: &Self::Reason,
|
||||
who: &AccountId,
|
||||
amount: Self::Balance,
|
||||
) -> (fungibles::Credit<AccountId, Self>, Self::Balance) {
|
||||
match Criterion::convert(asset.clone()) {
|
||||
Left(a) => {
|
||||
let (credit, amount) =
|
||||
<Left as fungibles::BalancedHold<AccountId>>::slash(a, reason, who, amount);
|
||||
(imbalance::from_fungibles(credit, asset), amount)
|
||||
},
|
||||
Right(a) => {
|
||||
let (credit, amount) =
|
||||
<Right as fungibles::BalancedHold<AccountId>>::slash(a, reason, who, amount);
|
||||
(imbalance::from_fungibles(credit, asset), amount)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungibles::Inspect<AccountId> + fungibles::Create<AccountId>,
|
||||
Right: fungibles::Inspect<AccountId, Balance = Left::Balance> + fungibles::Create<AccountId>,
|
||||
Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> fungibles::Create<AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
fn create(
|
||||
asset: AssetKind,
|
||||
admin: AccountId,
|
||||
is_sufficient: bool,
|
||||
min_balance: Self::Balance,
|
||||
) -> DispatchResult {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) =>
|
||||
<Left as fungibles::Create<AccountId>>::create(a, admin, is_sufficient, min_balance),
|
||||
Right(a) => <Right as fungibles::Create<AccountId>>::create(
|
||||
a,
|
||||
admin,
|
||||
is_sufficient,
|
||||
min_balance,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<
|
||||
Left: fungibles::Inspect<AccountId> + AccountTouch<Left::AssetId, AccountId>,
|
||||
Right: fungibles::Inspect<AccountId>
|
||||
+ AccountTouch<
|
||||
Right::AssetId,
|
||||
AccountId,
|
||||
Balance = <Left as AccountTouch<Left::AssetId, AccountId>>::Balance,
|
||||
>,
|
||||
Criterion: Convert<AssetKind, Either<Left::AssetId, Right::AssetId>>,
|
||||
AssetKind: AssetId,
|
||||
AccountId,
|
||||
> AccountTouch<AssetKind, AccountId> for UnionOf<Left, Right, Criterion, AssetKind, AccountId>
|
||||
{
|
||||
type Balance = <Left as AccountTouch<Left::AssetId, AccountId>>::Balance;
|
||||
|
||||
fn deposit_required(asset: AssetKind) -> Self::Balance {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as AccountTouch<Left::AssetId, AccountId>>::deposit_required(a),
|
||||
Right(a) => <Right as AccountTouch<Right::AssetId, AccountId>>::deposit_required(a),
|
||||
}
|
||||
}
|
||||
|
||||
fn should_touch(asset: AssetKind, who: &AccountId) -> bool {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as AccountTouch<Left::AssetId, AccountId>>::should_touch(a, who),
|
||||
Right(a) => <Right as AccountTouch<Right::AssetId, AccountId>>::should_touch(a, who),
|
||||
}
|
||||
}
|
||||
|
||||
fn touch(asset: AssetKind, who: &AccountId, depositor: &AccountId) -> DispatchResult {
|
||||
match Criterion::convert(asset) {
|
||||
Left(a) => <Left as AccountTouch<Left::AssetId, AccountId>>::touch(a, who, depositor),
|
||||
Right(a) =>
|
||||
<Right as AccountTouch<Right::AssetId, AccountId>>::touch(a, who, depositor),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user