git.delta.rocks / unique-network / refs/commits / 376ee6b104f8

difftreelog

Merge pull request #432 from UniqueNetwork/doc/refungible-pallet

Yaroslav Bolyukin2022-07-14parents: #12c8c8f #f742d10.patch.diff
in: master
Doc for refungible pallet

2 files changed

modifiedpallets/refungible/src/common.rsdiffbeforeafterboth
145 }145 }
146}146}
147147
148/// Implementation of `CommonCollectionOperations` for `RefungibleHandle`. It wraps Refungible Pallete
149/// methods and adds weight info.
148impl<T: Config> CommonCollectionOperations<T> for RefungibleHandle<T> {150impl<T: Config> CommonCollectionOperations<T> for RefungibleHandle<T> {
149 fn create_item(151 fn create_item(
150 &self,152 &self,
modifiedpallets/refungible/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/>.
16
17//! # Refungible Pallet
18//!
19//! The Refungible pallet provides functionality for handling refungible collections and tokens.
20//!
21//! - [`Config`]
22//! - [`RefungibleHandle`]
23//! - [`Pallet`]
24//! - [`CommonWeights`]
25//!
26//! ## Overview
27//!
28//! The Refungible pallet provides functions for:
29//!
30//! - RFT collection creation and removal
31//! - Minting and burning of RFT tokens
32//! - Partition and repartition of RFT tokens
33//! - Retrieving number of pieces of RFT token
34//! - Retrieving account balances
35//! - Transfering RFT token pieces
36//! - Burning RFT token pieces
37//! - Setting and checking allowance for RFT tokens
38//!
39//! ### Terminology
40//!
41//! - **RFT token:** Non fungible token that was partitioned to pieces. If an account owns all
42//! of the RFT token pieces than it owns the RFT token and can repartition it.
43//!
44//! - **RFT Collection:** A collection of RFT tokens. All RFT tokens are part of a collection.
45//! Each collection has its own settings and set of permissions.
46//!
47//! - **RFT token piece:** A fungible part of an RFT token.
48//!
49//! - **Balance:** RFT token pieces owned by an account
50//!
51//! - **Allowance:** Maximum number of RFT token pieces that one account is allowed to
52//! transfer from the balance of another account
53//!
54//! - **Burning:** The process of “deleting” a token from a collection or removing token pieces from
55//! an account balance.
56//!
57//! ### Implementations
58//!
59//! The Refungible pallet provides implementations for the following traits. If these traits provide
60//! the functionality that you need, then you can avoid coupling with the Refungible pallet.
61//!
62//! - [`CommonWeightInfo`](pallet_common::CommonWeightInfo): Functions for retrieval of transaction weight
63//! - [`CommonCollectionOperations`](pallet_common::CommonCollectionOperations): Functions for dealing
64//! with collections
65//! - [`RefungibleExtensions`](pallet_common::RefungibleExtensions): Functions specific for refungible
66//! collection
67//!
68//! ## Interface
69//!
70//! ### Dispatchable Functions
71//!
72//! - `init_collection` - Create RFT collection. RFT collection can be configured to allow or deny access for
73//! some accounts.
74//! - `destroy_collection` - Destroy exising RFT collection. There should be no tokens in the collection.
75//! - `burn` - Burn some amount of RFT token pieces owned by account. Burns the RFT token if no pieces left.
76//! - `transfer` - Transfer some amount of RFT token pieces. Transfers should be enabled for RFT collection.
77//! Nests the RFT token if RFT token pieces are sent to another token.
78//! - `create_item` - Mint RFT token in collection. Sender should have permission to mint tokens.
79//! - `set_allowance` - Set allowance for another account to transfer balance from sender's account.
80//! - `repartition` - Repartition token to selected number of pieces. Sender should own all existing pieces.
81//!
82//! ## Assumptions
83//!
84//! * Total number of pieces for one token shouldn't exceed `up_data_structs::MAX_REFUNGIBLE_PIECES`.
85//! * Total number of tokens of all types shouldn't be greater than `up_data_structs::MAX_TOKEN_PREFIX_LENGTH`.
86//! * Sender should be in collection's allow list to perform operations on tokens.
1687
17#![cfg_attr(not(feature = "std"), no_std)]88#![cfg_attr(not(feature = "std"), no_std)]
1889
86 #[pallet::generate_store(pub(super) trait Store)]157 #[pallet::generate_store(pub(super) trait Store)]
87 pub struct Pallet<T>(_);158 pub struct Pallet<T>(_);
88159
160 /// Amount of tokens minted for collection
89 #[pallet::storage]161 #[pallet::storage]
90 pub type TokensMinted<T: Config> =162 pub type TokensMinted<T: Config> =
91 StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u32, QueryKind = ValueQuery>;163 StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u32, QueryKind = ValueQuery>;
164
165 /// Amount of burnt tokens for collection
92 #[pallet::storage]166 #[pallet::storage]
93 pub type TokensBurnt<T: Config> =167 pub type TokensBurnt<T: Config> =
94 StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u32, QueryKind = ValueQuery>;168 StorageMap<Hasher = Twox64Concat, Key = CollectionId, Value = u32, QueryKind = ValueQuery>;
95169
170 /// Custom data serialized to bytes for token
96 #[pallet::storage]171 #[pallet::storage]
97 pub type TokenData<T: Config> = StorageNMap<172 pub type TokenData<T: Config> = StorageNMap<
98 Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),173 Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),
99 Value = ItemData,174 Value = ItemData,
100 QueryKind = ValueQuery,175 QueryKind = ValueQuery,
101 >;176 >;
102177
178 /// Total amount of pieces for token
103 #[pallet::storage]179 #[pallet::storage]
104 pub type TotalSupply<T: Config> = StorageNMap<180 pub type TotalSupply<T: Config> = StorageNMap<
105 Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),181 Key = (Key<Twox64Concat, CollectionId>, Key<Twox64Concat, TokenId>),
119 QueryKind = ValueQuery,195 QueryKind = ValueQuery,
120 >;196 >;
121197
198 /// Amount of tokens owned by account
122 #[pallet::storage]199 #[pallet::storage]
123 pub type AccountBalance<T: Config> = StorageNMap<200 pub type AccountBalance<T: Config> = StorageNMap<
124 Key = (201 Key = (
130 QueryKind = ValueQuery,207 QueryKind = ValueQuery,
131 >;208 >;
132209
210 /// Amount of token pieces owned by account
133 #[pallet::storage]211 #[pallet::storage]
134 pub type Balance<T: Config> = StorageNMap<212 pub type Balance<T: Config> = StorageNMap<
135 Key = (213 Key = (
142 QueryKind = ValueQuery,220 QueryKind = ValueQuery,
143 >;221 >;
144222
223 /// Allowance set by an owner for a spender for a token
145 #[pallet::storage]224 #[pallet::storage]
146 pub type Allowance<T: Config> = StorageNMap<225 pub type Allowance<T: Config> = StorageNMap<
147 Key = (226 Key = (
188}267}
189268
190impl<T: Config> Pallet<T> {269impl<T: Config> Pallet<T> {
270 /// Get number of RFT tokens in collection
191 pub fn total_supply(collection: &RefungibleHandle<T>) -> u32 {271 pub fn total_supply(collection: &RefungibleHandle<T>) -> u32 {
192 <TokensMinted<T>>::get(collection.id) - <TokensBurnt<T>>::get(collection.id)272 <TokensMinted<T>>::get(collection.id) - <TokensBurnt<T>>::get(collection.id)
193 }273 }
274
275 /// Check that RFT token exists
276 ///
277 /// - `token`: Token ID.
194 pub fn token_exists(collection: &RefungibleHandle<T>, token: TokenId) -> bool {278 pub fn token_exists(collection: &RefungibleHandle<T>, token: TokenId) -> bool {
195 <TotalSupply<T>>::contains_key((collection.id, token))279 <TotalSupply<T>>::contains_key((collection.id, token))
196 }280 }
197}281}
198282
199// unchecked calls skips any permission checks283// unchecked calls skips any permission checks
200impl<T: Config> Pallet<T> {284impl<T: Config> Pallet<T> {
285 /// Create RFT collection
286 ///
287 /// `init_collection` will take non-refundable deposit for collection creation.
288 ///
289 /// - `data`: Contains settings for collection limits and permissions.
201 pub fn init_collection(290 pub fn init_collection(
202 owner: T::CrossAccountId,291 owner: T::CrossAccountId,
203 data: CreateCollectionData<T::AccountId>,292 data: CreateCollectionData<T::AccountId>,
204 ) -> Result<CollectionId, DispatchError> {293 ) -> Result<CollectionId, DispatchError> {
205 <PalletCommon<T>>::init_collection(owner, data, false)294 <PalletCommon<T>>::init_collection(owner, data, false)
206 }295 }
296
297 /// Destroy RFT collection
298 ///
299 /// `destroy_collection` will throw error if collection contains any tokens.
300 /// Only owner can destroy collection.
207 pub fn destroy_collection(301 pub fn destroy_collection(
208 collection: RefungibleHandle<T>,302 collection: RefungibleHandle<T>,
209 sender: &T::CrossAccountId,303 sender: &T::CrossAccountId,
235 .is_some()329 .is_some()
236 }330 }
237331
238 pub fn burn_token(collection: &RefungibleHandle<T>, token_id: TokenId) -> DispatchResult {332 pub fn burn_token_unchecked(
333 collection: &RefungibleHandle<T>,
334 token_id: TokenId,
335 ) -> DispatchResult {
249 Ok(())346 Ok(())
250 }347 }
251348
349 /// Burn RFT token pieces
350 ///
351 /// `burn` will decrease total amount of token pieces and amount owned by sender.
352 /// `burn` can be called even if there are multiple owners of the RFT token.
353 /// If sender wouldn't have any pieces left after `burn` than she will stop being
354 /// one of the owners of the token. If there is no account that owns any pieces of
355 /// the token than token will be burned too.
356 ///
357 /// - `amount`: Amount of token pieces to burn.
358 /// - `token`: Token who's pieces should be burned
359 /// - `collection`: Collection that contains the token
252 pub fn burn(360 pub fn burn(
253 collection: &RefungibleHandle<T>,361 collection: &RefungibleHandle<T>,
254 owner: &T::CrossAccountId,362 owner: &T::CrossAccountId,
276 <Owned<T>>::remove((collection.id, owner, token));384 <Owned<T>>::remove((collection.id, owner, token));
277 <PalletStructure<T>>::unnest_if_nested(owner, collection.id, token);385 <PalletStructure<T>>::unnest_if_nested(owner, collection.id, token);
278 <AccountBalance<T>>::insert((collection.id, owner), account_balance);386 <AccountBalance<T>>::insert((collection.id, owner), account_balance);
279 Self::burn_token(collection, token)?;387 Self::burn_token_unchecked(collection, token)?;
280 <PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(388 <PalletCommon<T>>::deposit_event(CommonEvent::ItemDestroyed(
281 collection.id,389 collection.id,
282 token,390 token,
319 Ok(())427 Ok(())
320 }428 }
321429
430 /// Transfer RFT token pieces from one account to another.
431 ///
432 /// If the sender is no longer owns any pieces after the `transfer` than she stops being an owner of the token.
433 ///
434 /// - `from`: Owner of token pieces to transfer.
435 /// - `to`: Recepient of transfered token pieces.
436 /// - `amount`: Amount of token pieces to transfer.
437 /// - `token`: Token whos pieces should be transfered
438 /// - `collection`: Collection that contains the token
322 pub fn transfer(439 pub fn transfer(
323 collection: &RefungibleHandle<T>,440 collection: &RefungibleHandle<T>,
324 from: &T::CrossAccountId,441 from: &T::CrossAccountId,
423 Ok(())540 Ok(())
424 }541 }
425542
543 /// Batched operation to create multiple RFT tokens.
544 ///
545 /// Same as `create_item` but creates multiple tokens.
546 ///
547 /// - `data`: Same as 'data` in `create_item` but contains data for multiple tokens.
426 pub fn create_multiple_items(548 pub fn create_multiple_items(
427 collection: &RefungibleHandle<T>,549 collection: &RefungibleHandle<T>,
428 sender: &T::CrossAccountId,550 sender: &T::CrossAccountId,
568 ))690 ))
569 }691 }
570692
693 /// Set allowance for the spender to `transfer` or `burn` sender's token pieces.
694 ///
695 /// - `amount`: Amount of token pieces the spender is allowed to `transfer` or `burn.
571 pub fn set_allowance(696 pub fn set_allowance(
572 collection: &RefungibleHandle<T>,697 collection: &RefungibleHandle<T>,
573 sender: &T::CrossAccountId,698 sender: &T::CrossAccountId,
636 Ok(allowance)761 Ok(allowance)
637 }762 }
638763
764 /// Transfer RFT token pieces from one account to another.
765 ///
766 /// Same as the [`transfer`] but spender doesn't needs to be an owner of the token pieces.
767 /// The owner should set allowance for the spender to transfer pieces.
768 ///
769 /// [`transfer`]: struct.Pallet.html#method.transfer
639 pub fn transfer_from(770 pub fn transfer_from(
640 collection: &RefungibleHandle<T>,771 collection: &RefungibleHandle<T>,
641 spender: &T::CrossAccountId,772 spender: &T::CrossAccountId,
657 Ok(())788 Ok(())
658 }789 }
659790
791 /// Burn RFT token pieces from the account.
792 ///
793 /// Same as the [`burn`] but spender doesn't need to be an owner of the token pieces. The owner should
794 /// set allowance for the spender to burn pieces
795 ///
796 /// [`burn`]: struct.Pallet.html#method.burn
660 pub fn burn_from(797 pub fn burn_from(
661 collection: &RefungibleHandle<T>,798 collection: &RefungibleHandle<T>,
662 spender: &T::CrossAccountId,799 spender: &T::CrossAccountId,
677 Ok(())814 Ok(())
678 }815 }
679816
680 /// Delegated to `create_multiple_items`817 /// Create RFT token.
818 ///
819 /// The sender should be the owner/admin of the collection or collection should be configured
820 /// to allow public minting.
821 ///
822 /// - `data`: Contains list of users who will become the owners of the token pieces and amount
823 /// of token pieces they will receive.
681 pub fn create_item(824 pub fn create_item(
682 collection: &RefungibleHandle<T>,825 collection: &RefungibleHandle<T>,
683 sender: &T::CrossAccountId,826 sender: &T::CrossAccountId,
687 Self::create_multiple_items(collection, sender, vec![data], nesting_budget)830 Self::create_multiple_items(collection, sender, vec![data], nesting_budget)
688 }831 }
689832
833 /// Repartition RFT token.
834 ///
835 /// `repartition` will set token balance of the sender and total amount of token pieces.
836 /// Sender should own all of the token pieces. `repartition' could be done even if some
837 /// token pieces were burned before.
838 ///
839 /// - `amount`: Total amount of token pieces that the token will have after `repartition`.
690 pub fn repartition(840 pub fn repartition(
691 collection: &RefungibleHandle<T>,841 collection: &RefungibleHandle<T>,
692 owner: &T::CrossAccountId,842 owner: &T::CrossAccountId,