referrerpolicy=no-referrer-when-downgrade

frame_support/traits/tokens/
asset_ops.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Abstract asset operations traits.
19//!
20//! The following operations are defined:
21//! * [`Inspect`]
22//! * [`Update`]
23//! * [`Create`]
24//! * [`Destroy`]
25//! * [`Stash`]
26//! * [`Restore`]
27//!
28//! Also, all the operations above (except the `Create` operation) use
29//! the [`AssetDefinition`] to retrieve the `Id` type of the asset.
30//!
31//! An asset operation can be implemented multiple times
32//! using different strategies associated with this operation.
33//!
34//! A strategy defines the operation behavior,
35//! may supply additional parameters,
36//! and may define a return value type of the operation.
37//!
38//! ### Usage Example
39//!
40//! This example shows how to interact with pallet-uniques (assuming the pallet called Uniques in
41//! the chain’s Runtime) via the asset ops.
42//!
43//! If you are interested in the implementation example, you can look at the pallet-uniques
44//! implementation. You can check out the pallet-uniques tests if you want more examples of usage.
45//!
46//! ```rust,ignore
47//! type Collection = pallet_uniques::asset_ops::Collection<Uniques>;
48//! type Item = pallet_uniques::asset_ops::Item<Uniques>;
49//!
50//! // Collection creation
51//! //
52//! // Note the `Owner` and `Admin` are inspect strategies.
53//! //
54//! // **Any** inspect strategy can be used to produce a config value
55//! // using the `WithConfig` creation strategy.
56//! Collection::create(WithConfig::new(
57//!     (
58//!         Owner::with_config_value(collection_owner),
59//!         Admin::with_config_value(collection_admin)
60//!     ),
61//!     PredefinedId::from(collection_id),
62//! )).unwrap();
63//!
64//! // Get the collection owner
65//! let owner = Collection::inspect(&collection_id, Owner::default()).unwrap();
66//!
67//! // Get the collection admin
68//! let admin = Collection::inspect(&collection_id, Admin::default()).unwrap();
69//!
70//! // Get collection metadata
71//! let metadata = Collection::inspect(&collection_id, Bytes::default()).unwrap();
72//!
73//! // Get collection attribute
74//! use pallet_uniques::asset_strategies::Attribute;
75//! let attr_key = "example-key";
76//! let attr_value = Collection::inspect(
77//!    &collection_id,
78//!    Bytes(Attribute(attr_key.as_slice())),
79//! ).unwrap();
80//!
81//! // Item creation (note the usage of the same strategy -- WithConfig)
82//! Item::create(WithConfig::new(
83//!     Owner::with_config_value(item_owner),
84//!     PredefinedId::from(item_id),
85//! )).unwrap();
86//!
87//! // Get the item owner
88//! let item_owner = Item::inspect(&(collection_id, item_id), Owner::default()).unwrap();
89//!
90//! // Get item attribute
91//! let attr_key = "example-key";
92//! let attr_value = Item::inspect(
93//!     &(collection_id, item_id),
94//!     Bytes(Attribute(attr_key.as_slice())),
95//! ).unwrap();
96//!
97//! // Unconditionally update the item's owner (unchecked transfer)
98//! Item::update(&(collection_id, item_id), Owner::default(), &bob).unwrap();
99//!
100//! // CheckOrigin then transfer
101//! Item::update(
102//!     &(collection_id, item_id),
103//!     CheckOrigin(RuntimeOrigin::root(), Owner::default()),
104//!     &bob,
105//! ).unwrap();
106//!
107//! // From-To transfer
108//! Item::update(
109//!     &(collection_id, item_id),
110//!     ChangeOwnerFrom::check(alice),
111//!     &bob,
112//! ).unwrap();
113//!
114//! // Lock item (forbid changing its Owner)
115//! //
116//! // Note that Owner strategy is turned into the `CanUpdate<Owner>` strategy
117//! // via the `as_can_update` function.
118//! //
119//! // **Any** update strategy can be turned into the `CanUpdate` this way.
120//! Item::update(
121//!     &(collection_id, item_id),
122//!     Owner::default().as_can_update(),
123//!     false,
124//! );
125//! ```
126
127use core::marker::PhantomData;
128use sp_runtime::DispatchError;
129use sp_std::vec::Vec;
130
131pub mod common_ops;
132pub mod common_strategies;
133
134/// Trait for defining an asset.
135/// The definition must provide the `Id` type to identify the asset.
136pub trait AssetDefinition {
137	/// Type for identifying the asset.
138	type Id;
139}
140
141/// Get the `Id` type of the asset definition.
142pub type AssetIdOf<T> = <T as AssetDefinition>::Id;
143
144/// A strategy for use in the [`Inspect`] implementations.
145///
146/// The common inspect strategies are:
147/// * [`Bytes`](common_strategies::Bytes)
148/// * [`Owner`](common_strategies::Owner)
149/// * [`CanCreate`](common_strategies::CanCreate)
150/// * [`CanDestroy`](common_strategies::CanDestroy)
151/// * [`CanUpdate`](common_strategies::CanUpdate)
152pub trait InspectStrategy {
153	/// The value representing the asset's state related to this `InspectStrategy`.
154	type Value;
155}
156
157/// A trait representing the ability of a certain asset to **provide** its state
158/// information.
159///
160/// This trait can be implemented multiple times using different
161/// [`inspect strategies`](InspectStrategy).
162///
163/// An inspect strategy defines how the asset state is identified/retrieved
164/// and what [`Value`](InspectStrategy::Value) type is returned.
165pub trait Inspect<Strategy: InspectStrategy>: AssetDefinition {
166	/// Inspect state information of the asset
167	/// using the given `id` and the inspect `strategy`.
168	///
169	/// The ID type is retrieved from the [`AssetDefinition`].
170	fn inspect(id: &Self::Id, strategy: Strategy) -> Result<Strategy::Value, DispatchError>;
171}
172
173/// A strategy for use in the [`Update`] implementations.
174///
175/// The common update strategies are:
176/// * [`Bytes`](common_strategies::Bytes)
177/// * [`CanCreate`](common_strategies::CanCreate)
178/// * [`CanDestroy`](common_strategies::CanDestroy)
179/// * [`CanUpdate`](common_strategies::CanUpdate)
180pub trait UpdateStrategy {
181	/// The value to update the asset's state.
182	/// Usually, it should be related to the corresponding `InspectStrategy::Value`.
183	///
184	/// For instance:
185	/// * If the `Value` is `Vec<u8>`, the `UpdateValue` can be `Option<&'a [u8]>` (e.g., asset
186	///   attributes that can be modified or deleted).
187	/// * If the `Value` is `bool`, the `UpdateValue` can also be `bool`.
188	type UpdateValue<'a>;
189
190	/// This type represents a successful asset state update.
191	/// It will be in the [`Result`] type of the [`Update::update`] function.
192	type Success;
193}
194
195/// A trait representing the ability of a certain asset to **update** its state information.
196///
197/// This trait can be implemented multiple times using different
198/// [`update strategies`](UpdateStrategy).
199///
200/// An update strategy defines how the asset state is identified
201/// and what [`UpdateValue`](UpdateStrategy::UpdateValue) type is used.
202pub trait Update<Strategy: UpdateStrategy>: AssetDefinition {
203	/// Update the state information of the asset
204	/// using the given `id`, the update `strategy`, and the strategy's `update_value`.
205	///
206	/// The ID type is retrieved from the [`AssetDefinition`].
207	fn update(
208		id: &Self::Id,
209		strategy: Strategy,
210		update_value: Strategy::UpdateValue<'_>,
211	) -> Result<Strategy::Success, DispatchError>;
212}
213
214/// A strategy for use in the [`Create`] implementations.
215///
216/// The common "create" strategy is [`WithConfig`](common_strategies::WithConfig).
217pub trait CreateStrategy {
218	/// This type represents a successful asset creation.
219	/// It will be in the [`Result`] type of the [`Create::create`] function.
220	type Success;
221}
222
223/// An ID assignment approach to use in the "create" strategies.
224///
225/// The common ID assignments are:
226/// * [`AutoId`](common_strategies::AutoId)
227/// * [`PredefinedId`](common_strategies::PredefinedId)
228/// * [`DeriveAndReportId`](common_strategies::DeriveAndReportId)
229pub trait IdAssignment {
230	/// The reported ID type.
231	///
232	/// Examples:
233	/// * [`AutoId`](common_strategies::AutoId) returns the ID of the newly created asset
234	/// * [`PredefinedId`](common_strategies::PredefinedId) accepts the ID to be assigned to the
235	///   newly created asset
236	/// * [`DeriveAndReportId`](common_strategies::DeriveAndReportId) returns the ID derived from
237	///   the input parameters
238	type ReportedId;
239}
240
241/// A trait representing the ability of a certain asset to be created.
242///
243/// This trait can be implemented multiple times using different
244/// [`"create" strategies`](CreateStrategy).
245///
246/// A create strategy defines all aspects of asset creation including how an asset ID is assigned.
247pub trait Create<Strategy: CreateStrategy> {
248	/// Create a new asset using the provided `strategy`.
249	fn create(strategy: Strategy) -> Result<Strategy::Success, DispatchError>;
250}
251
252/// A strategy for use in the [`Destroy`] implementations.
253///
254/// The common destroy strategies are:
255/// * [`NoParams`](common_strategies::NoParams)
256/// * [`IfOwnedBy`](common_strategies::IfOwnedBy)
257/// * [`WithWitness`](common_strategies::WithWitness)
258pub trait DestroyStrategy {
259	/// This type represents a successful asset destruction.
260	/// It will be in the [`Result`] type of the [`Destroy::destroy`] function.
261	type Success;
262}
263
264/// A trait representing the ability of a certain asset to be destroyed.
265///
266/// This trait can be implemented multiple times using different
267/// [`destroy strategies`](DestroyStrategy).
268///
269/// A destroy strategy defines destroy parameters and the result value type.
270pub trait Destroy<Strategy: DestroyStrategy>: AssetDefinition {
271	/// Destroy the asset identified by the given `id` using the provided `strategy`.
272	///
273	/// The ID type is retrieved from the [`AssetDefinition`].
274	fn destroy(id: &Self::Id, strategy: Strategy) -> Result<Strategy::Success, DispatchError>;
275}
276
277/// A strategy for use in the [`Stash`] implementations.
278///
279/// The common stash strategies are:
280/// * [`NoParams`](common_strategies::NoParams)
281/// * [`IfOwnedBy`](common_strategies::IfOwnedBy)
282pub trait StashStrategy {
283	/// This type represents a successful asset stashing.
284	/// It will be in the [`Result`] type of the [`Stash::stash`] function.
285	type Success;
286}
287
288/// A trait representing the ability of a certain asset to be stashed.
289///
290/// This trait can be implemented multiple times using different
291/// [`stash strategies`](StashStrategy).
292///
293/// A stash strategy defines stash parameters.
294pub trait Stash<Strategy: StashStrategy>: AssetDefinition {
295	/// Stash the asset identified by the given `id` using the provided `strategy`.
296	///
297	/// The ID type is retrieved from the [`AssetDefinition`].
298	fn stash(id: &Self::Id, strategy: Strategy) -> Result<Strategy::Success, DispatchError>;
299}
300
301/// A strategy for use in the [`Restore`] implementations.
302/// The common restore strategies are:
303/// * [`NoParams`](common_strategies::NoParams)
304/// * [`WithConfig`](common_strategies::WithConfig)
305pub trait RestoreStrategy {
306	/// This type represents a successful asset restoration.
307	/// It will be in the [`Result`] type of the [`Restore::restore`] function.
308	type Success;
309}
310
311/// A trait representing the ability of a certain asset to be restored.
312///
313/// This trait can be implemented multiple times using different
314/// [`restore strategies`](RestoreStrategy).
315///
316/// A restore strategy defines restore parameters.
317pub trait Restore<Strategy: RestoreStrategy>: AssetDefinition {
318	/// Restore the asset identified by the given `id` using the provided `strategy`.
319	///
320	/// The ID type is retrieved from the [`AssetDefinition`].
321	fn restore(id: &Self::Id, strategy: Strategy) -> Result<Strategy::Success, DispatchError>;
322}