difftreelog
Merge pull request #432 from UniqueNetwork/doc/refungible-pallet
in: master
Doc for refungible pallet
2 files changed
pallets/refungible/src/common.rsdiffbeforeafterboth145 }145 }146}146}147147148/// Implementation of `CommonCollectionOperations` for `RefungibleHandle`. It wraps Refungible Pallete149/// 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,pallets/refungible/src/lib.rsdiffbeforeafterboth14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License15// 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/>.1617//! # Refungible Pallet18//!19//! The Refungible pallet provides functionality for handling refungible collections and tokens.20//!21//! - [`Config`]22//! - [`RefungibleHandle`]23//! - [`Pallet`]24//! - [`CommonWeights`]25//!26//! ## Overview27//!28//! The Refungible pallet provides functions for:29//!30//! - RFT collection creation and removal31//! - Minting and burning of RFT tokens32//! - Partition and repartition of RFT tokens33//! - Retrieving number of pieces of RFT token34//! - Retrieving account balances35//! - Transfering RFT token pieces36//! - Burning RFT token pieces37//! - Setting and checking allowance for RFT tokens38//!39//! ### Terminology40//!41//! - **RFT token:** Non fungible token that was partitioned to pieces. If an account owns all42//! 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 account50//!51//! - **Allowance:** Maximum number of RFT token pieces that one account is allowed to52//! transfer from the balance of another account53//!54//! - **Burning:** The process of “deleting” a token from a collection or removing token pieces from55//! an account balance.56//!57//! ### Implementations58//!59//! The Refungible pallet provides implementations for the following traits. If these traits provide60//! 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 weight63//! - [`CommonCollectionOperations`](pallet_common::CommonCollectionOperations): Functions for dealing64//! with collections65//! - [`RefungibleExtensions`](pallet_common::RefungibleExtensions): Functions specific for refungible66//! collection67//!68//! ## Interface69//!70//! ### Dispatchable Functions71//!72//! - `init_collection` - Create RFT collection. RFT collection can be configured to allow or deny access for73//! 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//! ## Assumptions83//!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.168717#![cfg_attr(not(feature = "std"), no_std)]88#![cfg_attr(not(feature = "std"), no_std)]188986 #[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>(_);88159160 /// Amount of tokens minted for collection89 #[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>;164165 /// Amount of burnt tokens for collection92 #[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>;95169170 /// Custom data serialized to bytes for token96 #[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 >;102177178 /// Total amount of pieces for token103 #[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 >;121197198 /// Amount of tokens owned by account122 #[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 >;132209210 /// Amount of token pieces owned by account133 #[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 >;144222223 /// Allowance set by an owner for a spender for a token145 #[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}189268190impl<T: Config> Pallet<T> {269impl<T: Config> Pallet<T> {270 /// Get number of RFT tokens in collection191 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 }274275 /// Check that RFT token exists276 ///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}198282199// unchecked calls skips any permission checks283// unchecked calls skips any permission checks200impl<T: Config> Pallet<T> {284impl<T: Config> Pallet<T> {285 /// Create RFT collection286 ///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 }296297 /// Destroy RFT collection298 ///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 }237331238 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 }251348349 /// Burn RFT token pieces350 ///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 being354 /// one of the owners of the token. If there is no account that owns any pieces of355 /// 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 burned359 /// - `collection`: Collection that contains the token252 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 }321429430 /// 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 transfered438 /// - `collection`: Collection that contains the token322 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 }425542543 /// 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 }570692693 /// 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 }638763764 /// 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.transfer639 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 }659790791 /// 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 should794 /// set allowance for the spender to burn pieces795 ///796 /// [`burn`]: struct.Pallet.html#method.burn660 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 }679816680 /// 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 configured820 /// to allow public minting.821 ///822 /// - `data`: Contains list of users who will become the owners of the token pieces and amount823 /// 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 }689832833 /// 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 some837 /// 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,