difftreelog
fix code style
in: master
4 files changed
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -13,9 +13,8 @@
use pallet_evm::GasWeightMapping;
use up_data_structs::{
COLLECTION_NUMBER_LIMIT, Collection, CollectionId, CreateItemData, ExistenceRequirement,
- MAX_TOKEN_PREFIX_LENGTH,
- COLLECTION_ADMINS_LIMIT, MetaUpdatePermission, Pays, PostDispatchInfo, TokenId, Weight,
- WithdrawReasons, CollectionStats, MAX_TOKEN_OWNERSHIP, CollectionMode,
+ MAX_TOKEN_PREFIX_LENGTH, COLLECTION_ADMINS_LIMIT, MetaUpdatePermission, Pays, PostDispatchInfo,
+ TokenId, Weight, WithdrawReasons, CollectionStats, MAX_TOKEN_OWNERSHIP, CollectionMode,
NFT_SPONSOR_TRANSFER_TIMEOUT, FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT,
REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT, MAX_SPONSOR_TIMEOUT, CUSTOM_DATA_LIMIT, CollectionLimits,
CustomDataLimit, CreateCollectionData, SponsorshipState,
pallets/nonfungible/src/lib.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -3,8 +3,7 @@
use erc::ERC721Events;
use frame_support::{BoundedVec, ensure};
use up_data_structs::{
- AccessMode, Collection, CollectionId, CustomDataLimit, TokenId,
- CreateCollectionData,
+ AccessMode, Collection, CollectionId, CustomDataLimit, TokenId, CreateCollectionData,
};
use pallet_common::{
Error as CommonError, Pallet as PalletCommon, Event as CommonEvent, account::CrossAccountId,
pallets/refungible/src/lib.rsdiffbeforeafterboth--- a/pallets/refungible/src/lib.rs
+++ b/pallets/refungible/src/lib.rs
@@ -2,8 +2,8 @@
use frame_support::{ensure, BoundedVec};
use up_data_structs::{
- AccessMode, Collection, CollectionId, CustomDataLimit,
- MAX_REFUNGIBLE_PIECES, TokenId, CreateCollectionData,
+ AccessMode, Collection, CollectionId, CustomDataLimit, MAX_REFUNGIBLE_PIECES, TokenId,
+ CreateCollectionData,
};
use pallet_common::{
Error as CommonError, Event as CommonEvent, Pallet as PalletCommon, account::CrossAccountId,
pallets/unique/src/lib.rsdiffbeforeafterboth1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56#![recursion_limit = "1024"]7#![cfg_attr(not(feature = "std"), no_std)]8#![allow(9 clippy::too_many_arguments,10 clippy::unnecessary_mut_passed,11 clippy::unused_unit12)]1314extern crate alloc;1516pub use serde::{Serialize, Deserialize};1718pub use frame_support::{19 construct_runtime, decl_module, decl_storage, decl_error, decl_event,20 dispatch::DispatchResult,21 ensure, fail, parameter_types,22 traits::{23 ExistenceRequirement, Get, Imbalance, KeyOwnerProofSystem, OnUnbalanced, Randomness,24 IsSubType, WithdrawReasons,25 },26 weights::{27 constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND},28 DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight,29 WeightToFeePolynomial, DispatchClass,30 },31 StorageValue, transactional,32 pallet_prelude::{DispatchResultWithPostInfo, ConstU32},33 BoundedVec,34};35use scale_info::TypeInfo;36use frame_system::{self as system, ensure_signed};37use sp_runtime::{sp_std::prelude::Vec};38use up_data_structs::{39 MAX_DECIMAL_POINTS,40 VARIABLE_ON_CHAIN_SCHEMA_LIMIT, CONST_ON_CHAIN_SCHEMA_LIMIT, OFFCHAIN_SCHEMA_LIMIT,41 MAX_COLLECTION_NAME_LENGTH, MAX_COLLECTION_DESCRIPTION_LENGTH,42 MAX_TOKEN_PREFIX_LENGTH, AccessMode, Collection, CreateItemData, CollectionLimits,43 CollectionId, CollectionMode, TokenId, SchemaVersion, SponsorshipState, MetaUpdatePermission,44 CreateCollectionData, CustomDataLimit,45};46use pallet_common::{47 account::CrossAccountId, CollectionHandle, Pallet as PalletCommon, Error as CommonError,48 CommonWeightInfo,49};50use pallet_refungible::{Pallet as PalletRefungible, RefungibleHandle};51use pallet_fungible::{Pallet as PalletFungible, FungibleHandle};52use pallet_nonfungible::{Pallet as PalletNonfungible, NonfungibleHandle};5354#[cfg(test)]55mod mock;5657#[cfg(test)]58mod tests;5960mod eth;61mod sponsorship;62pub use sponsorship::UniqueSponsorshipHandler;63pub use eth::sponsoring::UniqueEthSponsorshipHandler;6465pub use eth::UniqueErcSupport;6667pub mod common;68use common::CommonWeights;69pub mod dispatch;70use dispatch::dispatch_call;7172#[cfg(feature = "runtime-benchmarks")]73mod benchmarking;74pub mod weights;75use weights::WeightInfo;7677decl_error! {78 /// Error for non-fungible-token module.79 pub enum Error for Module<T: Config> {80 /// Decimal_points parameter must be lower than MAX_DECIMAL_POINTS constant, currently it is 30.81 CollectionDecimalPointLimitExceeded,82 /// This address is not set as sponsor, use setCollectionSponsor first.83 ConfirmUnsetSponsorFail,84 /// Length of items properties must be greater than 0.85 EmptyArgument,86 }87}8889pub trait Config:90 system::Config91 + pallet_evm_coder_substrate::Config92 + pallet_common::Config93 + pallet_nonfungible::Config94 + pallet_refungible::Config95 + pallet_fungible::Config96 + Sized97 + TypeInfo98{99 type Event: From<Event<Self>> + Into<<Self as frame_system::Config>::Event>;100101 /// Weight information for extrinsics in this pallet.102 type WeightInfo: WeightInfo;103}104105decl_event! {106 pub enum Event<T>107 where108 <T as frame_system::Config>::AccountId,109 <T as pallet_common::Config>::CrossAccountId,110 {111 /// Collection sponsor was removed112 ///113 /// # Arguments114 ///115 /// * collection_id: Globally unique collection identifier.116 CollectionSponsorRemoved(CollectionId),117118 /// Collection admin was added119 ///120 /// # Arguments121 ///122 /// * collection_id: Globally unique collection identifier.123 ///124 /// * admin: Admin address.125 CollectionAdminAdded(CollectionId, CrossAccountId),126127 /// Collection owned was change128 ///129 /// # Arguments130 ///131 /// * collection_id: Globally unique collection identifier.132 ///133 /// * owner: New owner address.134 CollectionOwnedChanged(CollectionId, AccountId),135136 /// Collection sponsor was set137 ///138 /// # Arguments139 ///140 /// * collection_id: Globally unique collection identifier.141 ///142 /// * owner: New sponsor address.143 CollectionSponsorSet(CollectionId, AccountId),144145 /// const on chain schema was set146 ///147 /// # Arguments148 ///149 /// * collection_id: Globally unique collection identifier.150 ConstOnChainSchemaSet(CollectionId),151152 /// New sponsor was confirm153 ///154 /// # Arguments155 ///156 /// * collection_id: Globally unique collection identifier.157 ///158 /// * sponsor: New sponsor address.159 SponsorshipConfirmed(CollectionId, AccountId),160161 /// Collection admin was removed162 ///163 /// # Arguments164 ///165 /// * collection_id: Globally unique collection identifier.166 ///167 /// * admin: Admin address.168 CollectionAdminRemoved(CollectionId, CrossAccountId),169170 /// Address was remove from allow list171 ///172 /// # Arguments173 ///174 /// * collection_id: Globally unique collection identifier.175 ///176 /// * user: Address.177 AllowListAddressRemoved(CollectionId, CrossAccountId),178179 /// Address was add to allow list180 ///181 /// # Arguments182 ///183 /// * collection_id: Globally unique collection identifier.184 ///185 /// * user: Address.186 AllowListAddressAdded(CollectionId, CrossAccountId),187188 /// Collection limits was set189 ///190 /// # Arguments191 ///192 /// * collection_id: Globally unique collection identifier.193 CollectionLimitSet(CollectionId),194195 /// Mint permission was set196 ///197 /// # Arguments198 ///199 /// * collection_id: Globally unique collection identifier.200 MintPermissionSet(CollectionId),201202 /// Offchain schema was set203 ///204 /// # Arguments205 ///206 /// * collection_id: Globally unique collection identifier.207 OffchainSchemaSet(CollectionId),208209 /// Public access mode was set210 ///211 /// # Arguments212 ///213 /// * collection_id: Globally unique collection identifier.214 ///215 /// * mode: New access state.216 PublicAccessModeSet(CollectionId, AccessMode),217218 /// Schema version was set219 ///220 /// # Arguments221 ///222 /// * collection_id: Globally unique collection identifier.223 SchemaVersionSet(CollectionId),224225 /// Variable on chain schema was set226 ///227 /// # Arguments228 ///229 /// * collection_id: Globally unique collection identifier.230 VariableOnChainSchemaSet(CollectionId),231 }232}233234type SelfWeightOf<T> = <T as Config>::WeightInfo;235236// # Used definitions237//238// ## User control levels239//240// chain-controlled - key is uncontrolled by user241// i.e autoincrementing index242// can use non-cryptographic hash243// real - key is controlled by user244// but it is hard to generate enough colliding values, i.e owner of signed txs245// can use non-cryptographic hash246// controlled - key is completly controlled by users247// i.e maps with mutable keys248// should use cryptographic hash249//250// ## User control level downgrade reasons251//252// ?1 - chain-controlled -> controlled253// collections/tokens can be destroyed, resulting in massive holes254// ?2 - chain-controlled -> controlled255// same as ?1, but can be only added, resulting in easier exploitation256// ?3 - real -> controlled257// no confirmation required, so addresses can be easily generated258decl_storage! {259 trait Store for Module<T: Config> as Unique {260261 //#region Private members262 /// Used for migrations263 ChainVersion: u64;264 //#endregion265266 //#region Tokens transfer rate limit baskets267 /// (Collection id (controlled?2), who created (real))268 /// TODO: Off chain worker should remove from this map when collection gets removed269 pub CreateItemBasket get(fn create_item_basket): map hasher(blake2_128_concat) (CollectionId, T::AccountId) => Option<T::BlockNumber>;270 /// Collection id (controlled?2), token id (controlled?2)271 pub NftTransferBasket get(fn nft_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;272 /// Collection id (controlled?2), owning user (real)273 pub FungibleTransferBasket get(fn fungible_transfer_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;274 /// Collection id (controlled?2), token id (controlled?2)275 pub ReFungibleTransferBasket get(fn refungible_transfer_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;276 //#endregion277278 /// Variable metadata sponsoring279 /// Collection id (controlled?2), token id (controlled?2)280 pub VariableMetaDataBasket get(fn variable_meta_data_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;281 /// Approval sponsoring282 pub NftApproveBasket get(fn nft_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<T::BlockNumber>;283 pub FungibleApproveBasket get(fn fungible_approve_basket): double_map hasher(blake2_128_concat) CollectionId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;284 pub RefungibleApproveBasket get(fn refungible_approve_basket): nmap hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId, hasher(twox_64_concat) T::AccountId => Option<T::BlockNumber>;285 }286}287288decl_module! {289 pub struct Module<T: Config> for enum Call290 where291 origin: T::Origin292 {293 type Error = Error<T>;294295 fn deposit_event() = default;296297 fn on_initialize(_now: T::BlockNumber) -> Weight {298 0299 }300301 /// This method creates a Collection of NFTs. Each Token may have multiple properties encoded as an array of bytes of certain length. The initial owner of the collection is set to the address that signed the transaction and can be changed later.302 ///303 /// # Permissions304 ///305 /// * Anyone.306 ///307 /// # Arguments308 ///309 /// * collection_name: UTF-16 string with collection name (limit 64 characters), will be stored as zero-terminated.310 ///311 /// * collection_description: UTF-16 string with collection description (limit 256 characters), will be stored as zero-terminated.312 ///313 /// * token_prefix: UTF-8 string with token prefix.314 ///315 /// * mode: [CollectionMode] collection type and type dependent data.316 // returns collection ID317 #[weight = <SelfWeightOf<T>>::create_collection()]318 #[transactional]319 #[deprecated]320 pub fn create_collection(origin,321 collection_name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,322 collection_description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,323 token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,324 mode: CollectionMode) -> DispatchResult {325 let data: CreateCollectionData<T::AccountId> = CreateCollectionData {326 name: collection_name,327 description: collection_description,328 token_prefix,329 mode,330 ..Default::default()331 };332 Self::create_collection_ex(origin, data)333 }334335 /// This method creates a collection336 ///337 /// Prefer it to deprecated [`created_collection`] method338 #[weight = <SelfWeightOf<T>>::create_collection()]339 #[transactional]340 pub fn create_collection_ex(origin, data: CreateCollectionData<T::AccountId>) -> DispatchResult {341 let owner = ensure_signed(origin)?;342343 let _id = match data.mode {344 CollectionMode::NFT => {<PalletNonfungible<T>>::init_collection(owner, data)?},345 CollectionMode::Fungible(decimal_points) => {346 // check params347 ensure!(decimal_points <= MAX_DECIMAL_POINTS, Error::<T>::CollectionDecimalPointLimitExceeded);348 <PalletFungible<T>>::init_collection(owner, data)?349 }350 CollectionMode::ReFungible => {351 <PalletRefungible<T>>::init_collection(owner, data)?352 }353 };354355 Ok(())356 }357358 /// **DANGEROUS**: Destroys collection and all NFTs within this collection. Users irrecoverably lose their assets and may lose real money.359 ///360 /// # Permissions361 ///362 /// * Collection Owner.363 ///364 /// # Arguments365 ///366 /// * collection_id: collection to destroy.367 #[weight = <SelfWeightOf<T>>::destroy_collection()]368 #[transactional]369 pub fn destroy_collection(origin, collection_id: CollectionId) -> DispatchResult {370 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);371372 let collection = <CollectionHandle<T>>::try_get(collection_id)?;373 collection.check_is_owner(&sender)?;374375 // =========376377 match collection.mode {378 CollectionMode::ReFungible => PalletRefungible::destroy_collection(RefungibleHandle::cast(collection), &sender)?,379 CollectionMode::Fungible(_) => PalletFungible::destroy_collection(FungibleHandle::cast(collection), &sender)?,380 CollectionMode::NFT => PalletNonfungible::destroy_collection(NonfungibleHandle::cast(collection), &sender)?,381 }382383 <NftTransferBasket<T>>::remove_prefix(collection_id, None);384 <FungibleTransferBasket<T>>::remove_prefix(collection_id, None);385 <ReFungibleTransferBasket<T>>::remove_prefix((collection_id,), None);386387 <VariableMetaDataBasket<T>>::remove_prefix(collection_id, None);388 <NftApproveBasket<T>>::remove_prefix(collection_id, None);389 <FungibleApproveBasket<T>>::remove_prefix(collection_id, None);390 <RefungibleApproveBasket<T>>::remove_prefix((collection_id,), None);391392 Ok(())393 }394395 /// Add an address to allow list.396 ///397 /// # Permissions398 ///399 /// * Collection Owner400 /// * Collection Admin401 ///402 /// # Arguments403 ///404 /// * collection_id.405 ///406 /// * address.407 #[weight = <SelfWeightOf<T>>::add_to_allow_list()]408 #[transactional]409 pub fn add_to_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{410411 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);412 let collection = <CollectionHandle<T>>::try_get(collection_id)?;413414 <PalletCommon<T>>::toggle_allowlist(415 &collection,416 &sender,417 &address,418 true,419 )?;420421 Self::deposit_event(Event::<T>::AllowListAddressAdded(422 collection_id,423 address424 ));425426 Ok(())427 }428429 /// Remove an address from allow list.430 ///431 /// # Permissions432 ///433 /// * Collection Owner434 /// * Collection Admin435 ///436 /// # Arguments437 ///438 /// * collection_id.439 ///440 /// * address.441 #[weight = <SelfWeightOf<T>>::remove_from_allow_list()]442 #[transactional]443 pub fn remove_from_allow_list(origin, collection_id: CollectionId, address: T::CrossAccountId) -> DispatchResult{444445 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);446 let collection = <CollectionHandle<T>>::try_get(collection_id)?;447448 <PalletCommon<T>>::toggle_allowlist(449 &collection,450 &sender,451 &address,452 false,453 )?;454455 <Pallet<T>>::deposit_event(Event::<T>::AllowListAddressRemoved(456 collection_id,457 address458 ));459460 Ok(())461 }462463 /// Toggle between normal and allow list access for the methods with access for `Anyone`.464 ///465 /// # Permissions466 ///467 /// * Collection Owner.468 ///469 /// # Arguments470 ///471 /// * collection_id.472 ///473 /// * mode: [AccessMode]474 #[weight = <SelfWeightOf<T>>::set_public_access_mode()]475 #[transactional]476 pub fn set_public_access_mode(origin, collection_id: CollectionId, mode: AccessMode) -> DispatchResult477 {478 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);479480 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;481 target_collection.check_is_owner(&sender)?;482483 target_collection.access = mode.clone();484485 <Pallet<T>>::deposit_event(Event::<T>::PublicAccessModeSet(486 collection_id,487 mode488 ));489490 target_collection.save()491 }492493 /// Allows Anyone to create tokens if:494 /// * Allow List is enabled, and495 /// * Address is added to allow list, and496 /// * This method was called with True parameter497 ///498 /// # Permissions499 /// * Collection Owner500 ///501 /// # Arguments502 ///503 /// * collection_id.504 ///505 /// * mint_permission: Boolean parameter. If True, allows minting to Anyone with conditions above.506 #[weight = <SelfWeightOf<T>>::set_mint_permission()]507 #[transactional]508 pub fn set_mint_permission(origin, collection_id: CollectionId, mint_permission: bool) -> DispatchResult509 {510 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);511512 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;513 target_collection.check_is_owner(&sender)?;514515 target_collection.mint_mode = mint_permission;516517 <Pallet<T>>::deposit_event(Event::<T>::MintPermissionSet(518 collection_id519 ));520521 target_collection.save()522 }523524 /// Change the owner of the collection.525 ///526 /// # Permissions527 ///528 /// * Collection Owner.529 ///530 /// # Arguments531 ///532 /// * collection_id.533 ///534 /// * new_owner.535 #[weight = <SelfWeightOf<T>>::change_collection_owner()]536 #[transactional]537 pub fn change_collection_owner(origin, collection_id: CollectionId, new_owner: T::AccountId) -> DispatchResult {538539 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);540541 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;542 target_collection.check_is_owner(&sender)?;543544 target_collection.owner = new_owner.clone();545 <Pallet<T>>::deposit_event(Event::<T>::CollectionOwnedChanged(546 collection_id,547 new_owner548 ));549550 target_collection.save()551 }552553 /// Adds an admin of the Collection.554 /// NFT Collection can be controlled by multiple admin addresses (some which can also be servers, for example). Admins can issue and burn NFTs, as well as add and remove other admins, but cannot change NFT or Collection ownership.555 ///556 /// # Permissions557 ///558 /// * Collection Owner.559 /// * Collection Admin.560 ///561 /// # Arguments562 ///563 /// * collection_id: ID of the Collection to add admin for.564 ///565 /// * new_admin_id: Address of new admin to add.566 #[weight = <SelfWeightOf<T>>::add_collection_admin()]567 #[transactional]568 pub fn add_collection_admin(origin, collection_id: CollectionId, new_admin_id: T::CrossAccountId) -> DispatchResult {569 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);570 let collection = <CollectionHandle<T>>::try_get(collection_id)?;571572 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminAdded(573 collection_id,574 new_admin_id.clone()575 ));576577 <PalletCommon<T>>::toggle_admin(&collection, &sender, &new_admin_id, true)578 }579580 /// Remove admin address of the Collection. An admin address can remove itself. List of admins may become empty, in which case only Collection Owner will be able to add an Admin.581 ///582 /// # Permissions583 ///584 /// * Collection Owner.585 /// * Collection Admin.586 ///587 /// # Arguments588 ///589 /// * collection_id: ID of the Collection to remove admin for.590 ///591 /// * account_id: Address of admin to remove.592 #[weight = <SelfWeightOf<T>>::remove_collection_admin()]593 #[transactional]594 pub fn remove_collection_admin(origin, collection_id: CollectionId, account_id: T::CrossAccountId) -> DispatchResult {595 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);596 let collection = <CollectionHandle<T>>::try_get(collection_id)?;597598 <Pallet<T>>::deposit_event(Event::<T>::CollectionAdminRemoved(599 collection_id,600 account_id.clone()601 ));602603 <PalletCommon<T>>::toggle_admin(&collection, &sender, &account_id, false)604 }605606 /// # Permissions607 ///608 /// * Collection Owner609 ///610 /// # Arguments611 ///612 /// * collection_id.613 ///614 /// * new_sponsor.615 #[weight = <SelfWeightOf<T>>::set_collection_sponsor()]616 #[transactional]617 pub fn set_collection_sponsor(origin, collection_id: CollectionId, new_sponsor: T::AccountId) -> DispatchResult {618 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);619620 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;621 target_collection.check_is_owner(&sender)?;622623 target_collection.sponsorship = SponsorshipState::Unconfirmed(new_sponsor.clone());624625 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorSet(626 collection_id,627 new_sponsor628 ));629630 target_collection.save()631 }632633 /// # Permissions634 ///635 /// * Sponsor.636 ///637 /// # Arguments638 ///639 /// * collection_id.640 #[weight = <SelfWeightOf<T>>::confirm_sponsorship()]641 #[transactional]642 pub fn confirm_sponsorship(origin, collection_id: CollectionId) -> DispatchResult {643 let sender = ensure_signed(origin)?;644645 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;646 ensure!(647 target_collection.sponsorship.pending_sponsor() == Some(&sender),648 Error::<T>::ConfirmUnsetSponsorFail649 );650651 target_collection.sponsorship = SponsorshipState::Confirmed(sender.clone());652653 <Pallet<T>>::deposit_event(Event::<T>::SponsorshipConfirmed(654 collection_id,655 sender656 ));657658 target_collection.save()659 }660661 /// Switch back to pay-per-own-transaction model.662 ///663 /// # Permissions664 ///665 /// * Collection owner.666 ///667 /// # Arguments668 ///669 /// * collection_id.670 #[weight = <SelfWeightOf<T>>::remove_collection_sponsor()]671 #[transactional]672 pub fn remove_collection_sponsor(origin, collection_id: CollectionId) -> DispatchResult {673 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);674675 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;676 target_collection.check_is_owner(&sender)?;677678 target_collection.sponsorship = SponsorshipState::Disabled;679680 <Pallet<T>>::deposit_event(Event::<T>::CollectionSponsorRemoved(681 collection_id682 ));683 target_collection.save()684 }685686 /// This method creates a concrete instance of NFT Collection created with CreateCollection method.687 ///688 /// # Permissions689 ///690 /// * Collection Owner.691 /// * Collection Admin.692 /// * Anyone if693 /// * Allow List is enabled, and694 /// * Address is added to allow list, and695 /// * MintPermission is enabled (see SetMintPermission method)696 ///697 /// # Arguments698 ///699 /// * collection_id: ID of the collection.700 ///701 /// * owner: Address, initial owner of the NFT.702 ///703 /// * data: Token data to store on chain.704 #[weight = <CommonWeights<T>>::create_item()]705 #[transactional]706 pub fn create_item(origin, collection_id: CollectionId, owner: T::CrossAccountId, data: CreateItemData) -> DispatchResultWithPostInfo {707 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);708709 dispatch_call::<T, _>(collection_id, |d| d.create_item(sender, owner, data))710 }711712 /// This method creates multiple items in a collection created with CreateCollection method.713 ///714 /// # Permissions715 ///716 /// * Collection Owner.717 /// * Collection Admin.718 /// * Anyone if719 /// * Allow List is enabled, and720 /// * Address is added to allow list, and721 /// * MintPermission is enabled (see SetMintPermission method)722 ///723 /// # Arguments724 ///725 /// * collection_id: ID of the collection.726 ///727 /// * itemsData: Array items properties. Each property is an array of bytes itself, see [create_item].728 ///729 /// * owner: Address, initial owner of the NFT.730 #[weight = <CommonWeights<T>>::create_multiple_items(items_data.len() as u32)]731 #[transactional]732 pub fn create_multiple_items(origin, collection_id: CollectionId, owner: T::CrossAccountId, items_data: Vec<CreateItemData>) -> DispatchResultWithPostInfo {733 ensure!(!items_data.is_empty(), Error::<T>::EmptyArgument);734 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);735736 dispatch_call::<T, _>(collection_id, |d| d.create_multiple_items(sender, owner, items_data))737 }738739 // TODO! transaction weight740741 /// Set transfers_enabled value for particular collection742 ///743 /// # Permissions744 ///745 /// * Collection Owner.746 ///747 /// # Arguments748 ///749 /// * collection_id: ID of the collection.750 ///751 /// * value: New flag value.752 #[weight = <SelfWeightOf<T>>::set_transfers_enabled_flag()]753 #[transactional]754 pub fn set_transfers_enabled_flag(origin, collection_id: CollectionId, value: bool) -> DispatchResult {755 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);756 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;757 target_collection.check_is_owner(&sender)?;758759 // =========760761 target_collection.limits.transfers_enabled = Some(value);762 target_collection.save()763 }764765 /// Destroys a concrete instance of NFT.766 ///767 /// # Permissions768 ///769 /// * Collection Owner.770 /// * Collection Admin.771 /// * Current NFT Owner.772 ///773 /// # Arguments774 ///775 /// * collection_id: ID of the collection.776 ///777 /// * item_id: ID of NFT to burn.778 #[weight = <CommonWeights<T>>::burn_item()]779 #[transactional]780 pub fn burn_item(origin, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {781 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);782783 let post_info = dispatch_call::<T, _>(collection_id, |d| d.burn_item(sender, item_id, value))?;784 if value == 1 {785 <NftTransferBasket<T>>::remove(collection_id, item_id);786 <NftApproveBasket<T>>::remove(collection_id, item_id);787 }788 // Those maps should be cleared only if token disappears completly, need to move this part of logic to pallets?789 // <FungibleApproveBasket<T>>::remove(collection_id, sender.as_sub());790 // <RefungibleApproveBasket<T>>::remove((collection_id, item_id, sender.as_sub()));791 Ok(post_info)792 }793794 /// Destroys a concrete instance of NFT on behalf of the owner795 /// See also: [`approve`]796 ///797 /// # Permissions798 ///799 /// * Collection Owner.800 /// * Collection Admin.801 /// * Current NFT Owner.802 ///803 /// # Arguments804 ///805 /// * collection_id: ID of the collection.806 ///807 /// * item_id: ID of NFT to burn.808 ///809 /// * from: owner of item810 #[weight = <CommonWeights<T>>::burn_from()]811 #[transactional]812 pub fn burn_from(origin, collection_id: CollectionId, from: T::CrossAccountId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {813 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);814815 dispatch_call::<T, _>(collection_id, |d| d.burn_from(sender, from, item_id, value))816 }817818 /// Change ownership of the token.819 ///820 /// # Permissions821 ///822 /// * Collection Owner823 /// * Collection Admin824 /// * Current NFT owner825 ///826 /// # Arguments827 ///828 /// * recipient: Address of token recipient.829 ///830 /// * collection_id.831 ///832 /// * item_id: ID of the item833 /// * Non-Fungible Mode: Required.834 /// * Fungible Mode: Ignored.835 /// * Re-Fungible Mode: Required.836 ///837 /// * value: Amount to transfer.838 /// * Non-Fungible Mode: Ignored839 /// * Fungible Mode: Must specify transferred amount840 /// * Re-Fungible Mode: Must specify transferred portion (between 0 and 1)841 #[weight = <CommonWeights<T>>::transfer()]842 #[transactional]843 pub fn transfer(origin, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128) -> DispatchResultWithPostInfo {844 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);845846 dispatch_call::<T, _>(collection_id, |d| d.transfer(sender, recipient, item_id, value))847 }848849 /// Set, change, or remove approved address to transfer the ownership of the NFT.850 ///851 /// # Permissions852 ///853 /// * Collection Owner854 /// * Collection Admin855 /// * Current NFT owner856 ///857 /// # Arguments858 ///859 /// * approved: Address that is approved to transfer this NFT or zero (if needed to remove approval).860 ///861 /// * collection_id.862 ///863 /// * item_id: ID of the item.864 #[weight = <CommonWeights<T>>::approve()]865 #[transactional]866 pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {867 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);868869 dispatch_call::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))870 }871872 /// Change ownership of a NFT on behalf of the owner. See Approve method for additional information. After this method executes, the approval is removed so that the approved address will not be able to transfer this NFT again from this owner.873 ///874 /// # Permissions875 /// * Collection Owner876 /// * Collection Admin877 /// * Current NFT owner878 /// * Address approved by current NFT owner879 ///880 /// # Arguments881 ///882 /// * from: Address that owns token.883 ///884 /// * recipient: Address of token recipient.885 ///886 /// * collection_id.887 ///888 /// * item_id: ID of the item.889 ///890 /// * value: Amount to transfer.891 #[weight = <CommonWeights<T>>::transfer_from()]892 #[transactional]893 pub fn transfer_from(origin, from: T::CrossAccountId, recipient: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, value: u128 ) -> DispatchResultWithPostInfo {894 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);895896 dispatch_call::<T, _>(collection_id, |d| d.transfer_from(sender, from, recipient, item_id, value))897 }898899 /// Set off-chain data schema.900 ///901 /// # Permissions902 ///903 /// * Collection Owner904 /// * Collection Admin905 ///906 /// # Arguments907 ///908 /// * collection_id.909 ///910 /// * schema: String representing the offchain data schema.911 #[weight = <CommonWeights<T>>::set_variable_metadata(data.len() as u32)]912 #[transactional]913 pub fn set_variable_meta_data (914 origin,915 collection_id: CollectionId,916 item_id: TokenId,917 data: BoundedVec<u8, CustomDataLimit>,918 ) -> DispatchResultWithPostInfo {919 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);920921 dispatch_call::<T, _>(collection_id, |d| d.set_variable_metadata(sender, item_id, data))922 }923924 /// Set meta_update_permission value for particular collection925 ///926 /// # Permissions927 ///928 /// * Collection Owner.929 ///930 /// # Arguments931 ///932 /// * collection_id: ID of the collection.933 ///934 /// * value: New flag value.935 #[weight = <SelfWeightOf<T>>::set_meta_update_permission_flag()]936 #[transactional]937 pub fn set_meta_update_permission_flag(origin, collection_id: CollectionId, value: MetaUpdatePermission) -> DispatchResult {938 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);939 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;940941 ensure!(942 target_collection.meta_update_permission != MetaUpdatePermission::None,943 <CommonError<T>>::MetadataFlagFrozen,944 );945 target_collection.check_is_owner(&sender)?;946947 target_collection.meta_update_permission = value;948949 target_collection.save()950 }951952 /// Set schema standard953 /// ImageURL954 /// Unique955 ///956 /// # Permissions957 ///958 /// * Collection Owner959 /// * Collection Admin960 ///961 /// # Arguments962 ///963 /// * collection_id.964 ///965 /// * schema: SchemaVersion: enum966 #[weight = <SelfWeightOf<T>>::set_schema_version()]967 #[transactional]968 pub fn set_schema_version(969 origin,970 collection_id: CollectionId,971 version: SchemaVersion972 ) -> DispatchResult {973 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);974 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;975 target_collection.check_is_owner_or_admin(&sender)?;976 target_collection.schema_version = version;977978 <Pallet<T>>::deposit_event(Event::<T>::SchemaVersionSet(979 collection_id980 ));981982 target_collection.save()983 }984985 /// Set off-chain data schema.986 ///987 /// # Permissions988 ///989 /// * Collection Owner990 /// * Collection Admin991 ///992 /// # Arguments993 ///994 /// * collection_id.995 ///996 /// * schema: String representing the offchain data schema.997 #[weight = <SelfWeightOf<T>>::set_offchain_schema(schema.len() as u32)]998 #[transactional]999 pub fn set_offchain_schema(1000 origin,1001 collection_id: CollectionId,1002 schema: BoundedVec<u8, ConstU32<OFFCHAIN_SCHEMA_LIMIT>>,1003 ) -> DispatchResult {1004 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1005 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1006 target_collection.check_is_owner_or_admin(&sender)?;10071008 target_collection.offchain_schema = schema;10091010 <Pallet<T>>::deposit_event(Event::<T>::OffchainSchemaSet(1011 collection_id1012 ));10131014 target_collection.save()1015 }10161017 /// Set const on-chain data schema.1018 ///1019 /// # Permissions1020 ///1021 /// * Collection Owner1022 /// * Collection Admin1023 ///1024 /// # Arguments1025 ///1026 /// * collection_id.1027 ///1028 /// * schema: String representing the const on-chain data schema.1029 #[weight = <SelfWeightOf<T>>::set_const_on_chain_schema(schema.len() as u32)]1030 #[transactional]1031 pub fn set_const_on_chain_schema (1032 origin,1033 collection_id: CollectionId,1034 schema: BoundedVec<u8, ConstU32<CONST_ON_CHAIN_SCHEMA_LIMIT>>1035 ) -> DispatchResult {1036 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1037 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1038 target_collection.check_is_owner_or_admin(&sender)?;10391040 target_collection.const_on_chain_schema = schema;10411042 <Pallet<T>>::deposit_event(Event::<T>::ConstOnChainSchemaSet(1043 collection_id1044 ));10451046 target_collection.save()1047 }10481049 /// Set variable on-chain data schema.1050 ///1051 /// # Permissions1052 ///1053 /// * Collection Owner1054 /// * Collection Admin1055 ///1056 /// # Arguments1057 ///1058 /// * collection_id.1059 ///1060 /// * schema: String representing the variable on-chain data schema.1061 #[weight = <SelfWeightOf<T>>::set_const_on_chain_schema(schema.len() as u32)]1062 #[transactional]1063 pub fn set_variable_on_chain_schema (1064 origin,1065 collection_id: CollectionId,1066 schema: BoundedVec<u8, ConstU32<VARIABLE_ON_CHAIN_SCHEMA_LIMIT>>1067 ) -> DispatchResult {1068 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1069 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1070 target_collection.check_is_owner_or_admin(&sender)?;10711072 target_collection.variable_on_chain_schema = schema;10731074 <Pallet<T>>::deposit_event(Event::<T>::VariableOnChainSchemaSet(1075 collection_id1076 ));10771078 target_collection.save()1079 }10801081 #[weight = <SelfWeightOf<T>>::set_collection_limits()]1082 #[transactional]1083 pub fn set_collection_limits(1084 origin,1085 collection_id: CollectionId,1086 new_limit: CollectionLimits,1087 ) -> DispatchResult {1088 let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);1089 let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;1090 target_collection.check_is_owner(&sender)?;1091 let old_limit = &target_collection.limits;10921093 target_collection.limits = <PalletCommon<T>>::clamp_limits(target_collection.mode.clone(), &old_limit, new_limit)?;10941095 <Pallet<T>>::deposit_event(Event::<T>::CollectionLimitSet(1096 collection_id1097 ));10981099 target_collection.save()1100 }1101 }1102}