use crate::{types::*, BalanceSnapShots, Config, Pallet};
use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
use frame_suite::{
assets::*,
base::Delimited,
misc::{Directive, Extent},
mutation::MutHandle,
virtuals::*,
};
use frame_support::{
pallet_prelude::NMapKey,
traits::tokens::{Fortitude, Precision},
Blake2_128Concat,
};
use sp_core::{ConstU32, Get};
use sp_runtime::{Cow, DispatchError, Vec};
pub fn deposit<'a, T: Config<I>, I: 'static>(
balance: &'a mut VirtualBalance<T, I>,
variant: &'a T::Position,
id: &'a Digest<T>,
value: &'a AssetOf<T, I>,
qualify: &'a DispatchPolicy,
) -> Result<(AssetOf<T, I>, VirtualReceipt<T, I>), DispatchError> {
let input = <LazyInput<'a, T, I> as FromTag<_, Deposit>>::from_tag((
MutHandle::Borrowed(balance),
Cow::Borrowed(variant),
Cow::Borrowed(id),
Cow::Borrowed(value),
Cow::Borrowed(qualify),
));
let raw = Pallet::<T, I>::deposit(input);
let Ok(result) = TryIntoTag::<_, Deposit>::try_into_tag(raw) else {
return Err(crate::Error::<T, I>::CorruptedPlugin.into());
};
match result {
Ok((asset, receipt)) => Ok((asset.into_owned(), receipt.into_owned())),
Err(e) => Err(e.into()),
}
}
pub fn withdraw<'a, T: Config<I>, I: 'static>(
balance: &'a mut VirtualBalance<T, I>,
variant: &'a T::Position,
id: &'a Digest<T>,
receipt: &'a VirtualReceipt<T, I>,
) -> Result<AssetOf<T, I>, DispatchError> {
let input = <LazyInput<'a, T, I> as FromTag<_, Withdraw>>::from_tag((
MutHandle::Borrowed(balance),
Cow::Borrowed(variant),
Cow::Borrowed(id),
Cow::Borrowed(receipt),
));
let raw = Pallet::<T, I>::withdraw(input);
let Ok(result) = TryIntoTag::<_, Withdraw>::try_into_tag(raw) else {
return Err(crate::Error::<T, I>::CorruptedPlugin.into());
};
match result {
Ok(v) => Ok(*v),
Err(e) => Err(e.into()),
}
}
pub fn mint<'a, T: Config<I>, I: 'static>(
balance: &'a mut VirtualBalance<T, I>,
variant: &'a T::Position,
id: &'a Digest<T>,
value: &'a AssetOf<T, I>,
qualify: &'a DispatchPolicy,
) -> Result<AssetOf<T, I>, DispatchError> {
let input = <LazyInput<'a, T, I> as FromTag<_, Mint>>::from_tag((
MutHandle::Borrowed(balance),
Cow::Borrowed(variant),
Cow::Borrowed(id),
Cow::Borrowed(value),
Cow::Borrowed(qualify),
));
let raw = Pallet::<T, I>::mint(input);
let Ok(result) = TryIntoTag::<_, Mint>::try_into_tag(raw) else {
return Err(crate::Error::<T, I>::CorruptedPlugin.into());
};
match result {
Ok(v) => Ok(v.into_owned()),
Err(e) => Err(e.into()),
}
}
pub fn reap<'a, T: Config<I>, I: 'static>(
balance: &'a mut VirtualBalance<T, I>,
variant: &'a T::Position,
id: &'a Digest<T>,
value: &'a AssetOf<T, I>,
qualify: &'a DispatchPolicy,
) -> Result<AssetOf<T, I>, DispatchError> {
let input = <LazyInput<'a, T, I> as FromTag<_, Reap>>::from_tag((
MutHandle::Borrowed(balance),
Cow::Borrowed(variant),
Cow::Borrowed(id),
Cow::Borrowed(value),
Cow::Borrowed(qualify),
));
let raw = Pallet::<T, I>::reap(input);
let Ok(result) = TryIntoTag::<_, Reap>::try_into_tag(raw) else {
return Err(crate::Error::<T, I>::CorruptedPlugin.into());
};
match result {
Ok(v) => Ok(v.into_owned()),
Err(e) => Err(e.into()),
}
}
#[allow(unused)]
pub fn drain<'a, T: Config<I>, I: 'static>(
balance: &'a mut VirtualBalance<T, I>,
variant: &'a T::Position,
id: &'a Digest<T>,
) -> Result<(), DispatchError> {
let input = <LazyInput<'a, T, I> as FromTag<_, Drain>>::from_tag((
MutHandle::Borrowed(balance),
Cow::Borrowed(variant),
Cow::Borrowed(id),
));
let raw = <Pallet<T, I> as LazyBalance>::drain(input);
let Ok(result) = TryIntoTag::<_, Drain>::try_into_tag(raw) else {
return Err(crate::Error::<T, I>::CorruptedPlugin.into());
};
match result {
Ok(_) => Ok(()),
Err(e) => Err(e.into()),
}
}
pub fn can_deposit<'a, T: Config<I>, I: 'static>(
balance: &'a VirtualBalance<T, I>,
variant: &'a T::Position,
id: &'a Digest<T>,
value: &'a AssetOf<T, I>,
qualify: &'a DispatchPolicy,
) -> Result<(), DispatchError> {
let input = <LazyInput<'a, T, I> as FromTag<_, CanDeposit>>::from_tag((
Cow::Borrowed(balance),
Cow::Borrowed(variant),
Cow::Borrowed(id),
Cow::Borrowed(value),
Cow::Borrowed(qualify),
));
let raw = Pallet::<T, I>::can_deposit(input);
let Ok(result) = TryIntoTag::<_, CanDeposit>::try_into_tag(raw) else {
return Err(crate::Error::<T, I>::CorruptedPlugin.into());
};
match result {
Ok(_) => Ok(()),
Err(e) => Err(e.into()),
}
}
pub fn can_withdraw<'a, T: Config<I>, I: 'static>(
balance: &'a VirtualBalance<T, I>,
variant: &'a T::Position,
id: &'a Digest<T>,
receipt: &'a VirtualReceipt<T, I>,
) -> Result<(), DispatchError> {
let input = <LazyInput<'a, T, I> as FromTag<_, CanWithdraw>>::from_tag((
Cow::Borrowed(balance),
Cow::Borrowed(variant),
Cow::Borrowed(id),
Cow::Borrowed(receipt),
));
let raw = Pallet::<T, I>::can_withdraw(input);
let Ok(result) = TryIntoTag::<_, CanWithdraw>::try_into_tag(raw) else {
return Err(crate::Error::<T, I>::CorruptedPlugin.into());
};
match result {
Ok(_) => Ok(()),
Err(e) => Err(e.into()),
}
}
pub fn can_mint<'a, T: Config<I>, I: 'static>(
balance: &'a VirtualBalance<T, I>,
variant: &'a T::Position,
id: &'a Digest<T>,
value: &'a AssetOf<T, I>,
qualify: &'a DispatchPolicy,
) -> Result<(), DispatchError> {
let input = <LazyInput<'a, T, I> as FromTag<_, CanMint>>::from_tag((
Cow::Borrowed(balance),
Cow::Borrowed(variant),
Cow::Borrowed(id),
Cow::Borrowed(value),
Cow::Borrowed(qualify),
));
let raw = Pallet::<T, I>::can_mint(input);
let Ok(result) = TryIntoTag::<_, CanMint>::try_into_tag(raw) else {
return Err(crate::Error::<T, I>::CorruptedPlugin.into());
};
match result {
Ok(_) => Ok(()),
Err(e) => Err(e.into()),
}
}
pub fn can_reap<'a, T: Config<I>, I: 'static>(
balance: &'a VirtualBalance<T, I>,
variant: &'a T::Position,
id: &'a Digest<T>,
value: &'a AssetOf<T, I>,
qualify: &'a DispatchPolicy,
) -> Result<(), DispatchError> {
let input = <LazyInput<'a, T, I> as FromTag<_, CanReap>>::from_tag((
Cow::Borrowed(balance),
Cow::Borrowed(variant),
Cow::Borrowed(id),
Cow::Borrowed(value),
Cow::Borrowed(qualify),
));
let raw = Pallet::<T, I>::can_reap(input);
let Ok(result) = TryIntoTag::<_, CanReap>::try_into_tag(raw) else {
return Err(crate::Error::<T, I>::CorruptedPlugin.into());
};
match result {
Ok(_) => Ok(()),
Err(e) => Err(e.into()),
}
}
pub fn balance_total<'a, T: Config<I>, I: 'static>(
balance: &'a VirtualBalance<T, I>,
variant: &'a T::Position,
id: &'a Digest<T>,
) -> Result<AssetOf<T, I>, DispatchError> {
let input = <LazyInput<'a, T, I> as FromTag<_, TotalValue>>::from_tag((
Cow::Borrowed(balance),
Cow::Borrowed(variant),
Cow::Borrowed(id),
));
let raw = Pallet::<T, I>::total_value(input);
let Ok(result) = TryIntoTag::<_, TotalValue>::try_into_tag(raw) else {
return Err(crate::Error::<T, I>::CorruptedPlugin.into());
};
match result {
Ok(v) => Ok(*v),
Err(e) => Err(e.into()),
}
}
pub fn receipt_active_value<'a, T: Config<I>, I: 'static>(
balance: &'a VirtualBalance<T, I>,
variant: &'a T::Position,
id: &'a Digest<T>,
receipt: &'a VirtualReceipt<T, I>,
) -> Result<AssetOf<T, I>, DispatchError> {
let input = <LazyInput<'a, T, I> as FromTag<_, ReceiptActiveValue>>::from_tag((
Cow::Borrowed(balance),
Cow::Borrowed(variant),
Cow::Borrowed(id),
Cow::Borrowed(receipt),
));
let raw = Pallet::<T, I>::receipt_active_value(input);
let Ok(result) = TryIntoTag::<_, ReceiptActiveValue>::try_into_tag(raw) else {
return Err(crate::Error::<T, I>::CorruptedPlugin.into());
};
match result {
Ok(v) => Ok(*v),
Err(e) => Err(e.into()),
}
}
pub fn receipt_deposit_value<'a, T: Config<I>, I: 'static>(
receipt: &'a VirtualReceipt<T, I>,
) -> Result<AssetOf<T, I>, DispatchError> {
let input =
<LazyInput<'a, T, I> as FromTag<_, ReceiptDepositValue>>::from_tag(Cow::Borrowed(receipt));
let raw = Pallet::<T, I>::receipt_deposit_value(input);
let Ok(result) = TryIntoTag::<_, ReceiptDepositValue>::try_into_tag(raw) else {
return Err(crate::Error::<T, I>::CorruptedPlugin.into());
};
match result {
Ok(v) => Ok(*v),
Err(e) => Err(e.into()),
}
}
pub fn has_deposits<'a, T: Config<I>, I: 'static>(
balance: &'a VirtualBalance<T, I>,
variant: &'a T::Position,
id: &'a Digest<T>,
) -> Result<(), DispatchError> {
let input = <LazyInput<'a, T, I> as FromTag<_, HasDeposits>>::from_tag((
Cow::Borrowed(balance),
Cow::Borrowed(variant),
Cow::Borrowed(id),
));
let raw = Pallet::<T, I>::has_deposits(input);
let Ok(result) = TryIntoTag::<_, HasDeposits>::try_into_tag(raw) else {
return Err(crate::Error::<T, I>::CorruptedPlugin.into());
};
match result {
Ok(_) => Ok(()),
Err(e) => Err(e.into()),
}
}
pub fn deposit_limits_of<'a, T: Config<I>, I: 'static>(
balance: &'a VirtualBalance<T, I>,
variant: &'a T::Position,
id: &'a Digest<T>,
qualify: &'a DispatchPolicy,
) -> Result<LimitsProduct<T, I>, DispatchError> {
let input = <LazyInput<'a, T, I> as FromTag<_, DepositLimits>>::from_tag((
Cow::Borrowed(balance),
Cow::Borrowed(variant),
Cow::Borrowed(id),
Cow::Borrowed(qualify),
));
let raw = Pallet::<T, I>::deposit_limits(input);
let Ok(result) = TryIntoTag::<_, DepositLimits>::try_into_tag(raw) else {
return Err(crate::Error::<T, I>::CorruptedPlugin.into());
};
match result {
Ok(v) => Ok(v.into_owned()),
Err(e) => Err(e.into()),
}
}
pub fn mint_limits_of<'a, T: Config<I>, I: 'static>(
balance: &'a VirtualBalance<T, I>,
variant: &'a T::Position,
id: &'a Digest<T>,
qualify: &'a DispatchPolicy,
) -> Result<LimitsProduct<T, I>, DispatchError> {
let input = <LazyInput<'a, T, I> as FromTag<_, MintLimits>>::from_tag((
Cow::Borrowed(balance),
Cow::Borrowed(variant),
Cow::Borrowed(id),
Cow::Borrowed(qualify),
));
let raw = Pallet::<T, I>::mint_limits(input);
let Ok(result) = TryIntoTag::<_, MintLimits>::try_into_tag(raw) else {
return Err(crate::Error::<T, I>::CorruptedPlugin.into());
};
match result {
Ok(v) => Ok(v.into_owned()),
Err(e) => Err(e.into()),
}
}
pub fn reap_limits_of<'a, T: Config<I>, I: 'static>(
balance: &'a VirtualBalance<T, I>,
variant: &'a T::Position,
id: &'a Digest<T>,
qualify: &'a DispatchPolicy,
) -> Result<LimitsProduct<T, I>, DispatchError> {
let input = <LazyInput<'a, T, I> as FromTag<_, ReapLimits>>::from_tag((
Cow::Borrowed(balance),
Cow::Borrowed(variant),
Cow::Borrowed(id),
Cow::Borrowed(qualify),
));
let raw = Pallet::<T, I>::reap_limits(input);
let Ok(result) = TryIntoTag::<_, ReapLimits>::try_into_tag(raw) else {
return Err(crate::Error::<T, I>::CorruptedPlugin.into());
};
match result {
Ok(v) => Ok(v.into_owned()),
Err(e) => Err(e.into()),
}
}
impl<T, I> LazyBalance for Pallet<T, I>
where
T: Config<I>,
I: 'static,
{
type Asset = AssetOf<T, I>;
type Rational = T::Bias;
type Time = T::Time;
type Balance = VirtualBalance<T, I>;
type Variant = T::Position;
type Id = Digest<T>;
type Limits = LimitsProduct<T, I>;
type Subject = DispatchPolicy;
type SnapShot = VirtualSnapShot<T, I>;
type Receipt = VirtualReceipt<T, I>;
type Input<'a> = LazyInput<'a, T, I>;
type Output<'a> = LazyOutput<'a, T, I>;
type BalanceFamily<'a> = T::BalanceFamily<'a>;
type BalanceContext = T::BalanceContext;
}
pub trait ProductProvider<Asset, Rational, Time, Addon>:
VirtualDynExtensionSchema<Addon>
+ VirtualDynBound<Asset>
+ VirtualDynBound<Rational>
+ VirtualDynBound<Time>
where
Addon: DiscriminantTag,
Rational: DiscriminantTag,
Time: DiscriminantTag,
Asset: DiscriminantTag,
{
}
impl<T, Asset, Rational, Time, Addon> ProductProvider<Asset, Rational, Time, Addon> for T
where
T: VirtualDynExtensionSchema<Addon>
+ VirtualDynBound<Asset>
+ VirtualDynBound<Rational>
+ VirtualDynBound<Time>,
Addon: DiscriminantTag,
Rational: DiscriminantTag,
Time: DiscriminantTag,
Asset: DiscriminantTag,
{
}
#[derive(Encode, Decode, DecodeWithMemTracking, TypeInfo, MaxEncodedLen)]
#[codec(encode_bound(
Provider: ProductProvider<Asset, Rational, Time, Addon>,
<Provider as VirtualDynExtensionSchema<Addon>>::Repr: Delimited + Default
))]
#[codec(decode_bound(
Provider: ProductProvider<Asset, Rational, Time, Addon>,
<Provider as VirtualDynExtensionSchema<Addon>>::Repr: Delimited + Default
))]
#[codec(decode_with_mem_tracking_bound(
Provider: ProductProvider<Asset, Rational, Time, Addon>,
<Provider as VirtualDynExtensionSchema<Addon>>::Repr: Delimited + Default
))]
#[codec(mel_bound(
<Provider as VirtualDynExtensionSchema<Addon>>::Repr: MaxEncodedLen
))]
#[scale_info(skip_type_params(T, I, Provider, Asset, Rational, Time, Addon))]
pub struct ProductType<T, I, Provider, Asset, Rational, Time, Addon>
where
Provider: ProductProvider<Asset, Rational, Time, Addon>,
T: Config<I>,
I: 'static,
Addon: DiscriminantTag,
Rational: DiscriminantTag,
Time: DiscriminantTag,
Asset: DiscriminantTag,
{
asset: SumDynType<AssetOf<T, I>, <Provider as VirtualDynBound<Asset>>::Bound>,
bias: SumDynType<T::Bias, <Provider as VirtualDynBound<Rational>>::Bound>,
time: SumDynType<T::Time, <Provider as VirtualDynBound<Time>>::Bound>,
addon: <Provider as VirtualDynExtensionSchema<Addon>>::Repr,
}
impl<T, I, Provider, Asset, Rational, Time, Addon> Clone
for ProductType<T, I, Provider, Asset, Rational, Time, Addon>
where
Provider: ProductProvider<Asset, Rational, Time, Addon>,
T: Config<I>,
I: 'static,
Addon: DiscriminantTag,
Rational: DiscriminantTag,
Time: DiscriminantTag,
Asset: DiscriminantTag,
{
fn clone(&self) -> Self {
Self {
asset: self.asset.clone(),
bias: self.bias.clone(),
time: self.time.clone(),
addon: self.addon.clone(),
}
}
}
impl<T, I, Provider, Asset, Rational, Time, Addon> core::fmt::Debug
for ProductType<T, I, Provider, Asset, Rational, Time, Addon>
where
Provider: ProductProvider<Asset, Rational, Time, Addon>,
T: Config<I>,
I: 'static,
Addon: DiscriminantTag,
Rational: DiscriminantTag,
Time: DiscriminantTag,
Asset: DiscriminantTag,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("ProductType")
.field("asset", &self.asset)
.field("bias", &self.bias)
.field("time", &self.time)
.field("addon", &self.addon)
.finish()
}
}
impl<T, I, Provider, Asset, Rational, Time, Addon> Default
for ProductType<T, I, Provider, Asset, Rational, Time, Addon>
where
Provider: ProductProvider<Asset, Rational, Time, Addon>,
T: Config<I>,
I: 'static,
Addon: DiscriminantTag,
Rational: DiscriminantTag,
Time: DiscriminantTag,
Asset: DiscriminantTag,
{
fn default() -> Self {
Self {
asset: Default::default(),
bias: Default::default(),
time: Default::default(),
addon: Default::default(),
}
}
}
impl<T, I, Provider, Asset, Rational, Time, Addon> PartialEq
for ProductType<T, I, Provider, Asset, Rational, Time, Addon>
where
Provider: ProductProvider<Asset, Rational, Time, Addon>,
T: Config<I>,
I: 'static,
Addon: DiscriminantTag,
Rational: DiscriminantTag,
Time: DiscriminantTag,
Asset: DiscriminantTag,
{
fn eq(&self, other: &Self) -> bool {
self.asset == other.asset
&& self.bias == other.bias
&& self.time == other.time
&& self.addon == other.addon
}
}
impl<T, I, Provider, Asset, Rational, Time, Addon> Eq
for ProductType<T, I, Provider, Asset, Rational, Time, Addon>
where
Provider: ProductProvider<Asset, Rational, Time, Addon>,
T: Config<I>,
I: 'static,
Addon: DiscriminantTag,
Rational: DiscriminantTag,
Time: DiscriminantTag,
Asset: DiscriminantTag,
{
}
macro_rules! impl_v_field {
(
$tag:ty,
$field:ident,
$product:ty,
$asset:ty,
$rational:ty,
$time:ty,
$addon:ty,
$value:ty
) => {
impl<T, I, Provider> VirtualDynField<$tag> for $product
where
Provider: ProductProvider<$asset, $rational, $time, $addon>,
T: Config<I>,
I: 'static,
{
type None = ();
type Some = $value;
type Many = Vec<$value>;
type Repr = SumDynType<$value, <Provider as VirtualDynBound<$tag>>::Bound>;
fn access(&self) -> Self::Repr {
self.$field.clone()
}
fn mutate(&mut self, v: Self::Repr) {
self.$field = v
}
fn len(&self) -> usize {
match &self.$field {
SumDynType::None => 0,
SumDynType::Some(_) => 1,
SumDynType::Many(v) => v.len(),
}
}
fn min(&self) -> usize {
match &self.$field {
SumDynType::None => 0,
SumDynType::Some(_) => 1,
SumDynType::Many(_) => 0,
}
}
fn max(&self) -> usize {
match &self.$field {
SumDynType::None => 0,
SumDynType::Some(_) => 1,
SumDynType::Many(_) => {
<Provider as VirtualDynBound<$tag>>::Bound::get() as usize
}
}
}
}
};
}
macro_rules! impl_v_ext {
(
$tag:ty,
$field:ident,
$product:ty,
$asset:ty,
$rational:ty,
$time:ty,
$addon:ty
) => {
impl<T, I, Provider> VirtualDynExtension<$tag> for $product
where
Provider: ProductProvider<$asset, $rational, $time, $addon>,
T: Config<I>,
I: 'static,
{
type TypesVia = Provider;
fn access(&self) -> <Provider as VirtualDynExtensionSchema<$addon>>::Repr {
self.$field.clone()
}
fn mutate(&mut self, v: <Provider as VirtualDynExtensionSchema<$addon>>::Repr) {
self.$field = v
}
}
};
}
macro_rules! impl_product_alloc {
(
$asset:ty,
$rational:ty,
$time:ty,
$addon:ty
) => {
impl_v_field!(
$asset,
asset,
ProductType<T,I,Provider,$asset,$rational,$time,$addon>,
$asset,
$rational,
$time,
$addon,
AssetOf<T,I>
);
impl_v_field!(
$rational,
bias,
ProductType<T,I,Provider,$asset,$rational,$time,$addon>,
$asset,
$rational,
$time,
$addon,
T::Bias
);
impl_v_field!(
$time,
time,
ProductType<T,I,Provider,$asset,$rational,$time,$addon>,
$asset,
$rational,
$time,
$addon,
T::Time
);
impl_v_ext!(
$addon,
addon,
ProductType<T,I,Provider,$asset,$rational,$time,$addon>,
$asset,
$rational,
$time,
$addon
);
};
}
impl_product_alloc!(BalanceAsset, BalanceRational, BalanceTime, BalanceAddon);
impl_product_alloc!(SnapShotAsset, SnapShotRational, SnapShotTime, SnapShotAddon);
impl_product_alloc!(ReceiptAsset, ReceiptRational, ReceiptTime, ReceiptAddon);
type LazyBalanceOf<T, I> = VirtualBalance<T, I>;
type LazyReceiptOf<T, I> = VirtualReceipt<T, I>;
type LazyAssetOf<T, I> = AssetOf<T, I>;
type LazyVariantOf<T, I> = <Pallet<T, I> as LazyBalance>::Variant;
type LazyIdOf<T, I> = <Pallet<T, I> as LazyBalance>::Id;
type LazyErrorOf<T, I> = <Context<Pallet<T, I>> as VirtualError<LazyBalanceError>>::Error;
macro_rules! lazy_input {
(
$(
$variant:ident (
$( $field:ident : $ty:ty ),* $(,)?
)
),* $(,)?
) => {
pub enum LazyInput<'a, T, I>
where
T: Config<I>,
I: 'static,
{
$(
$variant( $( $ty ),* ),
)*
}
$(
#[allow(unused_parens)]
impl<'a, T, I>
FromTag<( $( $ty ),* ), $variant>
for LazyInput<'a, T, I>
where
T: Config<I>,
I: 'static,
{
fn from_tag(t: ( $( $ty ),* )) -> Self {
let ( $( $field ),* ) = t;
LazyInput::$variant( $( $field ),* )
}
}
#[allow(unused_parens)]
impl<'a, T, I>
TryIntoTag<( $( $ty ),* ), $variant>
for LazyInput<'a, T, I>
where
T: Config<I>,
I: 'static,
{
type Error = ();
fn try_into_tag(self)
-> Result<( $( $ty ),* ), Self::Error>
{
match self {
LazyInput::$variant( $( $field ),* ) =>
Ok(( $( $field ),* )),
_ => Err(()),
}
}
}
)*
};
}
lazy_input! {
Deposit(
balance: MutHandle<'a, LazyBalanceOf<T, I>>,
variant: Cow<'a, LazyVariantOf<T, I>>,
id: Cow<'a, LazyIdOf<T, I>>,
asset: Cow<'a, LazyAssetOf<T, I>>,
subject: Cow<'a, DispatchPolicy>,
),
Mint(
balance: MutHandle<'a, LazyBalanceOf<T, I>>,
variant: Cow<'a, LazyVariantOf<T, I>>,
id: Cow<'a, LazyIdOf<T, I>>,
asset: Cow<'a, LazyAssetOf<T, I>>,
subject: Cow<'a, DispatchPolicy>,
),
Reap(
balance: MutHandle<'a, LazyBalanceOf<T, I>>,
variant: Cow<'a, LazyVariantOf<T, I>>,
id: Cow<'a, LazyIdOf<T, I>>,
asset: Cow<'a, LazyAssetOf<T, I>>,
subject: Cow<'a, DispatchPolicy>,
),
Drain(
balance: MutHandle<'a, LazyBalanceOf<T, I>>,
variant: Cow<'a, LazyVariantOf<T, I>>,
id: Cow<'a, LazyIdOf<T, I>>,
),
Withdraw(
balance: MutHandle<'a, LazyBalanceOf<T, I>>,
variant: Cow<'a, LazyVariantOf<T, I>>,
id: Cow<'a, LazyIdOf<T, I>>,
receipt: Cow<'a, LazyReceiptOf<T, I>>,
),
CanDeposit(
balance: Cow<'a, LazyBalanceOf<T, I>>,
variant: Cow<'a, LazyVariantOf<T, I>>,
id: Cow<'a, LazyIdOf<T, I>>,
asset: Cow<'a, LazyAssetOf<T, I>>,
subject: Cow<'a, DispatchPolicy>,
),
CanMint(
balance: Cow<'a, LazyBalanceOf<T, I>>,
variant: Cow<'a, LazyVariantOf<T, I>>,
id: Cow<'a, LazyIdOf<T, I>>,
asset: Cow<'a, LazyAssetOf<T, I>>,
subject: Cow<'a, DispatchPolicy>,
),
CanReap(
balance: Cow<'a, LazyBalanceOf<T, I>>,
variant: Cow<'a, LazyVariantOf<T, I>>,
id: Cow<'a, LazyIdOf<T, I>>,
asset: Cow<'a, LazyAssetOf<T, I>>,
subject: Cow<'a, DispatchPolicy>,
),
CanWithdraw(
balance: Cow<'a, LazyBalanceOf<T, I>>,
variant: Cow<'a, LazyVariantOf<T, I>>,
id: Cow<'a, LazyIdOf<T, I>>,
receipt: Cow<'a, LazyReceiptOf<T, I>>,
),
TotalValue(
balance: Cow<'a, LazyBalanceOf<T, I>>,
variant: Cow<'a, LazyVariantOf<T, I>>,
id: Cow<'a, LazyIdOf<T, I>>,
),
ReceiptActiveValue(
balance: Cow<'a, LazyBalanceOf<T, I>>,
variant: Cow<'a, LazyVariantOf<T, I>>,
id: Cow<'a, LazyIdOf<T, I>>,
receipt: Cow<'a, LazyReceiptOf<T, I>>,
),
HasDeposits(
balance: Cow<'a, LazyBalanceOf<T, I>>,
variant: Cow<'a, LazyVariantOf<T, I>>,
id: Cow<'a, LazyIdOf<T, I>>,
),
ReceiptDepositValue(
receipt: Cow<'a, LazyReceiptOf<T, I>>,
),
DepositLimits(
balance: Cow<'a, LazyBalanceOf<T, I>>,
variant: Cow<'a, LazyVariantOf<T, I>>,
id: Cow<'a, LazyIdOf<T, I>>,
subject: Cow<'a, DispatchPolicy>,
),
MintLimits(
balance: Cow<'a, LazyBalanceOf<T, I>>,
variant: Cow<'a, LazyVariantOf<T, I>>,
id: Cow<'a, LazyIdOf<T, I>>,
subject: Cow<'a, DispatchPolicy>,
),
ReapLimits(
balance: Cow<'a, LazyBalanceOf<T, I>>,
variant: Cow<'a, LazyVariantOf<T, I>>,
id: Cow<'a, LazyIdOf<T, I>>,
subject: Cow<'a, DispatchPolicy>,
),
}
macro_rules! lazy_output {
(
$(
$variant:ident ( $ty:ty )
),* $(,)?
) => {
pub enum LazyOutput<'a, T, I>
where
T: Config<I>,
I: 'static,
{
$(
$variant($ty),
)*
}
$(
impl<'a, T, I> FromTag<$ty, $variant>
for LazyOutput<'a, T, I>
where
T: Config<I>,
I: 'static,
{
fn from_tag(t: $ty) -> Self {
Self::$variant(t)
}
}
impl<'a, T, I> TryIntoTag<$ty, $variant>
for LazyOutput<'a, T, I>
where
T: Config<I>,
I: 'static,
{
type Error = ();
fn try_into_tag(self) -> Result<$ty, Self::Error> {
match self {
Self::$variant(i) => Ok(i),
_ => Err(()),
}
}
}
)*
};
}
lazy_output! {
Deposit(Result<(Cow<'a, AssetOf<T, I>>, Cow<'a, LazyReceiptOf<T, I>>), LazyErrorOf<T, I>>),
Mint(Result<Cow<'a, AssetOf<T, I>>, LazyErrorOf<T, I>>),
Reap(Result<Cow<'a, AssetOf<T, I>>, LazyErrorOf<T, I>>),
Withdraw(Result<Cow<'a, LazyAssetOf<T, I>>, LazyErrorOf<T, I>>),
Drain(Result<Cow<'a, AssetOf<T, I>>, LazyErrorOf<T, I>>),
CanDeposit(Result<(), LazyErrorOf<T, I>>),
CanMint(Result<(), LazyErrorOf<T, I>>),
CanReap(Result<(), LazyErrorOf<T, I>>),
CanWithdraw(Result<(), LazyErrorOf<T, I>>),
TotalValue(Result<Cow<'a, LazyAssetOf<T, I>>, LazyErrorOf<T, I>>),
ReceiptActiveValue(Result<Cow<'a, LazyAssetOf<T, I>>, LazyErrorOf<T, I>>),
HasDeposits(Result<(), LazyErrorOf<T, I>>),
ReceiptDepositValue(Result<Cow<'a, LazyAssetOf<T, I>>, LazyErrorOf<T, I>>),
DepositLimits(Result<Cow<'a, LimitsProduct<T, I>>, LazyErrorOf<T, I>>),
MintLimits(Result<Cow<'a, LimitsProduct<T, I>>, LazyErrorOf<T, I>>),
ReapLimits(Result<Cow<'a, LimitsProduct<T, I>>, LazyErrorOf<T, I>>),
}
impl<T, I> VirtualNMap<VirtualBalance<T, I>, SnapShotStorage> for Pallet<T, I>
where
T: Config<I>,
I: 'static,
{
type Key = (Digest<T>, T::Position, T::Time);
type Value = VirtualSnapShot<T, I>;
type KeyGen = (
NMapKey<Blake2_128Concat, Digest<T>>,
NMapKey<Blake2_128Concat, T::Position>,
NMapKey<Blake2_128Concat, T::Time>,
);
type Map = BalanceSnapShots<T, I>;
type Query = Option<VirtualSnapShot<T, I>>;
}
#[derive(Encode, Decode, DecodeWithMemTracking, TypeInfo, MaxEncodedLen)]
#[scale_info(skip_type_params(T, I))]
pub struct LimitsProduct<T, I>
where
T: Config<I>,
I: 'static,
{
asset: SumDynType<AssetOf<T, I>, ConstU32<3>>,
}
impl<T, I> Clone for LimitsProduct<T, I>
where
T: Config<I>,
I: 'static,
SumDynType<AssetOf<T, I>, ConstU32<3>>: Clone,
{
fn clone(&self) -> Self {
Self {
asset: self.asset.clone(),
}
}
}
impl<T, I> core::fmt::Debug for LimitsProduct<T, I>
where
T: Config<I>,
I: 'static,
SumDynType<AssetOf<T, I>, ConstU32<3>>: core::fmt::Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("LimitsProduct")
.field("asset", &self.asset)
.finish()
}
}
impl<T, I> Default for LimitsProduct<T, I>
where
T: Config<I>,
I: 'static,
SumDynType<AssetOf<T, I>, ConstU32<3>>: Default,
{
fn default() -> Self {
Self {
asset: Default::default(),
}
}
}
impl<T, I> core::cmp::PartialEq for LimitsProduct<T, I>
where
T: Config<I>,
I: 'static,
SumDynType<AssetOf<T, I>, ConstU32<3>>: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.asset == other.asset
}
}
impl<T, I> core::cmp::Eq for LimitsProduct<T, I>
where
T: Config<I>,
I: 'static,
SumDynType<AssetOf<T, I>, ConstU32<3>>: Eq,
{
}
impl<T: Config<I>, I: 'static> VirtualDynField<LimitsAsset> for LimitsProduct<T, I> {
type None = ();
type Some = AssetOf<T, I>;
type Many = Vec<AssetOf<T, I>>;
type Repr = SumDynType<AssetOf<T, I>, ConstU32<3>>;
fn access(&self) -> Self::Repr {
self.asset.clone()
}
fn mutate(&mut self, v: Self::Repr) {
self.asset = v
}
fn len(&self) -> usize {
match &self.asset {
SumDynType::None => 0,
SumDynType::Some(_) => 1,
SumDynType::Many(v) => v.len(),
}
}
fn min(&self) -> usize {
match &self.asset {
SumDynType::None => 0,
SumDynType::Some(_) => 1,
SumDynType::Many(_) => 0,
}
}
fn max(&self) -> usize {
match &self.asset {
SumDynType::None => 0,
SumDynType::Some(_) => 1,
SumDynType::Many(_) => 3,
}
}
}
impl<T: Config<I>, I: 'static> VirtualDynBound<LimitsAsset> for LimitsProduct<T, I> {
type Bound = ConstU32<3>;
}
impl<T: Config<I>, I: 'static> Extent<LimitsAsset> for LimitsProduct<T, I> {
type Scalar = AssetOf<T, I>;
fn minimum(&self) -> Option<Self::Scalar> {
self.index_get(0)
}
fn maximum(&self) -> Option<Self::Scalar> {
self.index_get(1)
}
fn optimal(&self) -> Option<Self::Scalar> {
self.index_get(3)
}
fn none() -> Self {
Default::default()
}
}
impl<T: Config<I>, I: 'static> Extent for LimitsProduct<T, I> {
type Scalar = AssetOf<T, I>;
fn minimum(&self) -> Option<Self::Scalar> {
self.index_get(0)
}
fn maximum(&self) -> Option<Self::Scalar> {
self.index_get(1)
}
fn optimal(&self) -> Option<Self::Scalar> {
self.index_get(3)
}
fn none() -> Self {
Default::default()
}
}
#[derive(
Clone, Eq, PartialEq, Encode, Decode, DecodeWithMemTracking, TypeInfo, MaxEncodedLen, Debug,
)]
pub struct DispatchPolicy {
pub precise: bool,
pub force: bool,
}
impl Directive for DispatchPolicy {
fn precision(&self) -> Precision {
if self.precise {
return Precision::Exact;
};
Precision::BestEffort
}
fn fortitude(&self) -> Fortitude {
if self.force {
return Fortitude::Force;
};
Fortitude::Polite
}
fn new(precision: Precision, fortitude: Fortitude) -> Self {
Self {
precise: matches!(precision, Precision::Exact),
force: matches!(fortitude, Fortitude::Force),
}
}
}
impl Default for DispatchPolicy {
fn default() -> Self {
Self {
precise: false,
force: false,
}
}
}