git.delta.rocks / unique-network / refs/commits / 9f5f42dac2e7

difftreelog

Merge pull request #440 from UniqueNetwork/doc/pallet_common

Yaroslav Bolyukin2022-07-21parents: #49a12f2 #6c6ed89.patch.diff
in: master
docs(pallet_common): Add general  documentation.

4 files changed

modifiedpallets/common/src/dispatch.rsdiffbeforeafterboth
1//! Module with interfaces for dispatching collections.
2
1use frame_support::{3use frame_support::{
2 dispatch::{4 dispatch::{
20 // submit_logs is measured as part of collection pallets22 // submit_logs is measured as part of collection pallets
21}23}
2224
23/// Helper function to implement substrate calls for common collection methods25/// Helper function to implement substrate calls for common collection methods.
26///
27/// * `collection` - The collection on which to call the method.
28/// * `call` - The function in which to call the corresponding method from [`CommonCollectionOperations`].
24pub fn dispatch_tx<29pub fn dispatch_tx<
25 T: Config,30 T: Config,
26 C: FnOnce(&dyn CommonCollectionOperations<T>) -> DispatchResultWithPostInfo,31 C: FnOnce(&dyn CommonCollectionOperations<T>) -> DispatchResultWithPostInfo,
64 result69 result
65}70}
6671
72/// Interface for working with different collections through the dispatcher.
67pub trait CollectionDispatch<T: Config> {73pub trait CollectionDispatch<T: Config> {
74 /// Create a collection. The collection will be created according to the value of [`data.mode`](CreateCollectionData::mode).
75 ///
76 /// * `sender` - The user who will become the owner of the collection.
77 /// * `data` - Description of the created collection.
68 fn create(78 fn create(
69 sender: T::CrossAccountId,79 sender: T::CrossAccountId,
70 data: CreateCollectionData<T::AccountId>,80 data: CreateCollectionData<T::AccountId>,
71 ) -> DispatchResult;81 ) -> DispatchResult;
82
83 /// Delete the collection.
84 ///
85 /// * `sender` - The owner of the collection.
86 /// * `handle` - Collection handle.
72 fn destroy(sender: T::CrossAccountId, handle: CollectionHandle<T>) -> DispatchResult;87 fn destroy(sender: T::CrossAccountId, handle: CollectionHandle<T>) -> DispatchResult;
7388
89 /// Get a specialized collection from the handle.
90 ///
91 /// * `handle` - Collection handle.
74 fn dispatch(handle: CollectionHandle<T>) -> Self;92 fn dispatch(handle: CollectionHandle<T>) -> Self;
93
94 /// Get the collection handle for the corresponding implementation.
75 fn into_inner(self) -> CollectionHandle<T>;95 fn into_inner(self) -> CollectionHandle<T>;
7696
97 /// Get the implementation of [`CommonCollectionOperations`].
77 fn as_dyn(&self) -> &dyn CommonCollectionOperations<T>;98 fn as_dyn(&self) -> &dyn CommonCollectionOperations<T>;
78}99}
79100
modifiedpallets/common/src/erc.rsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
16
17//! This module contains the implementation of pallet methods for evm.
1618
17use evm_coder::{19use evm_coder::{
18 solidity_interface, solidity, ToLog,20 solidity_interface, solidity, ToLog,
2931
30use crate::{Pallet, CollectionHandle, Config, CollectionProperties};32use crate::{Pallet, CollectionHandle, Config, CollectionProperties};
3133
34/// Events for ethereum collection helper.
32#[derive(ToLog)]35#[derive(ToLog)]
33pub enum CollectionHelpersEvents {36pub enum CollectionHelpersEvents {
37 /// The collection has been created.
34 CollectionCreated {38 CollectionCreated {
39 /// Collection owner.
35 #[indexed]40 #[indexed]
36 owner: address,41 owner: address,
42
43 /// Collection ID.
37 #[indexed]44 #[indexed]
38 collection_id: address,45 collection_id: address,
39 },46 },
40}47}
4148
42/// Does not always represent a full collection, for RFT it is either49/// Does not always represent a full collection, for RFT it is either
43/// collection (Implementing ERC721), or specific collection token (Implementing ERC20)50/// collection (Implementing ERC721), or specific collection token (Implementing ERC20).
44pub trait CommonEvmHandler {51pub trait CommonEvmHandler {
45 const CODE: &'static [u8];52 const CODE: &'static [u8];
4653
54 /// Call precompiled handle.
47 fn call(self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult>;55 fn call(self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult>;
48}56}
4957
58/// @title A contract that allows you to work with collections.
50#[solidity_interface(name = "Collection")]59#[solidity_interface(name = "Collection")]
51impl<T: Config> CollectionHandle<T>60impl<T: Config> CollectionHandle<T>
52where61where
53 T::AccountId: From<[u8; 32]>,62 T::AccountId: From<[u8; 32]>,
54{63{
64 /// Set collection property.
65 ///
66 /// @param key Property key.
67 /// @param value Propery value.
55 fn set_collection_property(68 fn set_collection_property(
56 &mut self,69 &mut self,
57 caller: caller,70 caller: caller,
68 .map_err(dispatch_to_evm::<T>)81 .map_err(dispatch_to_evm::<T>)
69 }82 }
7083
84 /// Delete collection property.
85 ///
86 /// @param key Property key.
71 fn delete_collection_property(&mut self, caller: caller, key: string) -> Result<()> {87 fn delete_collection_property(&mut self, caller: caller, key: string) -> Result<()> {
72 let caller = T::CrossAccountId::from_eth(caller);88 let caller = T::CrossAccountId::from_eth(caller);
73 let key = <Vec<u8>>::from(key)89 let key = <Vec<u8>>::from(key)
77 <Pallet<T>>::delete_collection_property(self, &caller, key).map_err(dispatch_to_evm::<T>)93 <Pallet<T>>::delete_collection_property(self, &caller, key).map_err(dispatch_to_evm::<T>)
78 }94 }
7995
96 /// Get collection property.
97 ///
80 /// Throws error if key not found98 /// @dev Throws error if key not found.
99 ///
100 /// @param key Property key.
101 /// @return bytes The property corresponding to the key.
81 fn collection_property(&self, key: string) -> Result<bytes> {102 fn collection_property(&self, key: string) -> Result<bytes> {
82 let key = <Vec<u8>>::from(key)103 let key = <Vec<u8>>::from(key)
83 .try_into()104 .try_into()
89 Ok(prop.to_vec())110 Ok(prop.to_vec())
90 }111 }
91112
113 /// Set the sponsor of the collection.
114 ///
115 /// @dev In order for sponsorship to work, it must be confirmed on behalf of the sponsor.
116 ///
117 /// @param sponsor Address of the sponsor from whose account funds will be debited for operations with the contract.
92 fn set_collection_sponsor(&mut self, caller: caller, sponsor: address) -> Result<void> {118 fn set_collection_sponsor(&mut self, caller: caller, sponsor: address) -> Result<void> {
93 check_is_owner_or_admin(caller, self)?;119 check_is_owner_or_admin(caller, self)?;
94120
98 save(self)124 save(self)
99 }125 }
100126
127 /// Collection sponsorship confirmation.
128 ///
129 /// @dev After setting the sponsor for the collection, it must be confirmed with this function.
101 fn confirm_collection_sponsorship(&mut self, caller: caller) -> Result<void> {130 fn confirm_collection_sponsorship(&mut self, caller: caller) -> Result<void> {
102 let caller = T::CrossAccountId::from_eth(caller);131 let caller = T::CrossAccountId::from_eth(caller);
103 if !self132 if !self
109 save(self)138 save(self)
110 }139 }
111140
141 /// Set limits for the collection.
142 /// @dev Throws error if limit not found.
143 /// @param limit Name of the limit. Valid names:
144 /// "accountTokenOwnershipLimit",
145 /// "sponsoredDataSize",
146 /// "sponsoredDataRateLimit",
147 /// "tokenLimit",
148 /// "sponsorTransferTimeout",
149 /// "sponsorApproveTimeout"
150 /// @param value Value of the limit.
112 #[solidity(rename_selector = "setCollectionLimit")]151 #[solidity(rename_selector = "setCollectionLimit")]
113 fn set_int_limit(&mut self, caller: caller, limit: string, value: uint32) -> Result<void> {152 fn set_int_limit(&mut self, caller: caller, limit: string, value: uint32) -> Result<void> {
114 check_is_owner_or_admin(caller, self)?;153 check_is_owner_or_admin(caller, self)?;
145 save(self)184 save(self)
146 }185 }
147186
187 /// Set limits for the collection.
188 /// @dev Throws error if limit not found.
189 /// @param limit Name of the limit. Valid names:
190 /// "ownerCanTransfer",
191 /// "ownerCanDestroy",
192 /// "transfersEnabled"
193 /// @param value Value of the limit.
148 #[solidity(rename_selector = "setCollectionLimit")]194 #[solidity(rename_selector = "setCollectionLimit")]
149 fn set_bool_limit(&mut self, caller: caller, limit: string, value: bool) -> Result<void> {195 fn set_bool_limit(&mut self, caller: caller, limit: string, value: bool) -> Result<void> {
150 check_is_owner_or_admin(caller, self)?;196 check_is_owner_or_admin(caller, self)?;
172 save(self)218 save(self)
173 }219 }
174220
221 /// Get contract address.
175 fn contract_address(&self, _caller: caller) -> Result<address> {222 fn contract_address(&self, _caller: caller) -> Result<address> {
176 Ok(crate::eth::collection_id_to_address(self.id))223 Ok(crate::eth::collection_id_to_address(self.id))
177 }224 }
178225
226 /// Add collection admin by substrate address.
227 /// @param new_admin Substrate administrator address.
179 fn add_collection_admin_substrate(&self, caller: caller, new_admin: uint256) -> Result<void> {228 fn add_collection_admin_substrate(&self, caller: caller, new_admin: uint256) -> Result<void> {
180 let caller = T::CrossAccountId::from_eth(caller);229 let caller = T::CrossAccountId::from_eth(caller);
181 let mut new_admin_arr: [u8; 32] = Default::default();230 let mut new_admin_arr: [u8; 32] = Default::default();
186 Ok(())235 Ok(())
187 }236 }
188237
238 /// Remove collection admin by substrate address.
239 /// @param admin Substrate administrator address.
189 fn remove_collection_admin_substrate(240 fn remove_collection_admin_substrate(&self, caller: caller, admin: uint256) -> Result<void> {
190 &self,
191 caller: caller,
192 new_admin: uint256,
193 ) -> Result<void> {
194 let caller = T::CrossAccountId::from_eth(caller);241 let caller = T::CrossAccountId::from_eth(caller);
195 let mut new_admin_arr: [u8; 32] = Default::default();242 let mut admin_arr: [u8; 32] = Default::default();
196 new_admin.to_big_endian(&mut new_admin_arr);243 admin.to_big_endian(&mut admin_arr);
197 let account_id = T::AccountId::from(new_admin_arr);244 let account_id = T::AccountId::from(admin_arr);
198 let new_admin = T::CrossAccountId::from_sub(account_id);245 let admin = T::CrossAccountId::from_sub(account_id);
199 <Pallet<T>>::toggle_admin(self, &caller, &new_admin, false)246 <Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;
200 .map_err(dispatch_to_evm::<T>)?;
201 Ok(())247 Ok(())
202 }248 }
203249
250 /// Add collection admin.
251 /// @param new_admin Address of the added administrator.
204 fn add_collection_admin(&self, caller: caller, new_admin: address) -> Result<void> {252 fn add_collection_admin(&self, caller: caller, new_admin: address) -> Result<void> {
205 let caller = T::CrossAccountId::from_eth(caller);253 let caller = T::CrossAccountId::from_eth(caller);
206 let new_admin = T::CrossAccountId::from_eth(new_admin);254 let new_admin = T::CrossAccountId::from_eth(new_admin);
207 <Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;255 <Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;
208 Ok(())256 Ok(())
209 }257 }
210258
259 /// Remove collection admin.
260 ///
261 /// @param new_admin Address of the removed administrator.
211 fn remove_collection_admin(&self, caller: caller, admin: address) -> Result<void> {262 fn remove_collection_admin(&self, caller: caller, admin: address) -> Result<void> {
212 let caller = T::CrossAccountId::from_eth(caller);263 let caller = T::CrossAccountId::from_eth(caller);
213 let admin = T::CrossAccountId::from_eth(admin);264 let admin = T::CrossAccountId::from_eth(admin);
214 <Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;265 <Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;
215 Ok(())266 Ok(())
216 }267 }
217268
269 /// Toggle accessibility of collection nesting.
270 ///
271 /// @param enable If "true" degenerates to nesting: 'Owner' else to nesting: 'Disabled'
218 #[solidity(rename_selector = "setCollectionNesting")]272 #[solidity(rename_selector = "setCollectionNesting")]
219 fn set_nesting_bool(&mut self, caller: caller, enable: bool) -> Result<void> {273 fn set_nesting_bool(&mut self, caller: caller, enable: bool) -> Result<void> {
220 check_is_owner_or_admin(caller, self)?;274 check_is_owner_or_admin(caller, self)?;
235 save(self)289 save(self)
236 }290 }
237291
292 /// Toggle accessibility of collection nesting.
293 ///
294 /// @param enable If "true" degenerates to nesting: {OwnerRestricted: [1, 2, 3]} else to nesting: 'Disabled'
295 /// @param collections Addresses of collections that will be available for nesting.
238 #[solidity(rename_selector = "setCollectionNesting")]296 #[solidity(rename_selector = "setCollectionNesting")]
239 fn set_nesting(297 fn set_nesting(
240 &mut self,298 &mut self,
280 save(self)338 save(self)
281 }339 }
282340
341 /// Set the collection access method.
342 /// @param mode Access mode
343 /// 0 for Normal
344 /// 1 for AllowList
283 fn set_collection_access(&mut self, caller: caller, mode: uint8) -> Result<void> {345 fn set_collection_access(&mut self, caller: caller, mode: uint8) -> Result<void> {
284 check_is_owner_or_admin(caller, self)?;346 check_is_owner_or_admin(caller, self)?;
285 let permissions = CollectionPermissions {347 let permissions = CollectionPermissions {
300 save(self)362 save(self)
301 }363 }
302364
365 /// Add the user to the allowed list.
366 ///
367 /// @param user Address of a trusted user.
303 fn add_to_collection_allow_list(&self, caller: caller, user: address) -> Result<void> {368 fn add_to_collection_allow_list(&self, caller: caller, user: address) -> Result<void> {
304 let caller = T::CrossAccountId::from_eth(caller);369 let caller = T::CrossAccountId::from_eth(caller);
305 let user = T::CrossAccountId::from_eth(user);370 let user = T::CrossAccountId::from_eth(user);
306 <Pallet<T>>::toggle_allowlist(self, &caller, &user, true).map_err(dispatch_to_evm::<T>)?;371 <Pallet<T>>::toggle_allowlist(self, &caller, &user, true).map_err(dispatch_to_evm::<T>)?;
307 Ok(())372 Ok(())
308 }373 }
309374
375 /// Remove the user from the allowed list.
376 ///
377 /// @param user Address of a removed user.
310 fn remove_from_collection_allow_list(&self, caller: caller, user: address) -> Result<void> {378 fn remove_from_collection_allow_list(&self, caller: caller, user: address) -> Result<void> {
311 let caller = T::CrossAccountId::from_eth(caller);379 let caller = T::CrossAccountId::from_eth(caller);
312 let user = T::CrossAccountId::from_eth(user);380 let user = T::CrossAccountId::from_eth(user);
313 <Pallet<T>>::toggle_allowlist(self, &caller, &user, false).map_err(dispatch_to_evm::<T>)?;381 <Pallet<T>>::toggle_allowlist(self, &caller, &user, false).map_err(dispatch_to_evm::<T>)?;
314 Ok(())382 Ok(())
315 }383 }
316384
385 /// Switch permission for minting.
386 ///
387 /// @param mode Enable if "true".
317 fn set_collection_mint_mode(&mut self, caller: caller, mode: bool) -> Result<void> {388 fn set_collection_mint_mode(&mut self, caller: caller, mode: bool) -> Result<void> {
318 check_is_owner_or_admin(caller, self)?;389 check_is_owner_or_admin(caller, self)?;
319 let permissions = CollectionPermissions {390 let permissions = CollectionPermissions {
351 Ok(())422 Ok(())
352}423}
353424
425/// Get the "tokenURI" key as [PropertyKey](up_data_structs::PropertyKey).
354pub fn token_uri_key() -> up_data_structs::PropertyKey {426pub fn token_uri_key() -> up_data_structs::PropertyKey {
355 b"tokenURI"427 b"tokenURI"
356 .to_vec()428 .to_vec()
modifiedpallets/common/src/eth.rsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
16
17//! The module contains a number of functions for converting and checking ethereum identifiers.
1618
17use up_data_structs::CollectionId;19use up_data_structs::CollectionId;
18use sp_core::H160;20use sp_core::H160;
23 0x17, 0xc4, 0xe6, 0x45, 0x3c, 0xc4, 0x9a, 0xaa, 0xae, 0xac, 0xa8, 0x94, 0xe6, 0xd9, 0x68, 0x3e,25 0x17, 0xc4, 0xe6, 0x45, 0x3c, 0xc4, 0x9a, 0xaa, 0xae, 0xac, 0xa8, 0x94, 0xe6, 0xd9, 0x68, 0x3e,
24];26];
2527
28/// Maps the ethereum address of the collection in substrate.
26pub fn map_eth_to_id(eth: &H160) -> Option<CollectionId> {29pub fn map_eth_to_id(eth: &H160) -> Option<CollectionId> {
27 if eth[0..16] != ETH_COLLECTION_PREFIX {30 if eth[0..16] != ETH_COLLECTION_PREFIX {
28 return None;31 return None;
32 Some(CollectionId(u32::from_be_bytes(id_bytes)))35 Some(CollectionId(u32::from_be_bytes(id_bytes)))
33}36}
37
38/// Maps the substrate collection id in ethereum.
34pub fn collection_id_to_address(id: CollectionId) -> H160 {39pub fn collection_id_to_address(id: CollectionId) -> H160 {
35 let mut out = [0; 20];40 let mut out = [0; 20];
36 out[0..16].copy_from_slice(&ETH_COLLECTION_PREFIX);41 out[0..16].copy_from_slice(&ETH_COLLECTION_PREFIX);
37 out[16..20].copy_from_slice(&u32::to_be_bytes(id.0));42 out[16..20].copy_from_slice(&u32::to_be_bytes(id.0));
38 H160(out)43 H160(out)
39}44}
4045
46/// Check if the ethereum address is a collection.
41pub fn is_collection(address: &H160) -> bool {47pub fn is_collection(address: &H160) -> bool {
42 address[0..16] == ETH_COLLECTION_PREFIX48 address[0..16] == ETH_COLLECTION_PREFIX
43}49}
modifiedpallets/common/src/lib.rsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1616
17//! # Common pallet
18//!
19//! The Common pallet provides functionality for handling collections.
20//!
21//! ## Overview
22//!
23//! The Common pallet provides an interface for common collection operations for different collection types
24//! (see [CommonCollectionOperations]), as well as a generic dispatcher for these, see [dispatch] module.
25//! It also provides this functionality to EVM, see [erc] and [eth] modules.
26//!
27//! The Common pallet provides functions for:
28//!
29//! - Setting and approving collection sponsor.
30//! - Get\set\delete allow list.
31//! - Get\set\delete collection properties.
32//! - Get\set\delete collection property permissions.
33//! - Get\set\delete token property permissions.
34//! - Get\set\delete collection administrators.
35//! - Checking access permissions.
36//!
37//! ### Terminology
38//! **Collection sponsor** - For the collection, you can set a sponsor, at whose expense it will
39//! be possible to mint tokens.
40//!
41//! **Allow list** - List of users who have the right to minting tokens.
42//!
43//! **Collection properties** - Collection properties are simply key-value stores where various
44//! metadata can be placed.
45//!
46//! **Permissions on token properties** - For each property in the token can be set permission
47//! to change, see [`PropertyPermission`].
48//!
49//! **Collection administrator** - For a collection, you can set administrators who have the right
50//! to most actions on the collection.
51
52#![warn(missing_docs)]
17#![cfg_attr(not(feature = "std"), no_std)]53#![cfg_attr(not(feature = "std"), no_std)]
18
19extern crate alloc;54extern crate alloc;
2055
21use core::ops::{Deref, DerefMut};56use core::ops::{Deref, DerefMut};
90pub mod eth;125pub mod eth;
91pub mod weights;126pub mod weights;
92127
128/// Weight info.
93pub type SelfWeightOf<T> = <T as Config>::WeightInfo;129pub type SelfWeightOf<T> = <T as Config>::WeightInfo;
94130
131/// Collection handle contains information about collection data and id.
132/// Also provides functionality to count consumed gas.
133///
134/// CollectionHandle is used as a generic wrapper for collections of all types.
135/// It allows to perform common operations and queries on any collection type,
136/// both completely general for all, as well as their respective implementations of [`CommonCollectionOperations`].
95#[must_use = "Should call submit_logs or save, otherwise some data will be lost for evm side"]137#[must_use = "Should call submit_logs or save, otherwise some data will be lost for evm side"]
96pub struct CollectionHandle<T: Config> {138pub struct CollectionHandle<T: Config> {
139 /// Collection id
97 pub id: CollectionId,140 pub id: CollectionId,
98 collection: Collection<T::AccountId>,141 collection: Collection<T::AccountId>,
142 /// Substrate recorder for counting consumed gas
99 pub recorder: SubstrateRecorder<T>,143 pub recorder: SubstrateRecorder<T>,
100}144}
145
101impl<T: Config> WithRecorder<T> for CollectionHandle<T> {146impl<T: Config> WithRecorder<T> for CollectionHandle<T> {
102 fn recorder(&self) -> &SubstrateRecorder<T> {147 fn recorder(&self) -> &SubstrateRecorder<T> {
103 &self.recorder148 &self.recorder
106 self.recorder151 self.recorder
107 }152 }
108}153}
154
109impl<T: Config> CollectionHandle<T> {155impl<T: Config> CollectionHandle<T> {
156 /// Same as [CollectionHandle::new] but with an explicit gas limit.
110 pub fn new_with_gas_limit(id: CollectionId, gas_limit: u64) -> Option<Self> {157 pub fn new_with_gas_limit(id: CollectionId, gas_limit: u64) -> Option<Self> {
111 <CollectionById<T>>::get(id).map(|collection| Self {158 <CollectionById<T>>::get(id).map(|collection| Self {
112 id,159 id,
115 })162 })
116 }163 }
117164
165 /// Same as [CollectionHandle::new] but with an existed [`SubstrateRecorder`].
118 pub fn new_with_recorder(id: CollectionId, recorder: SubstrateRecorder<T>) -> Option<Self> {166 pub fn new_with_recorder(id: CollectionId, recorder: SubstrateRecorder<T>) -> Option<Self> {
119 <CollectionById<T>>::get(id).map(|collection| Self {167 <CollectionById<T>>::get(id).map(|collection| Self {
120 id,168 id,
123 })171 })
124 }172 }
125173
174 /// Retrives collection data from storage and creates collection handle with default parameters.
175 /// If collection not found return `None`
126 pub fn new(id: CollectionId) -> Option<Self> {176 pub fn new(id: CollectionId) -> Option<Self> {
127 Self::new_with_gas_limit(id, u64::MAX)177 Self::new_with_gas_limit(id, u64::MAX)
128 }178 }
129179
180 /// Same as [`CollectionHandle::new`] but if collection not found [CollectionNotFound](Error::CollectionNotFound) returned.
130 pub fn try_get(id: CollectionId) -> Result<Self, DispatchError> {181 pub fn try_get(id: CollectionId) -> Result<Self, DispatchError> {
131 Ok(Self::new(id).ok_or(<Error<T>>::CollectionNotFound)?)182 Ok(Self::new(id).ok_or(<Error<T>>::CollectionNotFound)?)
132 }183 }
133184
185 /// Consume gas for reading.
134 pub fn consume_store_reads(&self, reads: u64) -> evm_coder::execution::Result<()> {186 pub fn consume_store_reads(&self, reads: u64) -> evm_coder::execution::Result<()> {
135 self.recorder187 self.recorder
136 .consume_gas(T::GasWeightMapping::weight_to_gas(188 .consume_gas(T::GasWeightMapping::weight_to_gas(
140 ))192 ))
141 }193 }
142194
195 /// Consume gas for writing.
143 pub fn consume_store_writes(&self, writes: u64) -> evm_coder::execution::Result<()> {196 pub fn consume_store_writes(&self, writes: u64) -> evm_coder::execution::Result<()> {
144 self.recorder197 self.recorder
145 .consume_gas(T::GasWeightMapping::weight_to_gas(198 .consume_gas(T::GasWeightMapping::weight_to_gas(
148 .saturating_mul(writes),201 .saturating_mul(writes),
149 ))202 ))
150 }203 }
204
205 /// Save collection to storage.
151 pub fn save(self) -> DispatchResult {206 pub fn save(self) -> DispatchResult {
152 <CollectionById<T>>::insert(self.id, self.collection);207 <CollectionById<T>>::insert(self.id, self.collection);
153 Ok(())208 Ok(())
154 }209 }
155210
211 /// Set collection sponsor.
212 ///
213 /// Unique collections allows sponsoring for certain actions.
214 /// This method allows you to set the sponsor of the collection.
215 /// In order for sponsorship to become active, it must be confirmed through [`Self::confirm_sponsorship`].
156 pub fn set_sponsor(&mut self, sponsor: T::AccountId) -> DispatchResult {216 pub fn set_sponsor(&mut self, sponsor: T::AccountId) -> DispatchResult {
157 self.collection.sponsorship = SponsorshipState::Unconfirmed(sponsor);217 self.collection.sponsorship = SponsorshipState::Unconfirmed(sponsor);
158 Ok(())218 Ok(())
159 }219 }
160220
221 /// Confirm sponsorship
222 ///
223 /// In order for the sponsorship to become active, the user set as the sponsor must confirm their participation.
224 /// Before confirming sponsorship, the user must be specified as the sponsor of the collection via [`Self::set_sponsor`].
161 pub fn confirm_sponsorship(&mut self, sender: &T::AccountId) -> Result<bool, DispatchError> {225 pub fn confirm_sponsorship(&mut self, sender: &T::AccountId) -> Result<bool, DispatchError> {
162 if self.collection.sponsorship.pending_sponsor() != Some(sender) {226 if self.collection.sponsorship.pending_sponsor() != Some(sender) {
163 return Ok(false);227 return Ok(false);
168 }232 }
169233
170 /// Checks that the collection was created with, and must be operated upon through **Unique API**.234 /// Checks that the collection was created with, and must be operated upon through **Unique API**.
171 /// Now check only the `external_collection` flag and if it's **true**, then return `CollectionIsExternal` error.235 /// Now check only the `external_collection` flag and if it's **true**, then return [`Error::CollectionIsExternal`] error.
172 pub fn check_is_internal(&self) -> DispatchResult {236 pub fn check_is_internal(&self) -> DispatchResult {
173 if self.external_collection {237 if self.external_collection {
174 return Err(<Error<T>>::CollectionIsExternal)?;238 return Err(<Error<T>>::CollectionIsExternal)?;
178 }242 }
179243
180 /// Checks that the collection was created with, and must be operated upon through an **assimilated API**.244 /// Checks that the collection was created with, and must be operated upon through an **assimilated API**.
181 /// Now check only the `external_collection` flag and if it's **false**, then return `CollectionIsInternal` error.245 /// Now check only the `external_collection` flag and if it's **false**, then return [`Error::CollectionIsInternal`] error.
182 pub fn check_is_external(&self) -> DispatchResult {246 pub fn check_is_external(&self) -> DispatchResult {
183 if !self.external_collection {247 if !self.external_collection {
184 return Err(<Error<T>>::CollectionIsInternal)?;248 return Err(<Error<T>>::CollectionIsInternal)?;
203}267}
204268
205impl<T: Config> CollectionHandle<T> {269impl<T: Config> CollectionHandle<T> {
206 pub fn check_is_owner(&self, subject: &T::CrossAccountId) -> DispatchResult {270 /// Checks if the `user` is the owner of the collection.
271 pub fn check_is_owner(&self, user: &T::CrossAccountId) -> DispatchResult {
207 ensure!(*subject.as_sub() == self.owner, <Error<T>>::NoPermission);272 ensure!(*user.as_sub() == self.owner, <Error<T>>::NoPermission);
208 Ok(())273 Ok(())
209 }274 }
275
276 /// Returns **true** if the `user` is the owner or administrator of the collection.
210 pub fn is_owner_or_admin(&self, subject: &T::CrossAccountId) -> bool {277 pub fn is_owner_or_admin(&self, user: &T::CrossAccountId) -> bool {
211 *subject.as_sub() == self.owner || <IsAdmin<T>>::get((self.id, subject))278 *user.as_sub() == self.owner || <IsAdmin<T>>::get((self.id, user))
212 }279 }
280
281 /// Checks if the `user` is the owner or administrator of the collection.
213 pub fn check_is_owner_or_admin(&self, subject: &T::CrossAccountId) -> DispatchResult {282 pub fn check_is_owner_or_admin(&self, user: &T::CrossAccountId) -> DispatchResult {
214 ensure!(self.is_owner_or_admin(subject), <Error<T>>::NoPermission);283 ensure!(self.is_owner_or_admin(user), <Error<T>>::NoPermission);
215 Ok(())284 Ok(())
216 }285 }
286
287 /// Return **true** if `user` was not allowed to have tokens, and he can ignore such restrictions.
217 pub fn ignores_allowance(&self, user: &T::CrossAccountId) -> bool {288 pub fn ignores_allowance(&self, user: &T::CrossAccountId) -> bool {
218 self.limits.owner_can_transfer() && self.is_owner_or_admin(user)289 self.limits.owner_can_transfer() && self.is_owner_or_admin(user)
219 }290 }
291
292 /// Return **true** if `user` does not have enough token parts, and he can ignore such restrictions.
220 pub fn ignores_owned_amount(&self, user: &T::CrossAccountId) -> bool {293 pub fn ignores_owned_amount(&self, user: &T::CrossAccountId) -> bool {
221 self.limits.owner_can_transfer() && self.is_owner_or_admin(user)294 self.limits.owner_can_transfer() && self.is_owner_or_admin(user)
222 }295 }
296
297 /// Checks if the user is in the allow list. If not [Error::AddressNotInAllowlist] returns.
223 pub fn check_allowlist(&self, user: &T::CrossAccountId) -> DispatchResult {298 pub fn check_allowlist(&self, user: &T::CrossAccountId) -> DispatchResult {
224 ensure!(299 ensure!(
225 <Allowlist<T>>::get((self.id, user)),300 <Allowlist<T>>::get((self.id, user)),
249 + TypeInfo324 + TypeInfo
250 + account::Config325 + account::Config
251 {326 {
327 /// Weight information for functions of this pallet.
252 type WeightInfo: WeightInfo;328 type WeightInfo: WeightInfo;
329
330 /// Events compatible with [`frame_system::Config::Event`].
253 type Event: IsType<<Self as frame_system::Config>::Event> + From<Event<Self>>;331 type Event: IsType<<Self as frame_system::Config>::Event> + From<Event<Self>>;
254332
333 /// Handler of accounts and payment.
255 type Currency: Currency<Self::AccountId>;334 type Currency: Currency<Self::AccountId>;
256335
336 /// Set price to create a collection.
257 #[pallet::constant]337 #[pallet::constant]
258 type CollectionCreationPrice: Get<338 type CollectionCreationPrice: Get<
259 <<Self as Config>::Currency as Currency<Self::AccountId>>::Balance,339 <<Self as Config>::Currency as Currency<Self::AccountId>>::Balance,
260 >;340 >;
341
342 /// Dispatcher of operations on collections.
261 type CollectionDispatch: CollectionDispatch<Self>;343 type CollectionDispatch: CollectionDispatch<Self>;
262344
345 /// Account which holds the chain's treasury.
263 type TreasuryAccountId: Get<Self::AccountId>;346 type TreasuryAccountId: Get<Self::AccountId>;
347
348 /// Address under which the CollectionHelper contract would be available.
264 type ContractAddress: Get<H160>;349 type ContractAddress: Get<H160>;
265350
351 /// Mapper for token addresses to Ethereum addresses.
266 type EvmTokenAddressMapping: TokenAddressMapping<H160>;352 type EvmTokenAddressMapping: TokenAddressMapping<H160>;
353
354 /// Mapper for token addresses to [`CrossAccountId`].
267 type CrossTokenAddressMapping: TokenAddressMapping<Self::CrossAccountId>;355 type CrossTokenAddressMapping: TokenAddressMapping<Self::CrossAccountId>;
268 }356 }
269357
276364
277 #[pallet::extra_constants]365 #[pallet::extra_constants]
278 impl<T: Config> Pallet<T> {366 impl<T: Config> Pallet<T> {
367 /// Maximum admins per collection.
279 pub fn collection_admins_limit() -> u32 {368 pub fn collection_admins_limit() -> u32 {
280 COLLECTION_ADMINS_LIMIT369 COLLECTION_ADMINS_LIMIT
281 }370 }
285 #[pallet::generate_deposit(pub fn deposit_event)]374 #[pallet::generate_deposit(pub fn deposit_event)]
286 pub enum Event<T: Config> {375 pub enum Event<T: Config> {
287 /// New collection was created376 /// New collection was created
288 ///377 CollectionCreated(
289 /// # Arguments378 /// Globally unique identifier of newly created collection.
290 ///
291 /// * collection_id: Globally unique identifier of newly created collection.
292 ///379 CollectionId,
293 /// * mode: [CollectionMode] converted into u8.380 /// [`CollectionMode`] converted into _u8_.
294 ///381 u8,
295 /// * account_id: Collection owner.382 /// Collection owner.
296 CollectionCreated(CollectionId, u8, T::AccountId),383 T::AccountId,
384 ),
297385
298 /// New collection was destroyed386 /// New collection was destroyed
299 ///387 CollectionDestroyed(
300 /// # Arguments388 /// Globally unique identifier of collection.
301 ///
302 /// * collection_id: Globally unique identifier of collection.
303 CollectionDestroyed(CollectionId),389 CollectionId,
390 ),
304391
305 /// New item was created.392 /// New item was created.
306 ///393 ItemCreated(
307 /// # Arguments394 /// Id of the collection where item was created.
308 ///
309 /// * collection_id: Id of the collection where item was created.
310 ///395 CollectionId,
311 /// * item_id: Id of an item. Unique within the collection.396 /// Id of an item. Unique within the collection.
312 ///397 TokenId,
313 /// * recipient: Owner of newly created item398 /// Owner of newly created item
314 ///399 T::CrossAccountId,
315 /// * amount: Always 1 for NFT400 /// Always 1 for NFT
316 ItemCreated(CollectionId, TokenId, T::CrossAccountId, u128),401 u128,
402 ),
317403
318 /// Collection item was burned.404 /// Collection item was burned.
319 ///405 ItemDestroyed(
320 /// # Arguments406 /// Id of the collection where item was destroyed.
321 ///
322 /// * collection_id.
323 ///407 CollectionId,
324 /// * item_id: Identifier of burned NFT.408 /// Identifier of burned NFT.
325 ///409 TokenId,
326 /// * owner: which user has destroyed its tokens410 /// Which user has destroyed its tokens.
327 ///411 T::CrossAccountId,
328 /// * amount: Always 1 for NFT412 /// Amount of token pieces destroed. Always 1 for NFT.
329 ItemDestroyed(CollectionId, TokenId, T::CrossAccountId, u128),413 u128,
414 ),
330415
331 /// Item was transferred416 /// Item was transferred
332 ///
333 /// * collection_id: Id of collection to which item is belong
334 ///
335 /// * item_id: Id of an item
336 ///
337 /// * sender: Original owner of item
338 ///
339 /// * recipient: New owner of item
340 ///
341 /// * amount: Always 1 for NFT
342 Transfer(417 Transfer(
418 /// Id of collection to which item is belong.
343 CollectionId,419 CollectionId,
420 /// Id of an item.
344 TokenId,421 TokenId,
422 /// Original owner of item.
345 T::CrossAccountId,423 T::CrossAccountId,
424 /// New owner of item.
346 T::CrossAccountId,425 T::CrossAccountId,
426 /// Amount of token pieces transfered. Always 1 for NFT.
347 u128,427 u128,
348 ),428 ),
349429
350 /// * collection_id430 /// Amount pieces of token owned by `sender` was approved for `spender`.
351 ///
352 /// * item_id
353 ///
354 /// * sender
355 ///
356 /// * spender
357 ///
358 /// * amount
359 Approved(431 Approved(
432 /// Id of collection to which item is belong.
360 CollectionId,433 CollectionId,
434 /// Id of an item.
361 TokenId,435 TokenId,
436 /// Original owner of item.
362 T::CrossAccountId,437 T::CrossAccountId,
438 /// Id for which the approval was granted.
363 T::CrossAccountId,439 T::CrossAccountId,
440 /// Amount of token pieces transfered. Always 1 for NFT.
364 u128,441 u128,
365 ),442 ),
366443
367 CollectionPropertySet(CollectionId, PropertyKey),444 /// The colletion property has been set.
445 CollectionPropertySet(
446 /// Id of collection to which property has been set.
447 CollectionId,
448 /// The property that was set.
449 PropertyKey,
450 ),
368451
369 CollectionPropertyDeleted(CollectionId, PropertyKey),452 /// The property has been deleted.
453 CollectionPropertyDeleted(
454 /// Id of collection to which property has been deleted.
455 CollectionId,
456 /// The property that was deleted.
457 PropertyKey,
458 ),
370459
371 TokenPropertySet(CollectionId, TokenId, PropertyKey),460 /// The token property has been set.
461 TokenPropertySet(
462 /// Identifier of the collection whose token has the property set.
463 CollectionId,
464 /// The token for which the property was set.
465 TokenId,
466 /// The property that was set.
467 PropertyKey,
468 ),
372469
373 TokenPropertyDeleted(CollectionId, TokenId, PropertyKey),470 /// The token property has been deleted.
471 TokenPropertyDeleted(
472 /// Identifier of the collection whose token has the property deleted.
473 CollectionId,
474 /// The token for which the property was deleted.
475 TokenId,
476 /// The property that was deleted.
477 PropertyKey,
478 ),
374479
375 PropertyPermissionSet(CollectionId, PropertyKey),480 /// The colletion property permission has been set.
481 PropertyPermissionSet(
482 /// Id of collection to which property permission has been set.
483 CollectionId,
484 /// The property permission that was set.
485 PropertyKey,
486 ),
376 }487 }
377488
378 #[pallet::error]489 #[pallet::error]
460 CollectionIsInternal,571 CollectionIsInternal,
461 }572 }
462573
574 /// Storage of the count of created collections.
463 #[pallet::storage]575 #[pallet::storage]
464 pub type CreatedCollectionCount<T> = StorageValue<Value = CollectionId, QueryKind = ValueQuery>;576 pub type CreatedCollectionCount<T> = StorageValue<Value = CollectionId, QueryKind = ValueQuery>;
577
578 /// Storage of the count of deleted collections.
465 #[pallet::storage]579 #[pallet::storage]
466 pub type DestroyedCollectionCount<T> =580 pub type DestroyedCollectionCount<T> =
467 StorageValue<Value = CollectionId, QueryKind = ValueQuery>;581 StorageValue<Value = CollectionId, QueryKind = ValueQuery>;
468582
469 /// Collection info583 /// Storage of collection info.
470 #[pallet::storage]584 #[pallet::storage]
471 pub type CollectionById<T> = StorageMap<585 pub type CollectionById<T> = StorageMap<
472 Hasher = Blake2_128Concat,586 Hasher = Blake2_128Concat,
475 QueryKind = OptionQuery,589 QueryKind = OptionQuery,
476 >;590 >;
477591
478 /// Collection properties592 /// Storage of collection properties.
479 #[pallet::storage]593 #[pallet::storage]
480 #[pallet::getter(fn collection_properties)]594 #[pallet::getter(fn collection_properties)]
481 pub type CollectionProperties<T> = StorageMap<595 pub type CollectionProperties<T> = StorageMap<
486 OnEmpty = up_data_structs::CollectionProperties,600 OnEmpty = up_data_structs::CollectionProperties,
487 >;601 >;
488602
603 /// Storage of collection properties permissions.
489 #[pallet::storage]604 #[pallet::storage]
490 #[pallet::getter(fn property_permissions)]605 #[pallet::getter(fn property_permissions)]
491 pub type CollectionPropertyPermissions<T> = StorageMap<606 pub type CollectionPropertyPermissions<T> = StorageMap<
495 QueryKind = ValueQuery,610 QueryKind = ValueQuery,
496 >;611 >;
497612
613 /// Storage of collection admins count.
498 #[pallet::storage]614 #[pallet::storage]
499 pub type AdminAmount<T> = StorageMap<615 pub type AdminAmount<T> = StorageMap<
500 Hasher = Blake2_128Concat,616 Hasher = Blake2_128Concat,
525 QueryKind = ValueQuery,641 QueryKind = ValueQuery,
526 >;642 >;
527643
528 /// Not used by code, exists only to provide some types to metadata644 /// Not used by code, exists only to provide some types to metadata.
529 #[pallet::storage]645 #[pallet::storage]
530 pub type DummyStorageValue<T: Config> = StorageValue<646 pub type DummyStorageValue<T: Config> = StorageValue<
531 Value = (647 Value = (
619}735}
620736
621impl<T: Config> Pallet<T> {737impl<T: Config> Pallet<T> {
622 /// Ethereum receiver 0x0000000000000000000000000000000000000000 is reserved, and shouldn't own tokens738 /// Enshure that receiver address is correct.
739 ///
740 /// Ethereum receiver 0x0000000000000000000000000000000000000000 is reserved, and shouldn't own tokens.
623 pub fn ensure_correct_receiver(receiver: &T::CrossAccountId) -> DispatchResult {741 pub fn ensure_correct_receiver(receiver: &T::CrossAccountId) -> DispatchResult {
624 ensure!(742 ensure!(
625 &T::CrossAccountId::from_eth(H160([0; 20])) != receiver,743 &T::CrossAccountId::from_eth(H160([0; 20])) != receiver,
626 <Error<T>>::AddressIsZero744 <Error<T>>::AddressIsZero
627 );745 );
628 Ok(())746 Ok(())
629 }747 }
748
749 /// Get a vector of collection admins.
630 pub fn adminlist(collection: CollectionId) -> Vec<T::CrossAccountId> {750 pub fn adminlist(collection: CollectionId) -> Vec<T::CrossAccountId> {
631 <IsAdmin<T>>::iter_prefix((collection,))751 <IsAdmin<T>>::iter_prefix((collection,))
632 .map(|(a, _)| a)752 .map(|(a, _)| a)
633 .collect()753 .collect()
634 }754 }
755
756 /// Get a vector of users allowed to mint tokens.
635 pub fn allowlist(collection: CollectionId) -> Vec<T::CrossAccountId> {757 pub fn allowlist(collection: CollectionId) -> Vec<T::CrossAccountId> {
636 <Allowlist<T>>::iter_prefix((collection,))758 <Allowlist<T>>::iter_prefix((collection,))
637 .map(|(a, _)| a)759 .map(|(a, _)| a)
638 .collect()760 .collect()
639 }761 }
762
763 /// Is `user` allowed to mint token in `collection`.
640 pub fn allowed(collection: CollectionId, user: T::CrossAccountId) -> bool {764 pub fn allowed(collection: CollectionId, user: T::CrossAccountId) -> bool {
641 <Allowlist<T>>::get((collection, user))765 <Allowlist<T>>::get((collection, user))
642 }766 }
767
768 /// Get statistics of collections.
643 pub fn collection_stats() -> CollectionStats {769 pub fn collection_stats() -> CollectionStats {
644 let created = <CreatedCollectionCount<T>>::get();770 let created = <CreatedCollectionCount<T>>::get();
645 let destroyed = <DestroyedCollectionCount<T>>::get();771 let destroyed = <DestroyedCollectionCount<T>>::get();
650 }776 }
651 }777 }
652778
779 /// Get the effective limits for the collection.
653 pub fn effective_collection_limits(collection: CollectionId) -> Option<CollectionLimits> {780 pub fn effective_collection_limits(collection: CollectionId) -> Option<CollectionLimits> {
654 let collection = <CollectionById<T>>::get(collection);781 let collection = <CollectionById<T>>::get(collection);
655 if collection.is_none() {782 if collection.is_none() {
683 Some(effective_limits)810 Some(effective_limits)
684 }811 }
685812
813 /// Returns information about the `collection` adapted for rpc.
686 pub fn rpc_collection(collection: CollectionId) -> Option<RpcCollection<T::AccountId>> {814 pub fn rpc_collection(collection: CollectionId) -> Option<RpcCollection<T::AccountId>> {
687 let Collection {815 let Collection {
688 name,816 name,
758}886}
759887
760impl<T: Config> Pallet<T> {888impl<T: Config> Pallet<T> {
889 /// Create new collection.
890 ///
891 /// * `owner` - The owner of the collection.
892 /// * `data` - Description of the created collection.
893 /// * `is_external` - Marks that collection managet by not "Unique network".
761 pub fn init_collection(894 pub fn init_collection(
762 owner: T::CrossAccountId,895 owner: T::CrossAccountId,
763 data: CreateCollectionData<T::AccountId>,896 data: CreateCollectionData<T::AccountId>,
858 Ok(id)991 Ok(id)
859 }992 }
860993
994 /// Destroy collection.
995 ///
996 /// * `collection` - Collection handler.
997 /// * `sender` - The owner or administrator of the collection.
861 pub fn destroy_collection(998 pub fn destroy_collection(
862 collection: CollectionHandle<T>,999 collection: CollectionHandle<T>,
863 sender: &T::CrossAccountId,1000 sender: &T::CrossAccountId,
886 Ok(())1023 Ok(())
887 }1024 }
8881025
1026 /// Set collection property.
1027 ///
1028 /// * `collection` - Collection handler.
1029 /// * `sender` - The owner or administrator of the collection.
1030 /// * `property` - The property to set.
889 pub fn set_collection_property(1031 pub fn set_collection_property(
890 collection: &CollectionHandle<T>,1032 collection: &CollectionHandle<T>,
891 sender: &T::CrossAccountId,1033 sender: &T::CrossAccountId,
904 Ok(())1046 Ok(())
905 }1047 }
9061048
1049 /// Set scouped collection property.
1050 ///
1051 /// * `collection_id` - ID of the collection for which the property is being set.
1052 /// * `scope` - Property scope.
1053 /// * `property` - The property to set.
907 pub fn set_scoped_collection_property(1054 pub fn set_scoped_collection_property(
908 collection_id: CollectionId,1055 collection_id: CollectionId,
909 scope: PropertyScope,1056 scope: PropertyScope,
917 Ok(())1064 Ok(())
918 }1065 }
9191066
1067 /// Set scouped collection properties.
1068 ///
1069 /// * `collection_id` - ID of the collection for which the properties is being set.
1070 /// * `scope` - Property scope.
1071 /// * `properties` - The properties to set.
920 pub fn set_scoped_collection_properties(1072 pub fn set_scoped_collection_properties(
921 collection_id: CollectionId,1073 collection_id: CollectionId,
922 scope: PropertyScope,1074 scope: PropertyScope,
930 Ok(())1082 Ok(())
931 }1083 }
9321084
1085 /// Set collection properties.
1086 ///
1087 /// * `collection` - Collection handler.
1088 /// * `sender` - The owner or administrator of the collection.
1089 /// * `properties` - The properties to set.
933 #[transactional]1090 #[transactional]
934 pub fn set_collection_properties(1091 pub fn set_collection_properties(
935 collection: &CollectionHandle<T>,1092 collection: &CollectionHandle<T>,
943 Ok(())1100 Ok(())
944 }1101 }
9451102
1103 /// Delete collection property.
1104 ///
1105 /// * `collection` - Collection handler.
1106 /// * `sender` - The owner or administrator of the collection.
1107 /// * `property` - The property to delete.
946 pub fn delete_collection_property(1108 pub fn delete_collection_property(
947 collection: &CollectionHandle<T>,1109 collection: &CollectionHandle<T>,
948 sender: &T::CrossAccountId,1110 sender: &T::CrossAccountId,
963 Ok(())1125 Ok(())
964 }1126 }
9651127
1128 /// Delete collection properties.
1129 ///
1130 /// * `collection` - Collection handler.
1131 /// * `sender` - The owner or administrator of the collection.
1132 /// * `properties` - The properties to delete.
966 #[transactional]1133 #[transactional]
967 pub fn delete_collection_properties(1134 pub fn delete_collection_properties(
968 collection: &CollectionHandle<T>,1135 collection: &CollectionHandle<T>,
976 Ok(())1143 Ok(())
977 }1144 }
9781145
979 // For migrations1146 /// Set collection propetry permission without any checks.
1147 ///
1148 /// Used for migrations.
1149 ///
1150 /// * `collection` - Collection handler.
1151 /// * `property_permissions` - Property permissions.
980 pub fn set_property_permission_unchecked(1152 pub fn set_property_permission_unchecked(
981 collection: CollectionId,1153 collection: CollectionId,
982 property_permission: PropertyKeyPermission,1154 property_permission: PropertyKeyPermission,
988 Ok(())1160 Ok(())
989 }1161 }
9901162
1163 /// Set collection property permission.
1164 ///
1165 /// * `collection` - Collection handler.
1166 /// * `sender` - The owner or administrator of the collection.
1167 /// * `property_permission` - Property permission.
991 pub fn set_property_permission(1168 pub fn set_property_permission(
992 collection: &CollectionHandle<T>,1169 collection: &CollectionHandle<T>,
993 sender: &T::CrossAccountId,1170 sender: &T::CrossAccountId,
1018 Ok(())1195 Ok(())
1019 }1196 }
10201197
1198 /// Set token property permission.
1199 ///
1200 /// * `collection` - Collection handler.
1201 /// * `sender` - The owner or administrator of the collection.
1202 /// * `property_permissions` - Property permissions.
1021 #[transactional]1203 #[transactional]
1022 pub fn set_token_property_permissions(1204 pub fn set_token_property_permissions(
1023 collection: &CollectionHandle<T>,1205 collection: &CollectionHandle<T>,
1031 Ok(())1213 Ok(())
1032 }1214 }
10331215
1216 /// Get collection property.
1034 pub fn get_collection_property(1217 pub fn get_collection_property(
1035 collection_id: CollectionId,1218 collection_id: CollectionId,
1036 key: &PropertyKey,1219 key: &PropertyKey,
1037 ) -> Option<PropertyValue> {1220 ) -> Option<PropertyValue> {
1038 Self::collection_properties(collection_id).get(key).cloned()1221 Self::collection_properties(collection_id).get(key).cloned()
1039 }1222 }
10401223
1224 /// Convert byte vector to property key vector.
1041 pub fn bytes_keys_to_property_keys(1225 pub fn bytes_keys_to_property_keys(
1042 keys: Vec<Vec<u8>>,1226 keys: Vec<Vec<u8>>,
1043 ) -> Result<Vec<PropertyKey>, DispatchError> {1227 ) -> Result<Vec<PropertyKey>, DispatchError> {
1049 .collect::<Result<Vec<PropertyKey>, DispatchError>>()1233 .collect::<Result<Vec<PropertyKey>, DispatchError>>()
1050 }1234 }
10511235
1236 /// Get properties according to given keys.
1052 pub fn filter_collection_properties(1237 pub fn filter_collection_properties(
1053 collection_id: CollectionId,1238 collection_id: CollectionId,
1054 keys: Option<Vec<PropertyKey>>,1239 keys: Option<Vec<PropertyKey>>,
1076 Ok(properties)1261 Ok(properties)
1077 }1262 }
10781263
1264 /// Get property permissions according to given keys.
1079 pub fn filter_property_permissions(1265 pub fn filter_property_permissions(
1080 collection_id: CollectionId,1266 collection_id: CollectionId,
1081 keys: Option<Vec<PropertyKey>>,1267 keys: Option<Vec<PropertyKey>>,
1105 Ok(key_permissions)1291 Ok(key_permissions)
1106 }1292 }
11071293
1294 /// Toggle `user` participation in the `collection`'s allow list.
1108 pub fn toggle_allowlist(1295 pub fn toggle_allowlist(
1109 collection: &CollectionHandle<T>,1296 collection: &CollectionHandle<T>,
1110 sender: &T::CrossAccountId,1297 sender: &T::CrossAccountId,
1124 Ok(())1311 Ok(())
1125 }1312 }
11261313
1314 /// Toggle `user` participation in the `collection`'s admin list.
1127 pub fn toggle_admin(1315 pub fn toggle_admin(
1128 collection: &CollectionHandle<T>,1316 collection: &CollectionHandle<T>,
1129 sender: &T::CrossAccountId,1317 sender: &T::CrossAccountId,
1159 Ok(())1347 Ok(())
1160 }1348 }
11611349
1350 /// Merge set fields from `new_limit` to `old_limit`.
1162 pub fn clamp_limits(1351 pub fn clamp_limits(
1163 mode: CollectionMode,1352 mode: CollectionMode,
1164 old_limit: &CollectionLimits,1353 old_limit: &CollectionLimits,
1204 Ok(new_limit)1393 Ok(new_limit)
1205 }1394 }
12061395
1396 /// Merge set fields from `new_permission` to `old_permission`.
1207 pub fn clamp_permissions(1397 pub fn clamp_permissions(
1208 _mode: CollectionMode,1398 _mode: CollectionMode,
1209 old_limit: &CollectionPermissions,1399 old_permission: &CollectionPermissions,
1210 mut new_limit: CollectionPermissions,1400 mut new_permission: CollectionPermissions,
1211 ) -> Result<CollectionPermissions, DispatchError> {1401 ) -> Result<CollectionPermissions, DispatchError> {
1212 limit_default_clone!(old_limit, new_limit,1402 limit_default_clone!(old_permission, new_permission,
1213 access => {},1403 access => {},
1214 mint_mode => {},1404 mint_mode => {},
1215 nesting => { /* todo check for permissive, if only it gets out of benchmarks */ },1405 nesting => { /* todo check for permissive, if only it gets out of benchmarks */ },
1216 );1406 );
1217 Ok(new_limit)1407 Ok(new_permission)
1218 }1408 }
1219}1409}
12201410
1411/// Indicates unsupported methods by returning [Error::UnsupportedOperation].
1221#[macro_export]1412#[macro_export]
1222macro_rules! unsupported {1413macro_rules! unsupported {
1223 () => {1414 () => {
1224 Err(<Error<T>>::UnsupportedOperation.into())1415 Err(<Error<T>>::UnsupportedOperation.into())
1225 };1416 };
1226}1417}
12271418
1228/// Worst cases1419/// Return weights for various worst-case operations.
1229pub trait CommonWeightInfo<CrossAccountId> {1420pub trait CommonWeightInfo<CrossAccountId> {
1421 /// Weight of item creation.
1230 fn create_item() -> Weight;1422 fn create_item() -> Weight;
1423
1424 /// Weight of items creation.
1231 fn create_multiple_items(amount: &[CreateItemData]) -> Weight;1425 fn create_multiple_items(amount: &[CreateItemData]) -> Weight;
1426
1427 /// Weight of items creation.
1232 fn create_multiple_items_ex(cost: &CreateItemExData<CrossAccountId>) -> Weight;1428 fn create_multiple_items_ex(cost: &CreateItemExData<CrossAccountId>) -> Weight;
1429
1430 /// The weight of the burning item.
1233 fn burn_item() -> Weight;1431 fn burn_item() -> Weight;
1432
1433 /// Property setting weight.
1434 ///
1435 /// * `amount`- The number of properties to set.
1234 fn set_collection_properties(amount: u32) -> Weight;1436 fn set_collection_properties(amount: u32) -> Weight;
1437
1438 /// Collection property deletion weight.
1439 ///
1440 /// * `amount`- The number of properties to set.
1235 fn delete_collection_properties(amount: u32) -> Weight;1441 fn delete_collection_properties(amount: u32) -> Weight;
1442
1443 /// Token property setting weight.
1444 ///
1445 /// * `amount`- The number of properties to set.
1236 fn set_token_properties(amount: u32) -> Weight;1446 fn set_token_properties(amount: u32) -> Weight;
1447
1448 /// Token property deletion weight.
1449 ///
1450 /// * `amount`- The number of properties to delete.
1237 fn delete_token_properties(amount: u32) -> Weight;1451 fn delete_token_properties(amount: u32) -> Weight;
1452
1453 /// Token property permissions set weight.
1454 ///
1455 /// * `amount`- The number of property permissions to set.
1238 fn set_token_property_permissions(amount: u32) -> Weight;1456 fn set_token_property_permissions(amount: u32) -> Weight;
1457
1458 /// Transfer price of the token or its parts.
1239 fn transfer() -> Weight;1459 fn transfer() -> Weight;
1460
1461 /// The price of setting the permission of the operation from another user.
1240 fn approve() -> Weight;1462 fn approve() -> Weight;
1463
1464 /// Transfer price from another user.
1241 fn transfer_from() -> Weight;1465 fn transfer_from() -> Weight;
1466
1467 /// The price of burning a token from another user.
1242 fn burn_from() -> Weight;1468 fn burn_from() -> Weight;
12431469
1244 /// Differs from burn_item in case of Fungible and Refungible, as it should burn1470 /// Differs from burn_item in case of Fungible and Refungible, as it should burn
1245 /// whole users's balance1471 /// whole users's balance.
1246 ///1472 ///
1247 /// This method shouldn't be used directly, as it doesn't count breadth price, use `burn_recursively` instead1473 /// This method shouldn't be used directly, as it doesn't count breadth price, use [burn_recursively](CommonWeightInfo::burn_recursively) instead
1248 fn burn_recursively_self_raw() -> Weight;1474 fn burn_recursively_self_raw() -> Weight;
1475
1249 /// Cost of iterating over `amount` children while burning, without counting child burning itself1476 /// Cost of iterating over `amount` children while burning, without counting child burning itself.
1250 ///1477 ///
1251 /// This method shouldn't be used directly, as it doesn't count depth price, use `burn_recursively` instead1478 /// This method shouldn't be used directly, as it doesn't count depth price, use [burn_recursively](CommonWeightInfo::burn_recursively) instead
1252 fn burn_recursively_breadth_raw(amount: u32) -> Weight;1479 fn burn_recursively_breadth_raw(amount: u32) -> Weight;
12531480
1481 /// The price of recursive burning a token.
1482 ///
1483 /// `max_selfs` - The maximum burning weight of the token itself.
1484 /// `max_breadth` - The maximum number of nested tokens to burn.
1254 fn burn_recursively(max_selfs: u32, max_breadth: u32) -> Weight {1485 fn burn_recursively(max_selfs: u32, max_breadth: u32) -> Weight {
1255 Self::burn_recursively_self_raw()1486 Self::burn_recursively_self_raw()
1256 .saturating_mul(max_selfs.max(1) as u64)1487 .saturating_mul(max_selfs.max(1) as u64)
1257 .saturating_add(Self::burn_recursively_breadth_raw(max_breadth))1488 .saturating_add(Self::burn_recursively_breadth_raw(max_breadth))
1258 }1489 }
1259}1490}
12601491
1492/// Weight info extension trait for refungible pallet.
1261pub trait RefungibleExtensionsWeightInfo {1493pub trait RefungibleExtensionsWeightInfo {
1494 /// Weight of token repartition.
1262 fn repartition() -> Weight;1495 fn repartition() -> Weight;
1263}1496}
12641497
1498/// Common collection operations.
1499///
1500/// It wraps methods in Fungible, Nonfungible and Refungible pallets
1501/// and adds weight info.
1265pub trait CommonCollectionOperations<T: Config> {1502pub trait CommonCollectionOperations<T: Config> {
1503 /// Create token.
1504 ///
1505 /// * `sender` - The user who mint the token and pays for the transaction.
1506 /// * `to` - The user who will own the token.
1507 /// * `data` - Token data.
1508 /// * `nesting_budget` - A budget that can be spent on nesting tokens.
1266 fn create_item(1509 fn create_item(
1267 &self,1510 &self,
1268 sender: T::CrossAccountId,1511 sender: T::CrossAccountId,
1269 to: T::CrossAccountId,1512 to: T::CrossAccountId,
1270 data: CreateItemData,1513 data: CreateItemData,
1271 nesting_budget: &dyn Budget,1514 nesting_budget: &dyn Budget,
1272 ) -> DispatchResultWithPostInfo;1515 ) -> DispatchResultWithPostInfo;
1516
1517 /// Create multiple tokens.
1518 ///
1519 /// * `sender` - The user who mint the token and pays for the transaction.
1520 /// * `to` - The user who will own the token.
1521 /// * `data` - Token data.
1522 /// * `nesting_budget` - A budget that can be spent on nesting tokens.
1273 fn create_multiple_items(1523 fn create_multiple_items(
1274 &self,1524 &self,
1275 sender: T::CrossAccountId,1525 sender: T::CrossAccountId,
1276 to: T::CrossAccountId,1526 to: T::CrossAccountId,
1277 data: Vec<CreateItemData>,1527 data: Vec<CreateItemData>,
1278 nesting_budget: &dyn Budget,1528 nesting_budget: &dyn Budget,
1279 ) -> DispatchResultWithPostInfo;1529 ) -> DispatchResultWithPostInfo;
1530
1531 /// Create multiple tokens.
1532 ///
1533 /// * `sender` - The user who mint the token and pays for the transaction.
1534 /// * `to` - The user who will own the token.
1535 /// * `data` - Token data.
1536 /// * `nesting_budget` - A budget that can be spent on nesting tokens.
1280 fn create_multiple_items_ex(1537 fn create_multiple_items_ex(
1281 &self,1538 &self,
1282 sender: T::CrossAccountId,1539 sender: T::CrossAccountId,
1283 data: CreateItemExData<T::CrossAccountId>,1540 data: CreateItemExData<T::CrossAccountId>,
1284 nesting_budget: &dyn Budget,1541 nesting_budget: &dyn Budget,
1285 ) -> DispatchResultWithPostInfo;1542 ) -> DispatchResultWithPostInfo;
1543
1544 /// Burn token.
1545 ///
1546 /// * `sender` - The user who owns the token.
1547 /// * `token` - Token id that will burned.
1548 /// * `amount` - The number of parts of the token that will be burned.
1286 fn burn_item(1549 fn burn_item(
1287 &self,1550 &self,
1288 sender: T::CrossAccountId,1551 sender: T::CrossAccountId,
1289 token: TokenId,1552 token: TokenId,
1290 amount: u128,1553 amount: u128,
1291 ) -> DispatchResultWithPostInfo;1554 ) -> DispatchResultWithPostInfo;
1555
1556 /// Burn token and all nested tokens recursievly.
1557 ///
1558 /// * `sender` - The user who owns the token.
1559 /// * `token` - Token id that will burned.
1560 /// * `self_budget` - The budget that can be spent on burning tokens.
1561 /// * `breadth_budget` - The budget that can be spent on burning nested tokens.
1292 fn burn_item_recursively(1562 fn burn_item_recursively(
1293 &self,1563 &self,
1294 sender: T::CrossAccountId,1564 sender: T::CrossAccountId,
1295 token: TokenId,1565 token: TokenId,
1296 self_budget: &dyn Budget,1566 self_budget: &dyn Budget,
1297 breadth_budget: &dyn Budget,1567 breadth_budget: &dyn Budget,
1298 ) -> DispatchResultWithPostInfo;1568 ) -> DispatchResultWithPostInfo;
1569
1570 /// Set collection properties.
1571 ///
1572 /// * `sender` - Must be either the owner of the collection or its admin.
1573 /// * `properties` - Properties to be set.
1299 fn set_collection_properties(1574 fn set_collection_properties(
1300 &self,1575 &self,
1301 sender: T::CrossAccountId,1576 sender: T::CrossAccountId,
1302 properties: Vec<Property>,1577 properties: Vec<Property>,
1303 ) -> DispatchResultWithPostInfo;1578 ) -> DispatchResultWithPostInfo;
1579
1580 /// Delete collection properties.
1581 ///
1582 /// * `sender` - Must be either the owner of the collection or its admin.
1583 /// * `properties` - The properties to be removed.
1304 fn delete_collection_properties(1584 fn delete_collection_properties(
1305 &self,1585 &self,
1306 sender: &T::CrossAccountId,1586 sender: &T::CrossAccountId,
1307 property_keys: Vec<PropertyKey>,1587 property_keys: Vec<PropertyKey>,
1308 ) -> DispatchResultWithPostInfo;1588 ) -> DispatchResultWithPostInfo;
1589
1590 /// Set token properties.
1591 ///
1592 /// The appropriate [`PropertyPermission`] for the token property
1593 /// must be set with [`Self::set_token_property_permissions`].
1594 ///
1595 /// * `sender` - Must be either the owner of the token or its admin.
1596 /// * `token_id` - The token for which the properties are being set.
1597 /// * `properties` - Properties to be set.
1598 /// * `budget` - Budget for setting properties.
1309 fn set_token_properties(1599 fn set_token_properties(
1310 &self,1600 &self,
1311 sender: T::CrossAccountId,1601 sender: T::CrossAccountId,
1312 token_id: TokenId,1602 token_id: TokenId,
1313 property: Vec<Property>,1603 properties: Vec<Property>,
1314 nesting_budget: &dyn Budget,1604 budget: &dyn Budget,
1315 ) -> DispatchResultWithPostInfo;1605 ) -> DispatchResultWithPostInfo;
1606
1607 /// Remove token properties.
1608 ///
1609 /// The appropriate [`PropertyPermission`] for the token property
1610 /// must be set with [`Self::set_token_property_permissions`].
1611 ///
1612 /// * `sender` - Must be either the owner of the token or its admin.
1613 /// * `token_id` - The token for which the properties are being remove.
1614 /// * `property_keys` - Keys to remove corresponding properties.
1615 /// * `budget` - Budget for removing properties.
1316 fn delete_token_properties(1616 fn delete_token_properties(
1317 &self,1617 &self,
1318 sender: T::CrossAccountId,1618 sender: T::CrossAccountId,
1319 token_id: TokenId,1619 token_id: TokenId,
1320 property_keys: Vec<PropertyKey>,1620 property_keys: Vec<PropertyKey>,
1321 nesting_budget: &dyn Budget,1621 budget: &dyn Budget,
1322 ) -> DispatchResultWithPostInfo;1622 ) -> DispatchResultWithPostInfo;
1623
1624 /// Set token property permissions.
1625 ///
1626 /// * `sender` - Must be either the owner of the token or its admin.
1627 /// * `token_id` - The token for which the properties are being set.
1628 /// * `properties` - Properties to be set.
1629 /// * `budget` - Budget for setting properties.
1323 fn set_token_property_permissions(1630 fn set_token_property_permissions(
1324 &self,1631 &self,
1325 sender: &T::CrossAccountId,1632 sender: &T::CrossAccountId,
1326 property_permissions: Vec<PropertyKeyPermission>,1633 property_permissions: Vec<PropertyKeyPermission>,
1327 ) -> DispatchResultWithPostInfo;1634 ) -> DispatchResultWithPostInfo;
1635
1636 /// Transfer amount of token pieces.
1637 ///
1638 /// * `sender` - Donor user.
1639 /// * `to` - Recepient user.
1640 /// * `token` - The token of which parts are being sent.
1641 /// * `amount` - The number of parts of the token that will be transferred.
1642 /// * `budget` - The maximum budget that can be spent on the transfer.
1328 fn transfer(1643 fn transfer(
1329 &self,1644 &self,
1330 sender: T::CrossAccountId,1645 sender: T::CrossAccountId,
1331 to: T::CrossAccountId,1646 to: T::CrossAccountId,
1332 token: TokenId,1647 token: TokenId,
1333 amount: u128,1648 amount: u128,
1334 nesting_budget: &dyn Budget,1649 budget: &dyn Budget,
1335 ) -> DispatchResultWithPostInfo;1650 ) -> DispatchResultWithPostInfo;
1651
1652 /// Grant access to another account to transfer parts of the token owned by the calling user via [Self::transfer_from].
1653 ///
1654 /// * `sender` - The user who grants access to the token.
1655 /// * `spender` - The user to whom the rights are granted.
1656 /// * `token` - The token to which access is granted.
1657 /// * `amount` - The amount of pieces that another user can dispose of.
1336 fn approve(1658 fn approve(
1337 &self,1659 &self,
1338 sender: T::CrossAccountId,1660 sender: T::CrossAccountId,
1339 spender: T::CrossAccountId,1661 spender: T::CrossAccountId,
1340 token: TokenId,1662 token: TokenId,
1341 amount: u128,1663 amount: u128,
1342 ) -> DispatchResultWithPostInfo;1664 ) -> DispatchResultWithPostInfo;
1665
1666 /// Send parts of a token owned by another user.
1667 ///
1668 /// Before calling this method, you must grant rights to the calling user via [`Self::approve`].
1669 ///
1670 /// * `sender` - The user who must have access to the token (see [`Self::approve`]).
1671 /// * `from` - The user who owns the token.
1672 /// * `to` - Recepient user.
1673 /// * `token` - The token of which parts are being sent.
1674 /// * `amount` - The number of parts of the token that will be transferred.
1675 /// * `budget` - The maximum budget that can be spent on the transfer.
1343 fn transfer_from(1676 fn transfer_from(
1344 &self,1677 &self,
1345 sender: T::CrossAccountId,1678 sender: T::CrossAccountId,
1346 from: T::CrossAccountId,1679 from: T::CrossAccountId,
1347 to: T::CrossAccountId,1680 to: T::CrossAccountId,
1348 token: TokenId,1681 token: TokenId,
1349 amount: u128,1682 amount: u128,
1350 nesting_budget: &dyn Budget,1683 budget: &dyn Budget,
1351 ) -> DispatchResultWithPostInfo;1684 ) -> DispatchResultWithPostInfo;
1685
1686 /// Burn parts of a token owned by another user.
1687 ///
1688 /// Before calling this method, you must grant rights to the calling user via [`Self::approve`].
1689 ///
1690 /// * `sender` - The user who must have access to the token (see [`Self::approve`]).
1691 /// * `from` - The user who owns the token.
1692 /// * `token` - The token of which parts are being sent.
1693 /// * `amount` - The number of parts of the token that will be transferred.
1694 /// * `budget` - The maximum budget that can be spent on the burn.
1352 fn burn_from(1695 fn burn_from(
1353 &self,1696 &self,
1354 sender: T::CrossAccountId,1697 sender: T::CrossAccountId,
1355 from: T::CrossAccountId,1698 from: T::CrossAccountId,
1356 token: TokenId,1699 token: TokenId,
1357 amount: u128,1700 amount: u128,
1358 nesting_budget: &dyn Budget,1701 budget: &dyn Budget,
1359 ) -> DispatchResultWithPostInfo;1702 ) -> DispatchResultWithPostInfo;
13601703
1704 /// Check permission to nest token.
1705 ///
1706 /// * `sender` - The user who initiated the check.
1707 /// * `from` - The token that is checked for embedding.
1708 /// * `under` - Token under which to check.
1709 /// * `budget` - The maximum budget that can be spent on the check.
1361 fn check_nesting(1710 fn check_nesting(
1362 &self,1711 &self,
1363 sender: T::CrossAccountId,1712 sender: T::CrossAccountId,
1364 from: (CollectionId, TokenId),1713 from: (CollectionId, TokenId),
1365 under: TokenId,1714 under: TokenId,
1366 nesting_budget: &dyn Budget,1715 budget: &dyn Budget,
1367 ) -> DispatchResult;1716 ) -> DispatchResult;
13681717
1718 /// Nest one token into another.
1719 ///
1720 /// * `under` - Token holder.
1721 /// * `to_nest` - Nested token.
1369 fn nest(&self, under: TokenId, to_nest: (CollectionId, TokenId));1722 fn nest(&self, under: TokenId, to_nest: (CollectionId, TokenId));
13701723
1724 /// Unnest token.
1725 ///
1726 /// * `under` - Token holder.
1727 /// * `to_nest` - Token to unnest.
1371 fn unnest(&self, under: TokenId, to_nest: (CollectionId, TokenId));1728 fn unnest(&self, under: TokenId, to_nest: (CollectionId, TokenId));
13721729
1730 /// Get all user tokens.
1731 ///
1732 /// * `account` - Account for which you need to get tokens.
1373 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId>;1733 fn account_tokens(&self, account: T::CrossAccountId) -> Vec<TokenId>;
1734
1735 /// Get all the tokens in the collection.
1374 fn collection_tokens(&self) -> Vec<TokenId>;1736 fn collection_tokens(&self) -> Vec<TokenId>;
1737
1738 /// Check if the token exists.
1739 ///
1740 /// * `token` - Id token to check.
1375 fn token_exists(&self, token: TokenId) -> bool;1741 fn token_exists(&self, token: TokenId) -> bool;
1742
1743 /// Get the id of the last minted token.
1376 fn last_token_id(&self) -> TokenId;1744 fn last_token_id(&self) -> TokenId;
13771745
1746 /// Get the owner of the token.
1747 ///
1748 /// * `token` - The token for which you need to find out the owner.
1378 fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId>;1749 fn token_owner(&self, token: TokenId) -> Option<T::CrossAccountId>;
1750
1751 /// Get the value of the token property by key.
1752 ///
1753 /// * `token` - Token with the property to get.
1754 /// * `key` - Property name.
1379 fn token_property(&self, token_id: TokenId, key: &PropertyKey) -> Option<PropertyValue>;1755 fn token_property(&self, token_id: TokenId, key: &PropertyKey) -> Option<PropertyValue>;
1756
1380 fn token_properties(&self, token_id: TokenId, keys: Option<Vec<PropertyKey>>) -> Vec<Property>;1757 /// Get a set of token properties by key vector.
1758 ///
1759 /// * `token` - Token with the property to get.
1760 /// * `keys` - Vector of property keys. If this parameter is [None](sp_std::result::Result),
1761 /// then all properties are returned.
1762 fn token_properties(&self, token: TokenId, keys: Option<Vec<PropertyKey>>) -> Vec<Property>;
1763
1381 /// Amount of unique collection tokens1764 /// Amount of unique collection tokens
1382 fn total_supply(&self) -> u32;1765 fn total_supply(&self) -> u32;
1766
1383 /// Amount of different tokens account has (Applicable to nonfungible/refungible)1767 /// Amount of different tokens account has.
1768 ///
1769 /// * `account` - The account for which need to get the balance.
1384 fn account_balance(&self, account: T::CrossAccountId) -> u32;1770 fn account_balance(&self, account: T::CrossAccountId) -> u32;
1771
1385 /// Amount of specific token account have (Applicable to fungible/refungible)1772 /// Amount of specific token account have.
1386 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128;1773 fn balance(&self, account: T::CrossAccountId, token: TokenId) -> u128;
1774
1387 /// Amount of token pieces1775 /// Amount of token pieces
1388 fn total_pieces(&self, token: TokenId) -> Option<u128>;1776 fn total_pieces(&self, token: TokenId) -> Option<u128>;
1777
1778 /// Get the number of parts of the token that a trusted user can manage.
1779 ///
1780 /// * `sender` - Trusted user.
1781 /// * `spender` - Owner of the token.
1782 /// * `token` - The token for which to get the value.
1389 fn allowance(1783 fn allowance(
1390 &self,1784 &self,
1391 sender: T::CrossAccountId,1785 sender: T::CrossAccountId,
1392 spender: T::CrossAccountId,1786 spender: T::CrossAccountId,
1393 token: TokenId,1787 token: TokenId,
1394 ) -> u128;1788 ) -> u128;
1789
1790 /// Get extension for RFT collection.
1395 fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>>;1791 fn refungible_extensions(&self) -> Option<&dyn RefungibleExtensions<T>>;
1396}1792}
13971793
1794/// Extension for RFT collection.
1398pub trait RefungibleExtensions<T>1795pub trait RefungibleExtensions<T>
1399where1796where
1400 T: Config,1797 T: Config,
1401{1798{
1799 /// Change the number of parts of the token.
1800 ///
1801 /// When the value changes down, this function is equivalent to burning parts of the token.
1802 ///
1803 /// * `sender` - The user calling the repartition operation. Must be the owner of the token.
1804 /// * `token` - The token for which you want to change the number of parts.
1805 /// * `amount` - The new value of the parts of the token.
1402 fn repartition(1806 fn repartition(
1403 &self,1807 &self,
1404 owner: &T::CrossAccountId,1808 sender: &T::CrossAccountId,
1405 token: TokenId,1809 token: TokenId,
1406 amount: u128,1810 amount: u128,
1407 ) -> DispatchResultWithPostInfo;1811 ) -> DispatchResultWithPostInfo;
1408}1812}
14091813
1410// Flexible enough for implementing CommonCollectionOperations1814/// Merge [`DispatchResult`] with [`Weight`] into [`DispatchResultWithPostInfo`].
1815///
1816/// Used for [`CommonCollectionOperations`] implementations and flexible enough to do so.
1411pub fn with_weight(res: DispatchResult, weight: Weight) -> DispatchResultWithPostInfo {1817pub fn with_weight(res: DispatchResult, weight: Weight) -> DispatchResultWithPostInfo {
1412 let post_info = PostDispatchInfo {1818 let post_info = PostDispatchInfo {
1413 actual_weight: Some(weight),1819 actual_weight: Some(weight),