mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-07-13 04:35:49 +00:00
Repot frame_support::traits; introduce some new currency stuff (#8435)
* Reservable, Transferrable Fungible(s), plus adapters. * Repot into new dir * Imbalances for Fungibles * Repot and balanced fungible. * Clean up names and bridge-over Imbalanced. * Repot frame_support::trait. Finally. * Make build. * Docs * Good errors * Fix tests. Implement fungible::Inspect for Balances. * Implement additional traits for Balances. * Revert UI test "fixes" * Fix UI error * Fix UI test * Fixes * Update lock * Grumbles * Grumbles * Fixes Co-authored-by: Bastian Köcher <info@kchr.de>
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Copyright (C) 2019-2021 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.
|
||||
|
||||
//! Traits and associated datatypes for managing abstract stored values.
|
||||
|
||||
use codec::FullCodec;
|
||||
use sp_runtime::traits::StoredMapError;
|
||||
use crate::storage::StorageMap;
|
||||
use crate::traits::misc::HandleLifetime;
|
||||
|
||||
/// An abstraction of a value stored within storage, but possibly as part of a larger composite
|
||||
/// item.
|
||||
pub trait StoredMap<K, T: Default> {
|
||||
/// Get the item, or its default if it doesn't yet exist; we make no distinction between the
|
||||
/// two.
|
||||
fn get(k: &K) -> T;
|
||||
|
||||
/// Maybe mutate the item only if an `Ok` value is returned from `f`. Do nothing if an `Err` is
|
||||
/// returned. It is removed or reset to default value if it has been mutated to `None`
|
||||
fn try_mutate_exists<R, E: From<StoredMapError>>(
|
||||
k: &K,
|
||||
f: impl FnOnce(&mut Option<T>) -> Result<R, E>,
|
||||
) -> Result<R, E>;
|
||||
|
||||
// Everything past here has a default implementation.
|
||||
|
||||
/// Mutate the item.
|
||||
fn mutate<R>(k: &K, f: impl FnOnce(&mut T) -> R) -> Result<R, StoredMapError> {
|
||||
Self::mutate_exists(k, |maybe_account| match maybe_account {
|
||||
Some(ref mut account) => f(account),
|
||||
x @ None => {
|
||||
let mut account = Default::default();
|
||||
let r = f(&mut account);
|
||||
*x = Some(account);
|
||||
r
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Mutate the item, removing or resetting to default value if it has been mutated to `None`.
|
||||
///
|
||||
/// This is infallible as long as the value does not get destroyed.
|
||||
fn mutate_exists<R>(
|
||||
k: &K,
|
||||
f: impl FnOnce(&mut Option<T>) -> R,
|
||||
) -> Result<R, StoredMapError> {
|
||||
Self::try_mutate_exists(k, |x| -> Result<R, StoredMapError> { Ok(f(x)) })
|
||||
}
|
||||
|
||||
/// Set the item to something new.
|
||||
fn insert(k: &K, t: T) -> Result<(), StoredMapError> { Self::mutate(k, |i| *i = t) }
|
||||
|
||||
/// Remove the item or otherwise replace it with its default value; we don't care which.
|
||||
fn remove(k: &K) -> Result<(), StoredMapError> { Self::mutate_exists(k, |x| *x = None) }
|
||||
}
|
||||
|
||||
/// A shim for placing around a storage item in order to use it as a `StoredValue`. Ideally this
|
||||
/// wouldn't be needed as `StorageValue`s should blanket implement `StoredValue`s, however this
|
||||
/// would break the ability to have custom impls of `StoredValue`. The other workaround is to
|
||||
/// implement it directly in the macro.
|
||||
///
|
||||
/// This form has the advantage that two additional types are provides, `Created` and `Removed`,
|
||||
/// which are both generic events that can be tied to handlers to do something in the case of being
|
||||
/// about to create an account where one didn't previously exist (at all; not just where it used to
|
||||
/// be the default value), or where the account is being removed or reset back to the default value
|
||||
/// where previously it did exist (though may have been in a default state). This works well with
|
||||
/// system module's `CallOnCreatedAccount` and `CallKillAccount`.
|
||||
pub struct StorageMapShim<S, L, K, T>(sp_std::marker::PhantomData<(S, L, K, T)>);
|
||||
impl<
|
||||
S: StorageMap<K, T, Query=T>,
|
||||
L: HandleLifetime<K>,
|
||||
K: FullCodec,
|
||||
T: FullCodec + Default,
|
||||
> StoredMap<K, T> for StorageMapShim<S, L, K, T> {
|
||||
fn get(k: &K) -> T { S::get(k) }
|
||||
fn insert(k: &K, t: T) -> Result<(), StoredMapError> {
|
||||
if !S::contains_key(&k) {
|
||||
L::created(k)?;
|
||||
}
|
||||
S::insert(k, t);
|
||||
Ok(())
|
||||
}
|
||||
fn remove(k: &K) -> Result<(), StoredMapError> {
|
||||
if S::contains_key(&k) {
|
||||
L::killed(&k)?;
|
||||
S::remove(k);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
fn mutate<R>(k: &K, f: impl FnOnce(&mut T) -> R) -> Result<R, StoredMapError> {
|
||||
if !S::contains_key(&k) {
|
||||
L::created(k)?;
|
||||
}
|
||||
Ok(S::mutate(k, f))
|
||||
}
|
||||
fn mutate_exists<R>(k: &K, f: impl FnOnce(&mut Option<T>) -> R) -> Result<R, StoredMapError> {
|
||||
S::try_mutate_exists(k, |maybe_value| {
|
||||
let existed = maybe_value.is_some();
|
||||
let r = f(maybe_value);
|
||||
let exists = maybe_value.is_some();
|
||||
|
||||
if !existed && exists {
|
||||
L::created(k)?;
|
||||
} else if existed && !exists {
|
||||
L::killed(k)?;
|
||||
}
|
||||
Ok(r)
|
||||
})
|
||||
}
|
||||
fn try_mutate_exists<R, E: From<StoredMapError>>(
|
||||
k: &K,
|
||||
f: impl FnOnce(&mut Option<T>) -> Result<R, E>,
|
||||
) -> Result<R, E> {
|
||||
S::try_mutate_exists(k, |maybe_value| {
|
||||
let existed = maybe_value.is_some();
|
||||
let r = f(maybe_value)?;
|
||||
let exists = maybe_value.is_some();
|
||||
|
||||
if !existed && exists {
|
||||
L::created(k).map_err(E::from)?;
|
||||
} else if existed && !exists {
|
||||
L::killed(k).map_err(E::from)?;
|
||||
}
|
||||
Ok(r)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user