From 0d8c1736ac580d04c7ac6f899b13a7f01521332f Mon Sep 17 00:00:00 2001 From: Dusan Morhac <55763425+dudo50@users.noreply.github.com> Date: Sat, 19 Oct 2024 17:37:38 +0200 Subject: [PATCH] Finish refactoring --- templates/parachain/pallets/xcnft/src/lib.rs | 1722 +++++++++++------- 1 file changed, 1060 insertions(+), 662 deletions(-) diff --git a/templates/parachain/pallets/xcnft/src/lib.rs b/templates/parachain/pallets/xcnft/src/lib.rs index c1c7050feb22..869c975fc3ae 100644 --- a/templates/parachain/pallets/xcnft/src/lib.rs +++ b/templates/parachain/pallets/xcnft/src/lib.rs @@ -1,5 +1,5 @@ //! # xcNFT Pallet by ParaSpell✨ Foundation team -//! +//! //! Pallet is made under [MIT](https://github.com/paraspell-research-foundation/xcNFT-Pallet/blob/main/LICENSE) license and is thereby free to use, modify, and distribute. //! //! A pallet that allows you to share your **Uniques** or **NFTs** across parachains. @@ -9,9 +9,12 @@ //! ## Overview //! //! This pallet consists of following functionalities: -//! - Transferring empty collection cross-chain: **collectionXtransfer** -//! - Transferring non-empty collection cross-chain (All NFTs are owned by collection owner): **collectionXtransfer** -//! - Transfering non-empty collection cross-chain (NFTs are distributed between different accounts): **collectionXtransfer** & **collectionXtransferVote** & **collectionXtransferInitiate** +//! - Transferring empty collection cross-chain: **collectionXtransfer** +//! - Transferring non-empty collection cross-chain (All NFTs are owned by collection owner): +//! **collectionXtransfer** +//! - Transfering non-empty collection cross-chain (NFTs are distributed between different +//! accounts): **collectionXtransfer** & **collectionXtransferVote** & +//! **collectionXtransferInitiate** //! - Transfering non-fungible assets cross-chain: **nftXtransfer** & **nftXclaim** //! - Updating collection metadata cross-chain: **collectionXupdate** //! - Updating non-fungible asset metadata cross-chain: **nftXupdate** @@ -21,30 +24,31 @@ //! - Transferring non-fungible asset ownership cross-chain: **nftXownership** //! //! Each function within pallet has its own weight and is defined in `weights.rs` file. -//! -//! Each function is also annotated with comments explaining the purpose and functionality design of the function. +//! +//! Each function is also annotated with comments explaining the purpose and functionality design of +//! the function. //! //! ## Dependencies //! This pallet depends on the following pallets: -//! +//! //! Substrate: //! - `frame-benchmarking` //! - `frame-support` //! - `frame-system` -//! +//! //! Cumulus: //! - `cumulus-primitives-core` //! - `cumulus-pallet-xcm` -//! +//! //! XCMP: //! - `xcm` -//! +//! //! SP: //! - `sp-runtime` //! - `sp-std` //! - `sp-core` //! - `sp-io` -//! +//! //! Substrate Pallets: //! - `pallet-nfts` //! - `pallet-uniques` @@ -64,33 +68,37 @@ mod tests; pub mod weights; #[cfg(feature = "runtime-benchmarks")] -mod benchmarking; - - +mod benchmarking; #[frame_support::pallet] pub mod pallet { -use frame_system::pallet_prelude::*; - use sp_runtime::{DispatchError, DispatchErrorWithPostInfo, traits::StaticLookup}; - use frame_support::{dispatch::DispatchResultWithPostInfo,dispatch::PostDispatchInfo,traits::Incrementable, pallet_prelude::*}; + use core::marker::PhantomData; use cumulus_primitives_core::ParaId; + use frame_support::{ + dispatch::{DispatchResultWithPostInfo, PostDispatchInfo}, + pallet_prelude::*, + traits::Incrementable, + }; + use frame_system::pallet_prelude::*; + use pallet_nfts::{CollectionConfigFor, DestroyWitness}; use scale_info::prelude::vec; + use sp_runtime::{traits::StaticLookup, DispatchError, DispatchErrorWithPostInfo}; use sp_std::prelude::*; use xcm::latest::prelude::*; - use pallet_nfts::{DestroyWitness, CollectionConfigFor}; - use core::marker::PhantomData; type AccountIdLookupOf = <::Lookup as StaticLookup>::Source; #[pallet::config] - pub trait Config: frame_system::Config + pallet_nfts::Config + parachain_info::Config { + pub trait Config: + frame_system::Config + pallet_nfts::Config + parachain_info::Config + { /// Because this pallet emits events, it depends on the runtime's definition of an event. - type RuntimeEvent: From> - + IsType<::RuntimeEvent>; + type RuntimeEvent: From> + + IsType<::RuntimeEvent>; /// The overarching call type; we assume sibling chains use the same type. - type RuntimeCall:From> + Encode; + type RuntimeCall: From> + Encode; /// The sender to use for cross-chain messages. type XcmSender: SendXcm; @@ -108,46 +116,42 @@ use frame_system::pallet_prelude::*; #[pallet::pallet] pub struct Pallet(PhantomData<(T, I)>); - /// Enum for voting, either Aye or Nay option. - #[derive( - Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default, Debug - )] + #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default, Debug)] #[scale_info(skip_type_params(T))] pub enum Vote { #[default] Aye, - Nay + Nay, } /// Struct for votes, contains two vectors, one for Aye voters and one for Nay voters. - #[derive( - Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default, Debug - )] - #[scale_info(skip_type_params(T,I))] + #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default, Debug)] + #[scale_info(skip_type_params(T, I))] pub struct Votes, I: 'static = ()> { aye: BoundedVec, nay: BoundedVec, } - /// Structure of proposal, contains proposal id, collection id, proposed collection owner, proposed destination parachain, proposed destination config, owners, number of votes, and end time. + /// Structure of proposal, contains proposal id, collection id, proposed collection owner, + /// proposed destination parachain, proposed destination config, owners, number of votes, and + /// end time. #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default, Debug)] - #[scale_info(skip_type_params(T, I))] + #[scale_info(skip_type_params(T, I))] pub struct Proposal, I: 'static = ()> { proposal_id: u64, collection_id: T::CollectionId, proposed_collection_owner: T::AccountId, proposed_destination_para: ParaId, - proposed_destination_config: CollectionConfigFor::, + proposed_destination_config: CollectionConfigFor, owners: BoundedVec, - number_of_votes: Votes, + number_of_votes: Votes, end_time: BlockNumberFor, } - /// Structure of sent assets, contains origin parachain id, origin collection id, origin asset id, destination collection id, and destination asset id. - #[derive( - Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default, - )] + /// Structure of sent assets, contains origin parachain id, origin collection id, origin asset + /// id, destination collection id, and destination asset id. + #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default)] #[scale_info(skip_type_params(T, I))] pub struct SentStruct, I: 'static = ()> { origin_para_id: ParaId, @@ -157,10 +161,9 @@ use frame_system::pallet_prelude::*; destination_asset_id: T::ItemId, } - /// Structure of received assets, contains origin parachain id, origin collection id, origin asset id, received collection id, and received asset id. - #[derive( - Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default, - )] + /// Structure of received assets, contains origin parachain id, origin collection id, origin + /// asset id, received collection id, and received asset id. + #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default)] #[scale_info(skip_type_params(T, I))] pub struct ReceivedStruct, I: 'static = ()> { origin_para_id: ParaId, @@ -170,10 +173,9 @@ use frame_system::pallet_prelude::*; received_asset_id: T::ItemId, } - /// Structure of received collections, contains origin parachain id, origin collection id, and received collection id. - #[derive( - Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default, - )] + /// Structure of received collections, contains origin parachain id, origin collection id, and + /// received collection id. + #[derive(Encode, Decode, MaxEncodedLen, TypeInfo, Clone, PartialEq, Default)] #[scale_info(skip_type_params(T, I))] pub struct ReceivedCols, I: 'static = ()> { origin_para_id: ParaId, @@ -181,50 +183,37 @@ use frame_system::pallet_prelude::*; received_collection_id: T::CollectionId, } - /// Storage for sent assets, contains origin collection id and origin asset id as tuple key and SentStruct as value. + /// Storage for sent assets, contains origin collection id and origin asset id as tuple key and + /// SentStruct as value. #[pallet::storage] #[pallet::getter(fn sent_assets)] - pub type SentAssets, I: 'static = ()> = StorageMap< - _, - Blake2_128Concat, - (T::CollectionId, T::ItemId), - SentStruct, - >; - - /// Storage for received assets, contains received collection id as tuple key and ReceivedStruct as value. + pub type SentAssets, I: 'static = ()> = + StorageMap<_, Blake2_128Concat, (T::CollectionId, T::ItemId), SentStruct>; + + /// Storage for received assets, contains received collection id as tuple key and ReceivedStruct + /// as value. #[pallet::storage] #[pallet::getter(fn received_assets)] - pub type ReceivedAssets, I: 'static = ()> = StorageMap< - _, - Blake2_128Concat, - (T::CollectionId, T::ItemId), - ReceivedStruct, - >; + pub type ReceivedAssets, I: 'static = ()> = + StorageMap<_, Blake2_128Concat, (T::CollectionId, T::ItemId), ReceivedStruct>; /// Storage for sent collections, contains origin collection id as key and SentCols as value. #[pallet::storage] #[pallet::getter(fn received_collections)] - pub type ReceivedCollections, I: 'static = ()> = StorageMap< - _, - Blake2_128Concat, - T::CollectionId, - ReceivedCols, - >; + pub type ReceivedCollections, I: 'static = ()> = + StorageMap<_, Blake2_128Concat, T::CollectionId, ReceivedCols>; /// Storage holding proposal ID, it is incremented each time a new proposal is created. #[pallet::storage] #[pallet::getter(fn next_proposal_id)] pub type NextProposalId, I: 'static = ()> = StorageValue<_, u64, ValueQuery>; - /// Storage for cross-chain proposals, contains proposal id as key and Proposal structure as value. + /// Storage for cross-chain proposals, contains proposal id as key and Proposal structure as + /// value. #[pallet::storage] #[pallet::getter(fn cross_chain_proposals)] - pub type CrossChainProposals, I: 'static = ()> = StorageMap< - _, - Blake2_128Concat, - u64, - Proposal, - >; + pub type CrossChainProposals, I: 'static = ()> = + StorageMap<_, Blake2_128Concat, u64, Proposal>; #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] @@ -243,10 +232,11 @@ use frame_system::pallet_prelude::*; destination_para_id: ParaId, }, - /// Event emited when a collection and its NFTs with different owners are transferred cross-chain. + /// Event emited when a collection and its NFTs with different owners are transferred + /// cross-chain. CollectionAndNFTsDiffTransferred { origin_collection_id: T::CollectionId, - nfts: Vec<(T::ItemId,AccountIdLookupOf, BoundedVec)>, + nfts: Vec<(T::ItemId, AccountIdLookupOf, BoundedVec)>, destination_para_id: ParaId, to_address: AccountIdLookupOf, }, @@ -260,13 +250,13 @@ use frame_system::pallet_prelude::*; }, /// Event emited when collection metadata update prompt is transferred cross-chain. - CollectionMetadataSent{ + CollectionMetadataSent { collection_id: T::CollectionId, proposed_data: BoundedVec, owner: T::AccountId, destination: ParaId, }, - + /// Event emited when cross-chain collection metadata update prompt transfer fails. CollectionMetadataFailedToXCM { e: SendError, @@ -284,9 +274,9 @@ use frame_system::pallet_prelude::*; owner: T::AccountId, destination: ParaId, }, - + /// Event emited when collection burn prompt is transferred cross-chain. - CollectionBurnSent{ + CollectionBurnSent { collection_id: T::CollectionId, burn_data: pallet_nfts::DestroyWitness, owner: T::AccountId, @@ -300,9 +290,9 @@ use frame_system::pallet_prelude::*; proposed_owner: AccountIdLookupOf, destination: ParaId, }, - + /// Event emited when collection ownership change prompt is transferred cross-chain. - CollectionOwnershipSent{ + CollectionOwnershipSent { collection_id: T::CollectionId, proposed_owner: AccountIdLookupOf, destination: ParaId, @@ -315,17 +305,15 @@ use frame_system::pallet_prelude::*; to_address: AccountIdLookupOf, }, - /// Event emited on destination chain, when collection with NFTs is already in received collections storage. - CollectionAlreadyReceived{ + /// Event emited on destination chain, when collection with NFTs is already in received + /// collections storage. + CollectionAlreadyReceived { origin_collection_id: T::CollectionId, to_address: AccountIdLookupOf, }, /// Event emited on destination chain, when empty collection fails to be created. - CollectionCreationFailed { - error: DispatchError, - owner: AccountIdLookupOf, - }, + CollectionCreationFailed { error: DispatchError, owner: AccountIdLookupOf }, /// Event emited on destination chain, when collection burn prompt fails to execute. CollectionBurnFailed { @@ -334,33 +322,38 @@ use frame_system::pallet_prelude::*; owner: AccountIdLookupOf, }, - /// Event emited on destination chain, when collection metadata update prompt fails to execute. + /// Event emited on destination chain, when collection metadata update prompt fails to + /// execute. CollectionMetadataSetFailed { error: DispatchError, collection_id: T::CollectionId, owner: AccountIdLookupOf, }, - /// Event emited on destination chain, when collection ownership change prompt fails to execute. + /// Event emited on destination chain, when collection ownership change prompt fails to + /// execute. CollectionOwnershipTransferFailed { error: DispatchError, collection_id: T::CollectionId, owner: AccountIdLookupOf, }, - /// Event emited on destination chain, when collection and its NFT are successfuly received. + /// Event emited on destination chain, when collection and its NFT are successfuly + /// received. CollectionWithNftsReceived { collection_id: T::CollectionId, items: Vec<(T::ItemId, BoundedVec)>, }, - /// Event emited on destination chain, when collection and its NFTs with different owners are successfuly received. + /// Event emited on destination chain, when collection and its NFTs with different owners + /// are successfuly received. CollectionWithNftsDiffOwnersReceived { collection_id: T::CollectionId, items: Vec<(T::ItemId, AccountIdLookupOf, BoundedVec)>, }, - /// Event emitted when collection cross-chain transfer proposal is created (Collection contains NFTs with different owners). + /// Event emitted when collection cross-chain transfer proposal is created (Collection + /// contains NFTs with different owners). CollectionTransferProposalCreated { proposal_id: u64, collection_id: T::CollectionId, @@ -369,21 +362,13 @@ use frame_system::pallet_prelude::*; }, /// Event emitted when a proposal vote is registered - CrossChainPropoposalVoteRegistered{ - proposal_id: u64, - voter: T::AccountId, - vote: Vote, - }, + CrossChainPropoposalVoteRegistered { proposal_id: u64, voter: T::AccountId, vote: Vote }, /// Event emitted when proposal expired - ProposalExpired { - proposal_id: u64, - }, + ProposalExpired { proposal_id: u64 }, /// Event emitted when proposal did not pass - ProposalDidNotPass { - proposal_id: u64, - }, + ProposalDidNotPass { proposal_id: u64 }, /// Event emitted when non-fungible asset is transferred cross-chain NFTTransferred { @@ -394,7 +379,8 @@ use frame_system::pallet_prelude::*; destination_asset_id: T::ItemId, }, - /// Event emitted when non-fungible asset is claimed (Its origin collection was sent cross-chain to same chain). + /// Event emitted when non-fungible asset is claimed (Its origin collection was sent + /// cross-chain to same chain). NFTClaimed { collection_claimed_from: T::CollectionId, asset_removed: T::ItemId, @@ -411,9 +397,9 @@ use frame_system::pallet_prelude::*; owner: T::AccountId, destination: ParaId, }, - + /// Event emitted when NFT metadata update prompt is transferred cross-chain. - NFTMetadataSent{ + NFTMetadataSent { collection_id: T::CollectionId, asset_id: T::ItemId, proposed_data: BoundedVec, @@ -429,9 +415,9 @@ use frame_system::pallet_prelude::*; owner: T::AccountId, destination: ParaId, }, - + /// Event emitted when NFT burn prompt is transferred cross-chain. - NFTBurnSent{ + NFTBurnSent { collection_id: T::CollectionId, asset_id: T::ItemId, owner: T::AccountId, @@ -446,9 +432,9 @@ use frame_system::pallet_prelude::*; proposed_owner: AccountIdLookupOf, destination: ParaId, }, - + /// Event emitted when NFT ownership change prompt is transferred cross-chain. - NFTOwnershipSent{ + NFTOwnershipSent { collection_id: T::CollectionId, asset_id: T::ItemId, proposed_owner: AccountIdLookupOf, @@ -487,7 +473,8 @@ use frame_system::pallet_prelude::*; owner: AccountIdLookupOf, }, - /// Event emitted on destination chain, when NFT is successfully received along with metadata if provided. + /// Event emitted on destination chain, when NFT is successfully received along with + /// metadata if provided. NFTReceived { origin_collection_id: T::CollectionId, origin_asset_id: T::ItemId, @@ -496,18 +483,20 @@ use frame_system::pallet_prelude::*; to_address: AccountIdLookupOf, }, - /// Event emitted on destination chain, when received NFT is NFT that was previously sent cross-chain. - NFTReturnedToOrigin{ + /// Event emitted on destination chain, when received NFT is NFT that was previously sent + /// cross-chain. + NFTReturnedToOrigin { returned_from_collection_id: T::CollectionId, returned_from_asset_id: T::ItemId, - to_address: T::AccountId + to_address: T::AccountId, }, + /// Event emitted when collection fails to mint on destination chain + CollectionMintFailed { error: DispatchError }, } #[pallet::error] pub enum Error { - /// Error returned when collection does not exist. CollectionDoesNotExist, @@ -529,7 +518,8 @@ use frame_system::pallet_prelude::*; /// Error returned when proposal is expired and couldn't be voted on anymore. ProposalExpired, - /// Error returned when proposal is still active, so cross-chain transfer cannot be initiated. + /// Error returned when proposal is still active, so cross-chain transfer cannot be + /// initiated. ProposalStillActive, /// Error returned when proposal does not exist. @@ -547,10 +537,11 @@ use frame_system::pallet_prelude::*; /// Error returned when user is not NFT owner. NotNFTOwner, - /// Error returned when NFT is not received, but user wants to claim it into different collection. + /// Error returned when NFT is not received, but user wants to claim it into different + /// collection. NFTNotReceived, - /// Error, that shouldn't happen. + /// Error, that shouldn't happen. NoNextCollectionId, /// Error returned when user enters wrong origin collection id. @@ -559,7 +550,6 @@ use frame_system::pallet_prelude::*; #[pallet::call] impl, I: 'static> Pallet { - /// Transfer a Collection along with its associated metadata / assets to another parachain. /// /// Origin must be Signed and the signing account must be : @@ -575,27 +565,43 @@ use frame_system::pallet_prelude::*; /// _ #[pallet::call_index(0)] #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] - pub fn collection_x_transfer(origin: OriginFor, origin_collection: T::CollectionId, destination_para: ParaId, config: CollectionConfigFor:: ) -> DispatchResultWithPostInfo { + pub fn collection_x_transfer( + origin: OriginFor, + origin_collection: T::CollectionId, + destination_para: ParaId, + config: CollectionConfigFor, + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin.clone())?; // See if collection exists - ensure!(pallet_nfts::Collection::::contains_key(&origin_collection), Error::::CollectionDoesNotExist); + ensure!( + pallet_nfts::Collection::::contains_key(&origin_collection), + Error::::CollectionDoesNotExist + ); // See if user owns the collection - let owner = pallet_nfts::Pallet::::collection_owner(origin_collection.clone()).ok_or(Error::::CollectionDoesNotExist)?; - ensure!(owner == who.clone(), Error::::NotCollectionOwner); + ensure!( + pallet_nfts::Pallet::::collection_owner(origin_collection.clone()) + .ok_or(Error::::CollectionDoesNotExist)? == + who.clone(), + Error::::NotCollectionOwner + ); // Retrieve collection item IDs let mut items = Vec::new(); - for (item_id, _item_details) in pallet_nfts::Item::::iter_prefix(&origin_collection) { + for (item_id, _item_details) in + pallet_nfts::Item::::iter_prefix(&origin_collection) + { items.push(item_id); } // First check if collection contains any metadata if it does, then save it let mut collection_metadata = None; - if pallet_nfts::CollectionMetadataOf::::contains_key(&origin_collection){ - collection_metadata = Some(pallet_nfts::CollectionMetadataOf::::get(origin_collection).unwrap().data); + if pallet_nfts::CollectionMetadataOf::::contains_key(&origin_collection) { + collection_metadata = Some( + pallet_nfts::CollectionMetadataOf::::get(origin_collection).unwrap().data, + ); } // If collection metadata is not present, then create empty metadata @@ -609,42 +615,42 @@ use frame_system::pallet_prelude::*; let mut bytes = [0u8; 32]; bytes.copy_from_slice(&account_vec); - // Check if the collection is empty (items array is empty) if items.is_empty() { - // Transfer the empty collection to the destination parachain match send_xcm::( (Parent, Junction::Parachain(destination_para.into())).into(), Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - AliasOrigin(xcm::latest::prelude::AccountId32 { id: bytes.into(), network: None }.into()), + AliasOrigin( + xcm::latest::prelude::AccountId32 { id: bytes.into(), network: None } + .into(), + ), Transact { origin_kind: OriginKind::SovereignAccount, require_weight_at_most: Weight::from_parts(1_000_000_000, 64 * 1024), - call: >::RuntimeCall::from(Call::< - T, - I, - >::parse_collection_empty { - origin_collection: origin_collection.clone(), - collection_metadata: collection_metadata.clone().unwrap(), - config, - }) + call: >::RuntimeCall::from( + Call::::parse_collection_empty { + origin_collection: origin_collection.clone(), + collection_metadata: collection_metadata.clone().unwrap(), + config, + }, + ) .encode() .into(), }, ]), ) { Ok((_hash, _cost)) => { - // If collection was received, remove from received collections if ReceivedCollections::::contains_key(&origin_collection) { ReceivedCollections::::remove(&origin_collection); } // Get collection from the storage - let collection = pallet_nfts::Collection::::get(origin_collection).unwrap(); - + let collection = + pallet_nfts::Collection::::get(origin_collection).unwrap(); + // Create destroy witness type let destroy_witness = DestroyWitness { item_metadatas: collection.clone().item_metadatas, @@ -653,8 +659,12 @@ use frame_system::pallet_prelude::*; }; // Burn the collection on origin chain - let _ = pallet_nfts::Pallet::::destroy(origin.clone(), origin_collection.clone(), destroy_witness); - + let _ = pallet_nfts::Pallet::::destroy( + origin.clone(), + origin_collection.clone(), + destroy_witness, + ); + // Emit an success event Self::deposit_event(Event::CollectionTransferred { origin_collection_id: origin_collection, @@ -669,16 +679,15 @@ use frame_system::pallet_prelude::*; destination: destination_para, }), } - } - else { - + } else { // Check if all the NFTs are owned by the same owner let collection_owner = who.clone(); for item_id in items.clone() { - if let Some(nft_owner) = pallet_nfts::Pallet::::owner(origin_collection, item_id) { + if let Some(nft_owner) = + pallet_nfts::Pallet::::owner(origin_collection, item_id) + { if nft_owner != collection_owner { - for (_data, proposal) in CrossChainProposals::::iter() { if proposal.collection_id == origin_collection { return Err(Error::::ProposalAlreadyExists.into()); @@ -687,14 +696,15 @@ use frame_system::pallet_prelude::*; // Find out how many different NFT owners does the collection have let mut different_owners = BoundedVec::new(); - + for item_id in items.clone() { - if let Some(nft_owner) = pallet_nfts::Pallet::::owner(origin_collection, item_id) { + if let Some(nft_owner) = + pallet_nfts::Pallet::::owner(origin_collection, item_id) + { if nft_owner != collection_owner { - // Check if owner is not present in different owners if !different_owners.contains(&nft_owner) { - different_owners.try_push(nft_owner).ok(); + different_owners.try_push(nft_owner).ok(); } } } @@ -707,16 +717,17 @@ use frame_system::pallet_prelude::*; if proposal_id == 0 { NextProposalId::::put(1); - }else if proposal_id == u64::MAX { + } else if proposal_id == u64::MAX { NextProposalId::::put(1); - }else { + } else { NextProposalId::::put(proposal_id + 1); } - let block_n: BlockNumberFor = frame_system::Pallet::::block_number(); + let block_n: BlockNumberFor = + frame_system::Pallet::::block_number(); let proposal = Proposal:: { - proposal_id: proposal_id, + proposal_id, collection_id: origin_collection, proposed_collection_owner: who.clone(), proposed_destination_config: config, @@ -729,25 +740,29 @@ use frame_system::pallet_prelude::*; end_time: block_n + T::ProposalTimeInBlocks::get().into(), }; - >::insert(proposal_id,proposal); + >::insert(proposal_id, proposal); Self::deposit_event(Event::CollectionTransferProposalCreated { - proposal_id: proposal_id, + proposal_id, collection_id: origin_collection, proposer: who.clone(), - destination: destination_para, + destination: destination_para, }); return Ok(().into()); - } + } } } // We get there, because collection owner is the same as NFT owners let mut collection_metadata = None; - - if pallet_nfts::CollectionMetadataOf::::contains_key(&origin_collection){ - collection_metadata = Some(pallet_nfts::CollectionMetadataOf::::get(origin_collection).unwrap().data); + + if pallet_nfts::CollectionMetadataOf::::contains_key(&origin_collection) { + collection_metadata = Some( + pallet_nfts::CollectionMetadataOf::::get(origin_collection) + .unwrap() + .data, + ); } if collection_metadata.is_none() { @@ -757,41 +772,49 @@ use frame_system::pallet_prelude::*; // Get NFT configs let mut nft_metadata = Vec::new(); for item_id in items.clone() { - if pallet_nfts::ItemMetadataOf::::contains_key(&origin_collection, item_id) { - let item_details = pallet_nfts::ItemMetadataOf::::get(origin_collection, item_id).unwrap().data; - nft_metadata.push((item_id,item_details)); - }else{ + if pallet_nfts::ItemMetadataOf::::contains_key( + &origin_collection, + item_id, + ) { + let item_details = + pallet_nfts::ItemMetadataOf::::get(origin_collection, item_id) + .unwrap() + .data; + nft_metadata.push((item_id, item_details)); + } else { // Add empty metadata nft_metadata.push((item_id, BoundedVec::new())); } } - // Send the collection and nfts along with associated metadata to the destination parachain + // Send the collection and nfts along with associated metadata to the destination + // parachain match send_xcm::( (Parent, Junction::Parachain(destination_para.into())).into(), Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - AliasOrigin(xcm::latest::prelude::AccountId32 { id: bytes.into(), network: None }.into()), + AliasOrigin( + xcm::latest::prelude::AccountId32 { id: bytes.into(), network: None } + .into(), + ), Transact { origin_kind: OriginKind::SovereignAccount, require_weight_at_most: Weight::from_parts(1_000_000_000, 64 * 1024), - call: >::RuntimeCall::from(Call::< - T, - I, - >::parse_collection_same_owner { - config, - origin_collection_id: origin_collection.clone(), - origin_para: parachain_info::Pallet::::parachain_id(), - collection_metadata: collection_metadata.unwrap(), - nfts: nft_metadata, - }) + call: >::RuntimeCall::from( + Call::::parse_collection_same_owner { + config, + origin_collection_id: origin_collection.clone(), + origin_para: parachain_info::Pallet::::parachain_id(), + collection_metadata: collection_metadata.unwrap(), + nfts: nft_metadata, + }, + ) .encode() .into(), }, ]), ) { Ok((_hash, _cost)) => { - // If collection was received, remove from received collections if ReceivedCollections::::contains_key(&origin_collection) { ReceivedCollections::::remove(&origin_collection); @@ -799,12 +822,17 @@ use frame_system::pallet_prelude::*; // Burning the NFTs for item_id in items.clone() { - let _ = pallet_nfts::Pallet::::burn(origin.clone(), origin_collection.clone(), item_id); + let _ = pallet_nfts::Pallet::::burn( + origin.clone(), + origin_collection.clone(), + item_id, + ); } // Get collection from the storage - let collection = pallet_nfts::Collection::::get(origin_collection).unwrap(); - + let collection = + pallet_nfts::Collection::::get(origin_collection).unwrap(); + // Create destroy witness type let destroy_witness = DestroyWitness { item_metadatas: collection.clone().item_metadatas, @@ -813,7 +841,11 @@ use frame_system::pallet_prelude::*; }; // Burning the collection - let _ = pallet_nfts::Pallet::::destroy(origin.clone(), origin_collection.clone(), destroy_witness); + let _ = pallet_nfts::Pallet::::destroy( + origin.clone(), + origin_collection.clone(), + destroy_witness, + ); // Emit a success event Self::deposit_event(Event::CollectionAndNFTsTransferred { @@ -829,7 +861,6 @@ use frame_system::pallet_prelude::*; destination: destination_para, }), } - } Ok(().into()) } @@ -844,14 +875,20 @@ use frame_system::pallet_prelude::*; /// - `actual_vote`: Enum type - either Aye or Nay. /// /// On success emits `CrossChainPropoposalVoteRegistered`. - /// #[pallet::call_index(1)] #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] - pub fn collection_x_transfer_vote(origin: OriginFor, proposal_id: u64, actual_vote: Vote) -> DispatchResultWithPostInfo { + pub fn collection_x_transfer_vote( + origin: OriginFor, + proposal_id: u64, + actual_vote: Vote, + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; // Check if proposal exists - ensure!(CrossChainProposals::::contains_key(proposal_id), Error::::ProposalDoesNotExist); + ensure!( + CrossChainProposals::::contains_key(proposal_id), + Error::::ProposalDoesNotExist + ); // Get the proposal let mut unwrapped_proposal = CrossChainProposals::::get(proposal_id).unwrap(); @@ -863,49 +900,66 @@ use frame_system::pallet_prelude::*; let block_n: BlockNumberFor = frame_system::Pallet::::block_number(); if block_n > unwrapped_proposal.end_time { - let number_of_votes = &unwrapped_proposal.number_of_votes.aye.len() + &unwrapped_proposal.number_of_votes.nay.len(); - - // If proposal did not pass (Less than 50% of votes are aye) remove proposal from storage and emit event. - if unwrapped_proposal.number_of_votes.aye.len() < number_of_votes / 2 || unwrapped_proposal.number_of_votes.aye.len() == 0 && unwrapped_proposal.number_of_votes.nay.len() == 0 { - + let number_of_votes = &unwrapped_proposal.number_of_votes.aye.len() + + &unwrapped_proposal.number_of_votes.nay.len(); + + // If proposal did not pass (Less than 50% of votes are aye) remove proposal from + // storage and emit event. + if unwrapped_proposal.number_of_votes.aye.len() < number_of_votes / 2 || + unwrapped_proposal.number_of_votes.aye.len() == 0 && + unwrapped_proposal.number_of_votes.nay.len() == 0 + { CrossChainProposals::::remove(proposal_id); - Self::deposit_event(Event::ProposalDidNotPass { - proposal_id: proposal_id, - }); + Self::deposit_event(Event::ProposalDidNotPass { proposal_id }); return Ok(().into()); } CrossChainProposals::::remove(proposal_id); - Self::deposit_event(Event::ProposalExpired { - proposal_id: proposal_id, - }); + Self::deposit_event(Event::ProposalExpired { proposal_id }); return Ok(().into()); } - // Check if the user has already voted, if they did, see if they voted the same or different. If same, return error and if different, update the vote + // Check if the user has already voted, if they did, see if they voted the same or + // different. If same, return error and if different, update the vote if unwrapped_proposal.number_of_votes.aye.contains(&who) { if actual_vote == Vote::Nay { unwrapped_proposal.number_of_votes.aye.retain(|x| x != &who); - unwrapped_proposal.number_of_votes.nay.try_push(who.clone()).map_err(|_| Error::::MaxOwnersReached)?; + unwrapped_proposal + .number_of_votes + .nay + .try_push(who.clone()) + .map_err(|_| Error::::MaxOwnersReached)?; } else { return Err(Error::::AlreadyVotedThis.into()); } } else if unwrapped_proposal.number_of_votes.nay.contains(&who) { if actual_vote == Vote::Aye { unwrapped_proposal.number_of_votes.nay.retain(|x| x != &who); - unwrapped_proposal.number_of_votes.aye.try_push(who.clone()).map_err(|_| Error::::MaxOwnersReached)?; + unwrapped_proposal + .number_of_votes + .aye + .try_push(who.clone()) + .map_err(|_| Error::::MaxOwnersReached)?; } else { return Err(Error::::AlreadyVotedThis.into()); } } else { if actual_vote == Vote::Aye { - unwrapped_proposal.number_of_votes.aye.try_push(who.clone()).map_err(|_| Error::::MaxOwnersReached)?; + unwrapped_proposal + .number_of_votes + .aye + .try_push(who.clone()) + .map_err(|_| Error::::MaxOwnersReached)?; } else { - unwrapped_proposal.number_of_votes.nay.try_push(who.clone()).map_err(|_| Error::::MaxOwnersReached)?; + unwrapped_proposal + .number_of_votes + .nay + .try_push(who.clone()) + .map_err(|_| Error::::MaxOwnersReached)?; } } @@ -914,7 +968,7 @@ use frame_system::pallet_prelude::*; //Emit a success event Self::deposit_event(Event::CrossChainPropoposalVoteRegistered { - proposal_id: proposal_id, + proposal_id, voter: who.clone(), vote: actual_vote, }); @@ -922,11 +976,12 @@ use frame_system::pallet_prelude::*; Ok(().into()) } - /// Transfer a Collection along with its associated metadata & assets owned by different owners to another parachain. + /// Transfer a Collection along with its associated metadata & assets owned by different + /// owners to another parachain. /// /// Origin must be Signed and the signing account must be : /// - the Owner of the `Collection`; - /// + /// /// Prereqiuisites: /// - Collection must be associated with proposal that has passed. /// @@ -934,20 +989,29 @@ use frame_system::pallet_prelude::*; /// - `proposal_id`: The cross-chain proposal ID. /// /// On success emits `CollectionAndNFTsDiffTransferred`. - /// #[pallet::call_index(2)] #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] - pub fn collection_x_transfer_initiate(origin: OriginFor, proposal_id: u64) -> DispatchResultWithPostInfo{ + pub fn collection_x_transfer_initiate( + origin: OriginFor, + proposal_id: u64, + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin.clone())?; - + // Check if proposal exists - ensure!(CrossChainProposals::::contains_key(proposal_id), Error::::ProposalDoesNotExist); - + ensure!( + CrossChainProposals::::contains_key(proposal_id), + Error::::ProposalDoesNotExist + ); + //Check if owner of the collection is the one who initiated the transfer let proposal = CrossChainProposals::::get(proposal_id).unwrap(); - - let owner = pallet_nfts::Pallet::::collection_owner(proposal.collection_id.clone()).ok_or(Error::::CollectionDoesNotExist)?; - ensure!(owner == who.clone(), Error::::NotCollectionOwner); + + ensure!( + pallet_nfts::Pallet::::collection_owner(proposal.collection_id.clone()) + .ok_or(Error::::CollectionDoesNotExist)? == + who.clone(), + Error::::NotCollectionOwner + ); // Check if the proposal is active or not let block_n: BlockNumberFor = frame_system::Pallet::::block_number(); @@ -957,53 +1021,77 @@ use frame_system::pallet_prelude::*; } // Check if the proposal passed - let number_of_votes = proposal.number_of_votes.aye.len() + proposal.number_of_votes.nay.len(); - - if proposal.number_of_votes.aye.len() < number_of_votes / 2 || proposal.number_of_votes.aye.len() == 0 && proposal.number_of_votes.nay.len() == 0 { + let number_of_votes = + proposal.number_of_votes.aye.len() + proposal.number_of_votes.nay.len(); - Self::deposit_event(Event::ProposalDidNotPass { - proposal_id: proposal_id, - }); + if proposal.number_of_votes.aye.len() < number_of_votes / 2 || + proposal.number_of_votes.aye.len() == 0 && + proposal.number_of_votes.nay.len() == 0 + { + Self::deposit_event(Event::ProposalDidNotPass { proposal_id }); // Remove the proposal CrossChainProposals::::remove(proposal_id); return Ok(().into()); - - }else if proposal.number_of_votes.aye.len() >= number_of_votes / 2 { - + } else if proposal.number_of_votes.aye.len() >= number_of_votes / 2 { // Get the collection metadata let mut collection_metadata = Some(BoundedVec::new()); - - if pallet_nfts::CollectionMetadataOf::::contains_key(proposal.collection_id.clone()){ - collection_metadata = Some(pallet_nfts::CollectionMetadataOf::::get(proposal.collection_id.clone()).unwrap().data); + + if pallet_nfts::CollectionMetadataOf::::contains_key( + proposal.collection_id.clone(), + ) { + collection_metadata = Some( + pallet_nfts::CollectionMetadataOf::::get( + proposal.collection_id.clone(), + ) + .unwrap() + .data, + ); } // Get NFT metadata let mut nft_metadata = Vec::new(); let mut items = Vec::new(); - for (item_id, _item_details) in pallet_nfts::Item::::iter_prefix(proposal.collection_id.clone()) { + for (item_id, _item_details) in + pallet_nfts::Item::::iter_prefix(proposal.collection_id.clone()) + { items.push(item_id); } if items.is_empty() { - // Remove the proposal CrossChainProposals::::remove(proposal_id); - // Transfer through regular transfer function again, because there are no NFTs in the collection - Self::collection_x_transfer(origin.clone(), proposal.collection_id, proposal.proposed_destination_para, proposal.proposed_destination_config.clone())?; + // Transfer through regular transfer function again, because there are no NFTs + // in the collection + Self::collection_x_transfer( + origin.clone(), + proposal.collection_id, + proposal.proposed_destination_para, + proposal.proposed_destination_config.clone(), + )?; } for item_id in items.clone() { - let nft_owner = pallet_nfts::Pallet::::owner(proposal.collection_id.clone(), item_id).unwrap(); + let nft_owner = + pallet_nfts::Pallet::::owner(proposal.collection_id.clone(), item_id) + .unwrap(); let unlooked_recipient = T::Lookup::unlookup(nft_owner.clone()); - - if pallet_nfts::ItemMetadataOf::::contains_key(proposal.collection_id.clone(), item_id) { - let item_details = pallet_nfts::ItemMetadataOf::::get(proposal.collection_id.clone(), item_id).unwrap().data; - nft_metadata.push((item_id,unlooked_recipient.clone(), item_details)); - }else{ + + if pallet_nfts::ItemMetadataOf::::contains_key( + proposal.collection_id.clone(), + item_id, + ) { + let item_details = pallet_nfts::ItemMetadataOf::::get( + proposal.collection_id.clone(), + item_id, + ) + .unwrap() + .data; + nft_metadata.push((item_id, unlooked_recipient.clone(), item_details)); + } else { // Add empty metadata nft_metadata.push((item_id, unlooked_recipient.clone(), BoundedVec::new())); } @@ -1024,46 +1112,57 @@ use frame_system::pallet_prelude::*; (Parent, Junction::Parachain(destination.into())).into(), Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - AliasOrigin(xcm::latest::prelude::AccountId32 { id: bytes.into(), network: None }.into()), + AliasOrigin( + xcm::latest::prelude::AccountId32 { id: bytes.into(), network: None } + .into(), + ), Transact { origin_kind: OriginKind::SovereignAccount, require_weight_at_most: Weight::from_parts(1_000_000_000, 64 * 1024), - call: >::RuntimeCall::from(Call::< - T, - I, - >::parse_collection_diff_owners { - config, - origin_collection_id: proposal.collection_id.clone(), - origin_para: parachain_info::Pallet::::parachain_id(), - collection_metadata: collection_metadata.unwrap(), - nfts: nft_metadata.clone(), - }) + call: >::RuntimeCall::from( + Call::::parse_collection_diff_owners { + config, + origin_collection_id: proposal.collection_id.clone(), + origin_para: parachain_info::Pallet::::parachain_id(), + collection_metadata: collection_metadata.unwrap(), + nfts: nft_metadata.clone(), + }, + ) .encode() .into(), }, ]), ) { Ok((_hash, _cost)) => { - // If collection was received, remove from received collections - if ReceivedCollections::::contains_key(proposal.collection_id.clone()) { + if ReceivedCollections::::contains_key(proposal.collection_id.clone()) + { ReceivedCollections::::remove(proposal.collection_id.clone()); } // Burning the NFTs for item_id in items.clone() { - //Get NFT owner - let nft_owner = pallet_nfts::Pallet::::owner(proposal.collection_id.clone(), item_id).unwrap(); - let signed_nft_owner: OriginFor = frame_system::RawOrigin::Signed(nft_owner.clone()).into(); - - //Burn the NFT - let _ = pallet_nfts::Pallet::::burn(signed_nft_owner, proposal.collection_id.clone(), item_id); + let nft_owner = pallet_nfts::Pallet::::owner( + proposal.collection_id.clone(), + item_id, + ) + .unwrap(); + let signed_nft_owner: OriginFor = + frame_system::RawOrigin::Signed(nft_owner.clone()).into(); + //Burn the NFT + let _ = pallet_nfts::Pallet::::burn( + signed_nft_owner, + proposal.collection_id.clone(), + item_id, + ); } //Burning the collection - let collection = pallet_nfts::Collection::::get(proposal.collection_id.clone()).unwrap(); + let collection = + pallet_nfts::Collection::::get(proposal.collection_id.clone()) + .unwrap(); let destroy_witness = DestroyWitness { item_metadatas: collection.clone().item_metadatas, @@ -1071,7 +1170,11 @@ use frame_system::pallet_prelude::*; attributes: collection.attributes, }; - let _ = pallet_nfts::Pallet::::destroy(origin.clone(), proposal.collection_id.clone(), destroy_witness); + let _ = pallet_nfts::Pallet::::destroy( + origin.clone(), + proposal.collection_id.clone(), + destroy_witness, + ); // Remove proposal from proposals CrossChainProposals::::remove(proposal_id); @@ -1092,9 +1195,9 @@ use frame_system::pallet_prelude::*; }), } } - + Ok(().into()) - } + } /// Transfer an asset along with associated metadata to another parachain. /// @@ -1105,36 +1208,55 @@ use frame_system::pallet_prelude::*; /// - `origin_collection`: The collection_id of the collection to be transferred. /// - `origin_asset`: The asset_id of the asset to be transferred. /// - `destination_para`: The destination chain ID to which collection is transferred. - /// - `destination_collection`: The collection_id of the collection that the asset have to be received into. + /// - `destination_collection`: The collection_id of the collection that the asset have to + /// be received into. /// - `destination_asset`: The asset_id of the asset to be received. /// /// On success emits `NFTTransferred`. - /// #[pallet::call_index(3)] #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] - pub fn nft_x_transfer(origin: OriginFor, origin_collection: T::CollectionId, origin_asset: T::ItemId, destination_para: ParaId, destination_collection: T::CollectionId, destination_asset: T::ItemId ) -> DispatchResultWithPostInfo { + pub fn nft_x_transfer( + origin: OriginFor, + origin_collection: T::CollectionId, + origin_asset: T::ItemId, + destination_para: ParaId, + destination_collection: T::CollectionId, + destination_asset: T::ItemId, + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin.clone())?; // See if collection exists - ensure!(pallet_nfts::Collection::::contains_key(&origin_collection), Error::::CollectionDoesNotExist); + ensure!( + pallet_nfts::Collection::::contains_key(&origin_collection), + Error::::CollectionDoesNotExist + ); // See if item exists - ensure!(pallet_nfts::Item::::contains_key(&origin_collection, &origin_asset), Error::::NFTDoesNotExist); + ensure!( + pallet_nfts::Item::::contains_key(&origin_collection, &origin_asset), + Error::::NFTDoesNotExist + ); // See if user owns the item - let owner = pallet_nfts::Pallet::::owner(origin_collection.clone(), origin_asset.clone()).ok_or(Error::::NFTDoesNotExist)?; - ensure!(owner == who.clone(), Error::::NotNFTOwner); + ensure!( + pallet_nfts::Pallet::::owner(origin_collection.clone(), origin_asset.clone()) + .ok_or(Error::::NFTDoesNotExist)? == + who.clone(), + Error::::NotNFTOwner + ); // Get Item data - let mut metadata = None; - - if pallet_nfts::ItemMetadataOf::::contains_key(&origin_collection, &origin_asset) { - metadata = pallet_nfts::ItemMetadataOf::::get(origin_collection.clone(), origin_asset.clone()).map(|i| i.data); - }else { - metadata = Some(BoundedVec::new()); + let mut metadata = Some(BoundedVec::new()); + + if pallet_nfts::ItemMetadataOf::::contains_key(&origin_collection, &origin_asset) + { + metadata = pallet_nfts::ItemMetadataOf::::get( + origin_collection.clone(), + origin_asset.clone(), + ) + .map(|i| i.data); } - // Convert accountId into accountid32 let account_vec = who.encode(); ensure!(account_vec.len() == 32, "AccountId must be 32 bytes."); @@ -1146,32 +1268,39 @@ use frame_system::pallet_prelude::*; (Parent, Junction::Parachain(destination_para.into())).into(), Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - AliasOrigin(xcm::latest::prelude::AccountId32 { id: bytes.into(), network: None }.into()), + AliasOrigin( + xcm::latest::prelude::AccountId32 { id: bytes.into(), network: None } + .into(), + ), Transact { origin_kind: OriginKind::SovereignAccount, require_weight_at_most: Weight::from_parts(1_000_000_000, 64 * 1024), - call: >::RuntimeCall::from(Call::< - T, - I, - >::parse_nft_transfer { - origin_collection: origin_collection.clone(), - origin_item: origin_asset.clone(), - collection: destination_collection.clone(), - item: destination_asset.clone(), - data: metadata.unwrap(), - origin_chain: parachain_info::Pallet::::parachain_id(), - }) + call: >::RuntimeCall::from( + Call::::parse_nft_transfer { + origin_collection: origin_collection.clone(), + origin_item: origin_asset.clone(), + collection: destination_collection.clone(), + item: destination_asset.clone(), + data: metadata.unwrap(), + origin_chain: parachain_info::Pallet::::parachain_id(), + }, + ) .encode() .into(), }, ]), ) { Ok((_hash, _cost)) => { - - // If in received list, burn asset and remove from received list - if ReceivedAssets::::contains_key(&(origin_collection.clone(), origin_asset.clone())) { - - let received = ReceivedAssets::::get(&(origin_collection.clone(), origin_asset.clone())).unwrap(); + // If in received list, burn asset and remove from received list + if ReceivedAssets::::contains_key(&( + origin_collection.clone(), + origin_asset.clone(), + )) { + let received = ReceivedAssets::::get(&( + origin_collection.clone(), + origin_asset.clone(), + )) + .unwrap(); SentAssets::::insert( (origin_collection.clone(), origin_asset.clone()), @@ -1185,27 +1314,43 @@ use frame_system::pallet_prelude::*; ); // Remove from received assets - ReceivedAssets::::remove(&(origin_collection.clone(), origin_asset.clone())); + ReceivedAssets::::remove(&( + origin_collection.clone(), + origin_asset.clone(), + )); // Burn the asset - pallet_nfts::Pallet::::burn(origin.clone(), origin_collection.clone(), origin_asset.clone()); + let _ = pallet_nfts::Pallet::::burn( + origin.clone(), + origin_collection.clone(), + origin_asset.clone(), + ); } - //Only remove asset metadata, because we are sending from origin chain - else{ - - let col_owner = pallet_nfts::Pallet::::collection_owner(origin_collection.clone()).unwrap(); - let signed_col: OriginFor = frame_system::RawOrigin::Signed(col_owner.clone()).into(); - - pallet_nfts::Pallet::::clear_metadata(signed_col.clone(), origin_collection.clone(), origin_asset.clone()); - - SentAssets::::insert((origin_collection.clone(), origin_asset.clone()), SentStruct { - origin_para_id:parachain_info::Pallet::::parachain_id(), - origin_collection_id: origin_collection.clone(), - origin_asset_id: origin_asset.clone(), - destination_collection_id: destination_collection.clone(), - destination_asset_id: destination_asset.clone(), - }); + else { + let col_owner = pallet_nfts::Pallet::::collection_owner( + origin_collection.clone(), + ) + .unwrap(); + let signed_col: OriginFor = + frame_system::RawOrigin::Signed(col_owner.clone()).into(); + + let _ = pallet_nfts::Pallet::::clear_metadata( + signed_col.clone(), + origin_collection.clone(), + origin_asset.clone(), + ); + + SentAssets::::insert( + (origin_collection.clone(), origin_asset.clone()), + SentStruct { + origin_para_id: parachain_info::Pallet::::parachain_id(), + origin_collection_id: origin_collection.clone(), + origin_asset_id: origin_asset.clone(), + destination_collection_id: destination_collection.clone(), + destination_asset_id: destination_asset.clone(), + }, + ); } //Emit a success event Self::deposit_event(Event::NFTTransferred { @@ -1226,62 +1371,127 @@ use frame_system::pallet_prelude::*; Ok(().into()) } - - /// Claim cross-chain sent asset if its origin collection was also sent to same destination chain. + /// Claim cross-chain sent asset if its origin collection was also sent to same destination + /// chain. /// /// Origin must be Signed and the signing account must be : - /// - the Owner of the asset in the `Current collection` and owner of the asset in the `Origin collection`; + /// - the Owner of the asset in the `Current collection` and owner of the asset in the + /// `Origin collection`; /// /// Arguments: - /// - `origin_collection_at_destination`: The collection_id at the destination of the collection that was transferred (Id it has at destination chain). - /// - `origin_collection_at_origin`: The origin collection_id of the collection that was transferred (Id it had at origin chain). - /// - `origin_asset_at_destination`: The origin asset id at the origin collection that is delivered. - /// - `current_collection`: The collection_id of the collection that the asset have been delivered into. + /// - `origin_collection_at_destination`: The collection_id at the destination of the + /// collection that was transferred (Id it has at destination chain). + /// - `origin_collection_at_origin`: The origin collection_id of the collection that was + /// transferred (Id it had at origin chain). + /// - `origin_asset_at_destination`: The origin asset id at the origin collection that is + /// delivered. + /// - `current_collection`: The collection_id of the collection that the asset have been + /// delivered into. /// - `current_asset`: The current asset_id of the asset in current collection. /// /// On success emits `NFTClaimed`. - /// #[pallet::call_index(4)] #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] - pub fn nft_x_claim(origin: OriginFor, origin_collection_at_destination: T::CollectionId, origin_collection_at_origin: T::CollectionId, origin_asset_at_destination: T::ItemId, current_collection: T::CollectionId ,current_asset: T::ItemId) -> DispatchResultWithPostInfo { + pub fn nft_x_claim( + origin: OriginFor, + origin_collection_at_destination: T::CollectionId, + origin_collection_at_origin: T::CollectionId, + origin_asset_at_destination: T::ItemId, + current_collection: T::CollectionId, + current_asset: T::ItemId, + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin.clone())?; // See if collection exists - ensure!(pallet_nfts::Collection::::contains_key(¤t_collection), Error::::CollectionDoesNotExist); + ensure!( + pallet_nfts::Collection::::contains_key(¤t_collection), + Error::::CollectionDoesNotExist + ); // See if origin collection exists - ensure!(pallet_nfts::Collection::::contains_key(&origin_collection_at_destination), Error::::CollectionDoesNotExist); + ensure!( + pallet_nfts::Collection::::contains_key(&origin_collection_at_destination), + Error::::CollectionDoesNotExist + ); // See if origin collection at origin is the same as in received collection - ensure!(ReceivedCollections::::get(&origin_collection_at_destination).unwrap().origin_collection_id == origin_collection_at_origin, Error::::WrongOriginCollectionAtOrigin); + ensure!( + ReceivedCollections::::get(&origin_collection_at_destination) + .unwrap() + .origin_collection_id == + origin_collection_at_origin, + Error::::WrongOriginCollectionAtOrigin + ); // See if current asset is in received assets - ensure!(ReceivedAssets::::contains_key(&(current_collection.clone(), current_asset.clone())), Error::::NFTNotReceived); + ensure!( + ReceivedAssets::::contains_key(&( + current_collection.clone(), + current_asset.clone() + )), + Error::::NFTNotReceived + ); // See if item in origin collection exists - ensure!(pallet_nfts::Item::::contains_key(&origin_collection_at_destination, &origin_asset_at_destination), Error::::NFTDoesNotExist); + ensure!( + pallet_nfts::Item::::contains_key( + &origin_collection_at_destination, + &origin_asset_at_destination + ), + Error::::NFTDoesNotExist + ); // See if user owns the item - ensure!(pallet_nfts::Pallet::::owner(origin_collection_at_destination.clone(), origin_asset_at_destination.clone()).ok_or(Error::::NFTDoesNotExist)? == who.clone(), Error::::NotNFTOwner); + ensure!( + pallet_nfts::Pallet::::owner( + origin_collection_at_destination.clone(), + origin_asset_at_destination.clone() + ) + .ok_or(Error::::NFTDoesNotExist)? == + who.clone(), + Error::::NotNFTOwner + ); // See if user owns the current asset - ensure!(pallet_nfts::Pallet::::owner(current_collection.clone(), current_asset.clone()).ok_or(Error::::NFTDoesNotExist)? == who.clone(), Error::::NotNFTOwner); + ensure!( + pallet_nfts::Pallet::::owner( + current_collection.clone(), + current_asset.clone() + ) + .ok_or(Error::::NFTDoesNotExist)? == + who.clone(), + Error::::NotNFTOwner + ); // Claim the asset - let mut metadata = None; - - if pallet_nfts::ItemMetadataOf::::contains_key(current_collection.clone(), current_asset.clone()) { - metadata = pallet_nfts::ItemMetadataOf::::get(current_collection.clone(), current_asset.clone()).map(|i| i.data); - }else{ - metadata = Some(BoundedVec::new()); + let mut metadata = Some(BoundedVec::new()); + + if pallet_nfts::ItemMetadataOf::::contains_key( + current_collection.clone(), + current_asset.clone(), + ) { + metadata = pallet_nfts::ItemMetadataOf::::get( + current_collection.clone(), + current_asset.clone(), + ) + .map(|i| i.data); } // Burn the current asset - let _ = pallet_nfts::Pallet::::burn(origin.clone(), current_collection.clone(), current_asset.clone()); + let _ = pallet_nfts::Pallet::::burn( + origin.clone(), + current_collection.clone(), + current_asset.clone(), + ); // Add the metadata to the old asset location if metadata.is_some() { - let _ = pallet_nfts::Pallet::::set_metadata(origin.clone(), origin_collection_at_destination.clone(), origin_asset_at_destination.clone(), metadata.unwrap()); + let _ = pallet_nfts::Pallet::::set_metadata( + origin.clone(), + origin_collection_at_destination.clone(), + origin_asset_at_destination.clone(), + metadata.unwrap(), + ); } // Remove asset from received @@ -1297,11 +1507,7 @@ use frame_system::pallet_prelude::*; Ok(().into()) } - - ///DONE - #[pallet::call_index(5)] - #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] - + /// Update collection metadata cross-chain. /// /// Origin must be Signed and the signing account must be : @@ -1313,10 +1519,16 @@ use frame_system::pallet_prelude::*; /// - `data`: The metadata to be added to destination collection. /// /// On success emits `CollectionMetadataSent`. - /// - pub fn collection_x_update(origin: OriginFor, destination_collection_id: T::CollectionId, destination_para: ParaId , data: BoundedVec) -> DispatchResultWithPostInfo { + #[pallet::call_index(5)] + #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] + pub fn collection_x_update( + origin: OriginFor, + destination_collection_id: T::CollectionId, + destination_para: ParaId, + data: BoundedVec, + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - + // Convert accountId into accountid32 let account_vec = who.encode(); ensure!(account_vec.len() == 32, "AccountId must be 32 bytes."); @@ -1328,24 +1540,25 @@ use frame_system::pallet_prelude::*; (Parent, Junction::Parachain(destination_para.into())).into(), Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - AliasOrigin(xcm::latest::prelude::AccountId32 { id: bytes.into(), network: None }.into()), + AliasOrigin( + xcm::latest::prelude::AccountId32 { id: bytes.into(), network: None } + .into(), + ), Transact { origin_kind: OriginKind::Native, require_weight_at_most: Weight::from_parts(1_000_000_000, 64 * 1024), - call: >::RuntimeCall::from(Call::< - T, - I, - >::parse_collection_metadata { - collection: destination_collection_id.clone(), - data: data.clone(), - }) + call: >::RuntimeCall::from( + Call::::parse_collection_metadata { + collection: destination_collection_id.clone(), + data: data.clone(), + }, + ) .encode() .into(), }, ]), ) { Ok((_hash, _cost)) => { - // Emit event about sucessful metadata send Self::deposit_event(Event::CollectionMetadataSent { collection_id: destination_collection_id.clone(), @@ -1353,7 +1566,6 @@ use frame_system::pallet_prelude::*; owner: who.clone(), destination: destination_para.clone(), }); - }, Err(e) => Self::deposit_event(Event::CollectionMetadataFailedToXCM { e, @@ -1365,7 +1577,7 @@ use frame_system::pallet_prelude::*; } Ok(().into()) } - + /// Update NFT metadata cross-chain. /// /// Origin must be Signed and the signing account must be : @@ -1378,10 +1590,15 @@ use frame_system::pallet_prelude::*; /// - `data`: The metadata to be added to destination collection. /// /// On success emits `NFTMetadataSent`. - /// #[pallet::call_index(6)] #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] - pub fn nft_x_update(origin: OriginFor, destination_collection_id: T::CollectionId, destination_asset_id: T::ItemId, destination_para: ParaId , data: BoundedVec) -> DispatchResultWithPostInfo { + pub fn nft_x_update( + origin: OriginFor, + destination_collection_id: T::CollectionId, + destination_asset_id: T::ItemId, + destination_para: ParaId, + data: BoundedVec, + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; // Convert accountId into accountid32 @@ -1395,25 +1612,26 @@ use frame_system::pallet_prelude::*; (Parent, Junction::Parachain(destination_para.into())).into(), Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - AliasOrigin(xcm::latest::prelude::AccountId32 { id: bytes.into(), network: None }.into()), + AliasOrigin( + xcm::latest::prelude::AccountId32 { id: bytes.into(), network: None } + .into(), + ), Transact { origin_kind: OriginKind::SovereignAccount, require_weight_at_most: Weight::from_parts(1_000_000_000, 64 * 1024), - call: >::RuntimeCall::from(Call::< - T, - I, - >::parse_nft_metadata { - collection: destination_collection_id.clone(), - item: destination_asset_id.clone(), - data: data.clone(), - }) + call: >::RuntimeCall::from( + Call::::parse_nft_metadata { + collection: destination_collection_id.clone(), + item: destination_asset_id.clone(), + data: data.clone(), + }, + ) .encode() .into(), }, ]), ) { Ok((_hash, _cost)) => { - // Emit event about sucessful metadata send Self::deposit_event(Event::NFTMetadataSent { collection_id: destination_collection_id.clone(), @@ -1422,7 +1640,6 @@ use frame_system::pallet_prelude::*; owner: who.clone(), destination: destination_para.clone(), }); - }, Err(e) => Self::deposit_event(Event::NFTMetadataFailedToXCM { e, @@ -1435,7 +1652,7 @@ use frame_system::pallet_prelude::*; } Ok(().into()) } - + /// Prompt to burn empty collection cross-chain. /// /// Origin must be Signed and the signing account must be : @@ -1444,13 +1661,18 @@ use frame_system::pallet_prelude::*; /// Arguments: /// - `destination_collection_id`: The collection_id at the destination. /// - `destination_para`: The recipient parachain ID. - /// - `witness_data`: The amount of NFTs, metadatas and configs in the collection (Needs to be all zeros for successful burn). + /// - `witness_data`: The amount of NFTs, metadatas and configs in the collection (Needs to + /// be all zeros for successful burn). /// /// On success emits `CollectionBurnSent`. - /// #[pallet::call_index(7)] #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] - pub fn collection_x_burn(origin: OriginFor, destination_collection_id: T::CollectionId, destination_para: ParaId, witnes_data: pallet_nfts::DestroyWitness) -> DispatchResultWithPostInfo { + pub fn collection_x_burn( + origin: OriginFor, + destination_collection_id: T::CollectionId, + destination_para: ParaId, + witnes_data: pallet_nfts::DestroyWitness, + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; // Convert accountId into accountid32 @@ -1464,18 +1686,23 @@ use frame_system::pallet_prelude::*; (Parent, Junction::Parachain(destination_para.into())).into(), Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - AliasOrigin(xcm::latest::prelude::AccountId32 { id: bytes.into(), network: None }.into()), + AliasOrigin( + xcm::latest::prelude::AccountId32 { id: bytes.into(), network: None } + .into(), + ), Transact { origin_kind: OriginKind::SovereignAccount, require_weight_at_most: Weight::from_parts(1_000_000_000, 64 * 1024), - call: >::RuntimeCall::from(Call::parse_collection_burn {collection_to_burn: destination_collection_id.clone(), witness_data: witnes_data.clone() }) + call: >::RuntimeCall::from(Call::parse_collection_burn { + collection_to_burn: destination_collection_id.clone(), + witness_data: witnes_data.clone(), + }) .encode() .into(), }, ]), ) { Ok((_hash, _cost)) => { - // Emit event about sucessful burn prompt transfer Self::deposit_event(Event::CollectionBurnSent { collection_id: destination_collection_id.clone(), @@ -1483,7 +1710,6 @@ use frame_system::pallet_prelude::*; owner: who.clone(), destination: destination_para.clone(), }); - }, Err(e) => Self::deposit_event(Event::CollectionBurnFailedToXCM { e, @@ -1493,7 +1719,7 @@ use frame_system::pallet_prelude::*; destination: destination_para.clone(), }), } - + Ok(().into()) } @@ -1508,31 +1734,35 @@ use frame_system::pallet_prelude::*; /// - `destination_para`: The recipient parachain ID. /// /// On success emits `NFTBurnSent`. - /// #[pallet::call_index(8)] #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] - pub fn nft_x_burn (origin: OriginFor, destination_collection_id: T::CollectionId, destination_asset_id: T::ItemId, destination_para: ParaId) -> DispatchResultWithPostInfo { + pub fn nft_x_burn( + origin: OriginFor, + destination_collection_id: T::CollectionId, + destination_asset_id: T::ItemId, + destination_para: ParaId, + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; - + // Convert accountId into accountid32 let account_vec = who.encode(); ensure!(account_vec.len() == 32, "AccountId must be 32 bytes."); let mut bytes = [0u8; 32]; bytes.copy_from_slice(&account_vec); - + // Send the prompt to burn NFT match send_xcm::( (Parent, Junction::Parachain(destination_para.into())).into(), Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - AliasOrigin(xcm::latest::prelude::AccountId32 { id: bytes.into(), network: None }.into()), + AliasOrigin( + xcm::latest::prelude::AccountId32 { id: bytes.into(), network: None } + .into(), + ), Transact { origin_kind: OriginKind::SovereignAccount, require_weight_at_most: Weight::from_parts(1_000_000_000, 64 * 1024), - call: >::RuntimeCall::from(Call::< - T, - I, - >::parse_nft_burn { + call: >::RuntimeCall::from(Call::::parse_nft_burn { collection: destination_collection_id.clone(), item: destination_asset_id.clone(), }) @@ -1542,7 +1772,6 @@ use frame_system::pallet_prelude::*; ]), ) { Ok((_hash, _cost)) => { - // Emit event about sucessful metadata send Self::deposit_event(Event::NFTBurnSent { collection_id: destination_collection_id.clone(), @@ -1550,7 +1779,6 @@ use frame_system::pallet_prelude::*; owner: who.clone(), destination: destination_para.clone(), }); - }, Err(e) => Self::deposit_event(Event::NFTBurnFailedToXCM { e, @@ -1560,7 +1788,7 @@ use frame_system::pallet_prelude::*; destination: destination_para.clone(), }), } - + Ok(().into()) } @@ -1568,7 +1796,8 @@ use frame_system::pallet_prelude::*; /// /// Origin must be Signed and the signing account must be : /// - the Owner of the `destination collection`; - /// - the New owner must agree to the ownership change by executing function setAcceptOwnership(maybeCollection) + /// - the New owner must agree to the ownership change by executing function + /// setAcceptOwnership(maybeCollection) /// /// Arguments: /// - `destination_collection_id`: The collection_id at the destination. @@ -1576,10 +1805,14 @@ use frame_system::pallet_prelude::*; /// - `destination_account`: The destination account that will receive collection. /// /// On success emits `CollectionOwnershipSent`. - /// #[pallet::call_index(9)] #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] - pub fn collection_x_change_owner(origin: OriginFor, destination_collection_id: T::CollectionId, destination_para: ParaId, destination_account: AccountIdLookupOf) -> DispatchResultWithPostInfo { + pub fn collection_x_change_owner( + origin: OriginFor, + destination_collection_id: T::CollectionId, + destination_para: ParaId, + destination_account: AccountIdLookupOf, + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; // Convert accountId into accountid32 @@ -1593,31 +1826,31 @@ use frame_system::pallet_prelude::*; (Parent, Junction::Parachain(destination_para.into())).into(), Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - AliasOrigin(xcm::latest::prelude::AccountId32 { id: bytes.into(), network: None }.into()), + AliasOrigin( + xcm::latest::prelude::AccountId32 { id: bytes.into(), network: None } + .into(), + ), Transact { origin_kind: OriginKind::SovereignAccount, require_weight_at_most: Weight::from_parts(1_000_000_000, 64 * 1024), - call: >::RuntimeCall::from(Call::< - T, - I, - >::parse_collection_owner { - new_owner: destination_account.clone(), - collection: destination_collection_id.clone(), - }) + call: >::RuntimeCall::from( + Call::::parse_collection_owner { + new_owner: destination_account.clone(), + collection: destination_collection_id.clone(), + }, + ) .encode() .into(), }, ]), ) { Ok((_hash, _cost)) => { - // Emit event about sucessful metadata send Self::deposit_event(Event::CollectionOwnershipSent { collection_id: destination_collection_id.clone(), proposed_owner: destination_account.clone(), destination: destination_para.clone(), }); - }, Err(e) => Self::deposit_event(Event::CollectionOwnershipFailedToXCM { e, @@ -1626,7 +1859,7 @@ use frame_system::pallet_prelude::*; destination: destination_para.clone(), }), } - + Ok(().into()) } @@ -1642,10 +1875,15 @@ use frame_system::pallet_prelude::*; /// - `destination_account`: The destination account that will receive collection. /// /// On success emits `NFTOwnershipSent`. - /// #[pallet::call_index(10)] #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] - pub fn nft_x_change_owner(origin: OriginFor, destination_collection_id: T::CollectionId, destination_asset_id: T::ItemId, destination_para: ParaId, destination_account: AccountIdLookupOf) -> DispatchResultWithPostInfo { + pub fn nft_x_change_owner( + origin: OriginFor, + destination_collection_id: T::CollectionId, + destination_asset_id: T::ItemId, + destination_para: ParaId, + destination_account: AccountIdLookupOf, + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin)?; // Convert accountId into accountid32 @@ -1659,14 +1897,14 @@ use frame_system::pallet_prelude::*; (Parent, Junction::Parachain(destination_para.into())).into(), Xcm(vec![ UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - AliasOrigin(xcm::latest::prelude::AccountId32 { id: bytes.into(), network: None }.into()), + AliasOrigin( + xcm::latest::prelude::AccountId32 { id: bytes.into(), network: None } + .into(), + ), Transact { origin_kind: OriginKind::SovereignAccount, require_weight_at_most: Weight::from_parts(1_000_000_000, 64 * 1024), - call: >::RuntimeCall::from(Call::< - T, - I, - >::parse_nft_owner { + call: >::RuntimeCall::from(Call::::parse_nft_owner { new_owner: destination_account.clone(), collection: destination_collection_id.clone(), item: destination_asset_id.clone(), @@ -1677,7 +1915,6 @@ use frame_system::pallet_prelude::*; ]), ) { Ok((_hash, _cost)) => { - // Emit event about sucessful metadata send Self::deposit_event(Event::NFTOwnershipSent { collection_id: destination_collection_id.clone(), @@ -1685,7 +1922,6 @@ use frame_system::pallet_prelude::*; proposed_owner: destination_account.clone(), destination: destination_para.clone(), }); - }, Err(e) => Self::deposit_event(Event::NFTOwnershipFailedToXCM { e, @@ -1695,41 +1931,50 @@ use frame_system::pallet_prelude::*; destination: destination_para.clone(), }), } - + Ok(().into()) } - ///TEST + /// Receive function for collection_x_transfer function. + /// + /// Shouldn't be used as a regular call. + /// + /// On success emits `CollectionReceived`. #[pallet::call_index(11)] #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] - pub fn parse_collection_empty(origin: OriginFor ,origin_collection: T::CollectionId, collection_metadata: BoundedVec, config: CollectionConfigFor::) -> DispatchResultWithPostInfo { - //Create collection + pub fn parse_collection_empty( + origin: OriginFor, + origin_collection: T::CollectionId, + collection_metadata: BoundedVec, + config: CollectionConfigFor, + ) -> DispatchResultWithPostInfo { let signed_origin = ensure_signed(origin.clone())?; - - //unlookup the signed_origin let signed_origin_lookup = T::Lookup::unlookup(signed_origin.clone()); + // Create the collection match pallet_nfts::Pallet::::create( origin.clone(), signed_origin_lookup.clone(), - config.clone() + config.clone(), ) { - Ok(_) => { - }, + Ok(_) => {}, Err(e) => { // Deposit event indicating failure to create collection Self::deposit_event(Event::CollectionCreationFailed { owner: signed_origin_lookup.clone(), error: e, }); - } + }, } - //Set the collection metadata if not empty + // Set the collection metadata if not empty if !collection_metadata.is_empty() { - match pallet_nfts::Pallet::::set_collection_metadata(origin.clone(), origin_collection.clone(), collection_metadata.clone()) { - Ok(_) => { - }, + match pallet_nfts::Pallet::::set_collection_metadata( + origin.clone(), + origin_collection.clone(), + collection_metadata.clone(), + ) { + Ok(_) => {}, Err(e) => { // Deposit event indicating failure to set metadata Self::deposit_event(Event::CollectionMetadataSetFailed { @@ -1737,11 +1982,11 @@ use frame_system::pallet_prelude::*; owner: signed_origin_lookup.clone(), error: e, }); - } + }, } } - // Emit event + // Emit a success event Self::deposit_event(Event::CollectionReceived { origin_collection_id: origin_collection.clone(), received_collection_id: origin_collection.clone(), @@ -1751,19 +1996,27 @@ use frame_system::pallet_prelude::*; Ok(().into()) } - ///TEST + /// Receive function for collection_x_burn function. + /// + /// Doesn't differ from nfts pallet destroy function. + /// + /// On success emits regular destroy function events. #[pallet::call_index(12)] #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] - pub fn parse_collection_burn(origin: OriginFor, collection_to_burn: T::CollectionId, witness_data: pallet_nfts::DestroyWitness) -> DispatchResultWithPostInfo { - //Burn the collection + pub fn parse_collection_burn( + origin: OriginFor, + collection_to_burn: T::CollectionId, + witness_data: pallet_nfts::DestroyWitness, + ) -> DispatchResultWithPostInfo { let signed_origin = ensure_signed(origin.clone())?; - - //unlookup the signed_origin let signed_origin_lookup = T::Lookup::unlookup(signed_origin.clone()); - match pallet_nfts::Pallet::::destroy(origin.clone(), collection_to_burn.clone(), witness_data.clone()) { - Ok(_) => { - }, + match pallet_nfts::Pallet::::destroy( + origin.clone(), + collection_to_burn.clone(), + witness_data.clone(), + ) { + Ok(_) => {}, Err(e) => { // Deposit event indicating failure to burn collection Self::deposit_event(Event::CollectionBurnFailed { @@ -1771,25 +2024,33 @@ use frame_system::pallet_prelude::*; collection_id: collection_to_burn.clone(), error: e, }); - } + }, } Ok(().into()) } - ///DONE + /// Receive function for collection_x_update function. + /// + /// Doesn't differ from nfts pallet setCollectionMetadara function. + /// + /// On success emits regular setCollectionMetadata function events. #[pallet::call_index(13)] #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] - pub fn parse_collection_metadata(origin: OriginFor, collection: T::CollectionId, data: BoundedVec) -> DispatchResultWithPostInfo { + pub fn parse_collection_metadata( + origin: OriginFor, + collection: T::CollectionId, + data: BoundedVec, + ) -> DispatchResultWithPostInfo { let signed_origin = ensure_signed(origin.clone())?; - - //unlookup the signed_origin let signed_origin_lookup = T::Lookup::unlookup(signed_origin.clone()); - //Set the collection metadata - match pallet_nfts::Pallet::::set_collection_metadata(origin.clone(), collection.clone(), data.clone()) { - Ok(_) => { - }, + match pallet_nfts::Pallet::::set_collection_metadata( + origin.clone(), + collection.clone(), + data.clone(), + ) { + Ok(_) => {}, Err(e) => { // Deposit event indicating failure to set metadata Self::deposit_event(Event::CollectionMetadataSetFailed { @@ -1797,26 +2058,33 @@ use frame_system::pallet_prelude::*; owner: signed_origin_lookup.clone(), error: e, }); - } + }, } Ok(().into()) } - ///TEST + /// Receive function for collection_x_change_owner function. + /// + /// Doesn't differ from nfts pallet transferOwnership function. + /// + /// On success emits regular transferOwnership function events. #[pallet::call_index(14)] #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] - pub fn parse_collection_owner(origin: OriginFor, new_owner: AccountIdLookupOf, collection: T::CollectionId) -> DispatchResultWithPostInfo { - + pub fn parse_collection_owner( + origin: OriginFor, + new_owner: AccountIdLookupOf, + collection: T::CollectionId, + ) -> DispatchResultWithPostInfo { let signed_origin = ensure_signed(origin.clone())?; - - //unlookup the signed_origin let signed_origin_lookup = T::Lookup::unlookup(signed_origin.clone()); - //Change the collection owner - match pallet_nfts::Pallet::::transfer_ownership(origin.clone(), collection.clone(), new_owner.clone()) { - Ok(_) => { - }, + match pallet_nfts::Pallet::::transfer_ownership( + origin.clone(), + collection.clone(), + new_owner.clone(), + ) { + Ok(_) => {}, Err(e) => { // Deposit event indicating failure to transfer ownership Self::deposit_event(Event::CollectionOwnershipTransferFailed { @@ -1824,26 +2092,33 @@ use frame_system::pallet_prelude::*; owner: signed_origin_lookup.clone(), error: e, }); - } + }, } Ok(().into()) } - ///Test + /// Receive function for nft_x_burn function. + /// + /// Doesn't differ from nfts pallet burn function. + /// + /// On success emits regular burn function events. #[pallet::call_index(15)] #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] - pub fn parse_nft_burn(origin: OriginFor, collection: T::CollectionId, item: T::ItemId) -> DispatchResultWithPostInfo { - + pub fn parse_nft_burn( + origin: OriginFor, + collection: T::CollectionId, + item: T::ItemId, + ) -> DispatchResultWithPostInfo { let signed_origin = ensure_signed(origin.clone())?; - - //unlookup the signed_origin let signed_origin_lookup = T::Lookup::unlookup(signed_origin.clone()); - //Burn the NFT - match pallet_nfts::Pallet::::burn(origin.clone(), collection.clone(), item.clone()) { - Ok(_) => { - }, + match pallet_nfts::Pallet::::burn( + origin.clone(), + collection.clone(), + item.clone(), + ) { + Ok(_) => {}, Err(e) => { // Deposit event indicating failure to burn NFT Self::deposit_event(Event::NFTBurnFailed { @@ -1852,25 +2127,35 @@ use frame_system::pallet_prelude::*; owner: signed_origin_lookup.clone(), error: e, }); - } + }, } Ok(().into()) } - ///TEST + /// Receive function for nft_x_update function. + /// + /// Doesn't differ from nfts pallet setMetadata function. + /// + /// On success emits regular setMetadata function events. #[pallet::call_index(16)] #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] - pub fn parse_nft_metadata(origin: OriginFor, collection: T::CollectionId, item: T::ItemId, data: BoundedVec) -> DispatchResultWithPostInfo { + pub fn parse_nft_metadata( + origin: OriginFor, + collection: T::CollectionId, + item: T::ItemId, + data: BoundedVec, + ) -> DispatchResultWithPostInfo { let signed_origin = ensure_signed(origin.clone())?; - - //unlookup the signed_origin let signed_origin_lookup = T::Lookup::unlookup(signed_origin.clone()); - //Set the NFT metadata - match pallet_nfts::Pallet::::set_metadata(origin.clone(), collection.clone(), item.clone(), data.clone()) { - Ok(_) => { - }, + match pallet_nfts::Pallet::::set_metadata( + origin.clone(), + collection.clone(), + item.clone(), + data.clone(), + ) { + Ok(_) => {}, Err(e) => { // Deposit event indicating failure to set metadata Self::deposit_event(Event::NFTMetadataSetFailed { @@ -1879,25 +2164,35 @@ use frame_system::pallet_prelude::*; owner: signed_origin_lookup.clone(), error: e, }); - } + }, } Ok(().into()) } - ///TEST + /// Receive function for nft_x_change_owner function. + /// + /// Doesn't differ from nfts pallet transfer function. + /// + /// On success emits regular transfer function events. #[pallet::call_index(17)] #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] - pub fn parse_nft_owner(origin: OriginFor, new_owner: AccountIdLookupOf, collection: T::CollectionId, item: T::ItemId) -> DispatchResultWithPostInfo { + pub fn parse_nft_owner( + origin: OriginFor, + new_owner: AccountIdLookupOf, + collection: T::CollectionId, + item: T::ItemId, + ) -> DispatchResultWithPostInfo { let signed_origin = ensure_signed(origin.clone())?; - - //unlookup the signed_origin let signed_origin_lookup = T::Lookup::unlookup(signed_origin.clone()); - //Change the NFT owner - match pallet_nfts::Pallet::::transfer(origin.clone(), collection.clone(), item.clone(), new_owner.clone()) { - Ok(_) => { - }, + match pallet_nfts::Pallet::::transfer( + origin.clone(), + collection.clone(), + item.clone(), + new_owner.clone(), + ) { + Ok(_) => {}, Err(e) => { // Deposit event indicating failure to transfer ownership Self::deposit_event(Event::NFTOwnershipTransferFailed { @@ -1906,64 +2201,78 @@ use frame_system::pallet_prelude::*; owner: signed_origin_lookup.clone(), error: e, }); - } + }, } Ok(().into()) } - + + /// Receive function for nft_x_transfer function. + /// + /// Shouldn't be used as a regular call. + /// + /// On success emits `NFTReceived` or `NFTReturnedToOrigin` events. #[pallet::call_index(18)] #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] - pub fn parse_nft_transfer( origin: OriginFor, collection: T::CollectionId, item: T::ItemId, data: BoundedVec, origin_collection: T::CollectionId, origin_item: T::ItemId, origin_chain: ParaId) -> DispatchResultWithPostInfo { + pub fn parse_nft_transfer( + origin: OriginFor, + collection: T::CollectionId, + item: T::ItemId, + data: BoundedVec, + origin_collection: T::CollectionId, + origin_item: T::ItemId, + origin_chain: ParaId, + ) -> DispatchResultWithPostInfo { let signed_origin = ensure_signed(origin.clone())?; - - //unlookup the signed_origin let signed_origin_lookup = T::Lookup::unlookup(signed_origin.clone()); - //Check if the collection exists - let collection_exists = pallet_nfts::Collection::::contains_key(&collection); - ensure!(collection_exists, Error::::CollectionDoesNotExist); - - //Check if not in receiving assets - let received_exists = ReceivedAssets::::contains_key(&(collection.clone(), item.clone())); - ensure!(!received_exists, Error::::NFTAlreadyReceived); - - let sent_exists = SentAssets::::contains_key(&(collection.clone(), item.clone())); - if sent_exists { - //User has no permission to claim the NFT - //We need to get collection owner and put him as signer - let col_owner = pallet_nfts::Pallet::::collection_owner(collection.clone()).unwrap(); - let signed_col: OriginFor = frame_system::RawOrigin::Signed(col_owner.clone()).into(); - - //This means, that this is the NFT origin chain, we also check if ParaId matches - // Retrieve the sent asset and store it in a variable - let sent_asset = SentAssets::::get(&(collection.clone(), item.clone())).unwrap(); - - if sent_asset.origin_para_id == parachain_info::Pallet::::parachain_id() { - - - //We know we are the origin chain, we can add only metadata - - if !data.is_empty(){ - match pallet_nfts::Pallet::::set_metadata(signed_col.clone(), collection.clone(), item.clone(), data.clone()) { - Ok(_) => { - }, - Err(e) => { - // Deposit event indicating failure to set metadata - Self::deposit_event(Event::NFTMetadataSetFailed { - collection_id: collection.clone(), - asset_id: item.clone(), - owner: signed_origin_lookup.clone(), - error: e, - }); - } - } + // Check if the collection exists + ensure!( + pallet_nfts::Collection::::contains_key(&collection), + Error::::CollectionDoesNotExist + ); + + // Check if not in receiving assets + ensure!( + !ReceivedAssets::::contains_key(&(collection.clone(), item.clone())), + Error::::NFTAlreadyReceived + ); + + if SentAssets::::contains_key(&(collection.clone(), item.clone())) { + // User returns nft to origin collection, use collection owner to add metadata + let col_owner = + pallet_nfts::Pallet::::collection_owner(collection.clone()).unwrap(); + let signed_col: OriginFor = + frame_system::RawOrigin::Signed(col_owner.clone()).into(); + let sent_asset = + SentAssets::::get(&(collection.clone(), item.clone())).unwrap(); + + if sent_asset.origin_para_id == parachain_info::Pallet::::parachain_id() { + // We know we are the origin chain, we can add only metadata + if !data.is_empty() { + match pallet_nfts::Pallet::::set_metadata( + signed_col.clone(), + collection.clone(), + item.clone(), + data.clone(), + ) { + Ok(_) => {}, + Err(e) => { + // Deposit event indicating failure to set metadata + Self::deposit_event(Event::NFTMetadataSetFailed { + collection_id: collection.clone(), + asset_id: item.clone(), + owner: signed_origin_lookup.clone(), + error: e, + }); + }, } + } - //We also remove sent assets and received assets + // We also remove sent assets and received assets SentAssets::::remove(&(collection.clone(), item.clone())); - //We emit event about return to origin chain + // We emit event about return to origin chain Self::deposit_event(Event::NFTReturnedToOrigin { returned_from_collection_id: collection.clone(), returned_from_asset_id: item.clone(), @@ -1971,26 +2280,34 @@ use frame_system::pallet_prelude::*; }); return Ok(().into()) - } - else { - //We know, that we return to chain that sent this NFT once already - //We proceed as normal, with the only difference being, that we remove the item from sent assets + } else { + // The item returns to chain, that sent it already, but it is not origin, + // proceeding as normal, but removing item from sent assets SentAssets::::remove(&(collection.clone(), item.clone())); } } - //Check if the owner owns the collection - let col_owner = pallet_nfts::Pallet::::collection_owner(collection); - ensure!(col_owner.unwrap()==signed_origin.clone(), Error::::NotCollectionOwner); + // Check if the owner owns the collection + ensure!( + pallet_nfts::Pallet::::collection_owner(collection).unwrap() == + signed_origin.clone(), + Error::::NotCollectionOwner + ); - //Check if the item exists - let item_exists = pallet_nfts::Item::::contains_key(&collection, &item); - ensure!(!item_exists, Error::::NFTExists); + // Check if the item exists + ensure!( + !pallet_nfts::Item::::contains_key(&collection, &item), + Error::::NFTExists + ); - //Mint the NFT - match pallet_nfts::Pallet::::mint(origin.clone(), collection.clone(), item.clone(), signed_origin_lookup.clone(), None) { - Ok(_) => { - }, + match pallet_nfts::Pallet::::mint( + origin.clone(), + collection.clone(), + item.clone(), + signed_origin_lookup.clone(), + None, + ) { + Ok(_) => {}, Err(e) => { // Deposit event indicating failure to mint NFT Self::deposit_event(Event::NFTMintFailed { @@ -1999,13 +2316,17 @@ use frame_system::pallet_prelude::*; owner: signed_origin_lookup.clone(), error: e, }); - } + }, } - if !data.is_empty(){ - match pallet_nfts::Pallet::::set_metadata(origin.clone(), collection.clone(), item.clone(), data.clone()) { - Ok(_) => { - }, + if !data.is_empty() { + match pallet_nfts::Pallet::::set_metadata( + origin.clone(), + collection.clone(), + item.clone(), + data.clone(), + ) { + Ok(_) => {}, Err(e) => { // Deposit event indicating failure to set metadata Self::deposit_event(Event::NFTMetadataSetFailed { @@ -2014,24 +2335,29 @@ use frame_system::pallet_prelude::*; owner: signed_origin_lookup.clone(), error: e, }); - } + }, } - } + } - //Check if the NFT was minted if storage contains the item - let item_exists = pallet_nfts::Item::::contains_key(&collection, &item); - ensure!(item_exists, Error::::NFTDoesNotExist); + // Check if the NFT was minted successfuly + ensure!( + pallet_nfts::Item::::contains_key(&collection, &item), + Error::::NFTDoesNotExist + ); + + // Add the item to the received item storage + ReceivedAssets::::insert( + (collection.clone(), item.clone()), + ReceivedStruct { + origin_para_id: origin_chain.clone(), + origin_collection_id: origin_collection.clone(), + origin_asset_id: origin_item.clone(), + received_collection_id: collection.clone(), + received_asset_id: item.clone(), + }, + ); - //Add the item to the received item storage - ReceivedAssets::::insert((collection.clone(), item.clone()), ReceivedStruct { - origin_para_id: origin_chain.clone(), - origin_collection_id: origin_collection.clone(), - origin_asset_id: origin_item.clone(), - received_collection_id: collection.clone(), - received_asset_id: item.clone(), - }); - - //Emit event + // Emit a success event Self::deposit_event(Event::NFTReceived { origin_collection_id: origin_collection.clone(), origin_asset_id: origin_item.clone(), @@ -2040,54 +2366,79 @@ use frame_system::pallet_prelude::*; to_address: signed_origin_lookup.clone(), }); - Ok(().into()) - } - ///TEST + /// Receive function for collection_x_transfer function. + /// + /// Used when collection has nfts, but they are owned by the same owner. + /// + /// Shouldn't be used as a regular call. + /// + /// On success emits `CollectionWithNftsReceived` event. #[pallet::call_index(19)] #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] - pub fn parse_collection_same_owner(origin: OriginFor, config: CollectionConfigFor::, collection_metadata: BoundedVec ,nfts: Vec<(T::ItemId, BoundedVec)>, origin_para: ParaId, origin_collection_id: T::CollectionId) -> DispatchResultWithPostInfo { - + pub fn parse_collection_same_owner( + origin: OriginFor, + config: CollectionConfigFor, + collection_metadata: BoundedVec, + nfts: Vec<(T::ItemId, BoundedVec)>, + origin_para: ParaId, + origin_collection_id: T::CollectionId, + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin.clone())?; - - //unlookup the signed_origin let signed_origin_lookup = T::Lookup::unlookup(who.clone()); - //Get next collection id + // Get next collection id let mut next_collection_id = pallet_nfts::NextCollectionId::::get() - .or(T::CollectionId::initial_value()).unwrap(); + .or(T::CollectionId::initial_value()) + .unwrap(); - let collection = pallet_nfts::Pallet::::create( + match pallet_nfts::Pallet::::create( origin.clone(), signed_origin_lookup.clone(), - config.clone() - )?; + config.clone(), + ) { + Ok(_) => {}, + Err(e) => { + // Deposit event indicating failure to create collection + Self::deposit_event(Event::CollectionMintFailed { error: e }); + }, + } let mut user_collection = next_collection_id.clone(); - //just to be sure, check if user is collection owner - let col_owner = pallet_nfts::Pallet::::collection_owner(next_collection_id.clone()); - if col_owner.unwrap()!=who.clone(){ + + // just to be sure, check if user is collection owner + if pallet_nfts::Pallet::::collection_owner(next_collection_id.clone()).unwrap() != + who.clone() + { //Get current next_collection_id - let current_next_collection_id = pallet_nfts::NextCollectionId::::get().ok_or(Error::::NoNextCollectionId)?; - //Go from next_collection_id to current_next_collection_id and try to find the collection that is owned by the user - while next_collection_id!=current_next_collection_id{ - let col_owner = pallet_nfts::Pallet::::collection_owner(next_collection_id); - if col_owner.unwrap()==who.clone(){ - //We have users collection + let current_next_collection_id = pallet_nfts::NextCollectionId::::get() + .ok_or(Error::::NoNextCollectionId)?; + + // Go from next_collection_id to current_next_collection_id and try to find the + // collection that is owned by the user + while next_collection_id != current_next_collection_id { + if pallet_nfts::Pallet::::collection_owner(next_collection_id).unwrap() == + who.clone() + { + // We have users collection user_collection = next_collection_id.clone(); break; } - next_collection_id = next_collection_id.increment().ok_or(Error::::NoNextCollectionId)?; + next_collection_id = + next_collection_id.increment().ok_or(Error::::NoNextCollectionId)?; } } - //Set the collection metadata if present - if !collection_metadata.is_empty(){ - match pallet_nfts::Pallet::::set_collection_metadata(origin.clone(), user_collection.clone(), collection_metadata.clone()) { - Ok(_) => { - }, + // Set the collection metadata if present + if !collection_metadata.is_empty() { + match pallet_nfts::Pallet::::set_collection_metadata( + origin.clone(), + user_collection.clone(), + collection_metadata.clone(), + ) { + Ok(_) => {}, Err(e) => { // Deposit event indicating failure to set metadata Self::deposit_event(Event::CollectionMetadataSetFailed { @@ -2095,19 +2446,23 @@ use frame_system::pallet_prelude::*; owner: signed_origin_lookup.clone(), error: e, }); - } + }, } } - //Mint the NFTs + //Iterate through vector of nfts for nft in nfts.clone() { let item = nft.0; let data = nft.1; - //Mint the NFT - match pallet_nfts::Pallet::::mint(origin.clone(), user_collection.clone(), item.clone(), signed_origin_lookup.clone(), None) { - Ok(_) => { - }, + match pallet_nfts::Pallet::::mint( + origin.clone(), + user_collection.clone(), + item.clone(), + signed_origin_lookup.clone(), + None, + ) { + Ok(_) => {}, Err(e) => { // Deposit event indicating failure to mint NFT Self::deposit_event(Event::NFTMintFailed { @@ -2116,15 +2471,17 @@ use frame_system::pallet_prelude::*; owner: signed_origin_lookup.clone(), error: e, }); - } + }, } //If empty metadata, skip - if data.is_empty(){ - - }else{ - match pallet_nfts::Pallet::::set_metadata(origin.clone(), user_collection.clone(), item.clone(), data.clone()) { - Ok(_) => { - }, + if data.is_empty() { + match pallet_nfts::Pallet::::set_metadata( + origin.clone(), + user_collection.clone(), + item.clone(), + data.clone(), + ) { + Ok(_) => {}, Err(e) => { // Deposit event indicating failure to set metadata Self::deposit_event(Event::NFTMetadataSetFailed { @@ -2133,75 +2490,106 @@ use frame_system::pallet_prelude::*; owner: signed_origin_lookup.clone(), error: e, }); - } + }, } } - //Check if the NFT was minted if storage contains the item - let item_exists = pallet_nfts::Item::::contains_key(&user_collection, &item); - ensure!(item_exists, Error::::NFTDoesNotExist); - + // Check if the NFT was minted if storage contains the item + ensure!( + pallet_nfts::Item::::contains_key(&user_collection, &item), + Error::::NFTDoesNotExist + ); } - //Add collection to received collections - ReceivedCollections::::insert(user_collection.clone(), ReceivedCols { - origin_para_id: origin_para.clone(), - origin_collection_id: origin_collection_id.clone(), - received_collection_id: user_collection.clone(), - }); - - //If all went up to this point, emit event about successful cross-chain operation + // Add collection to received collections + ReceivedCollections::::insert( + user_collection.clone(), + ReceivedCols { + origin_para_id: origin_para.clone(), + origin_collection_id: origin_collection_id.clone(), + received_collection_id: user_collection.clone(), + }, + ); + + // Emit event about successful cross-chain operation Self::deposit_event(Event::CollectionWithNftsReceived { collection_id: user_collection.clone(), items: nfts.clone(), }); - Ok(().into()) } - - ///TEST + + /// Receive function for collection_x_transfer_initiate function. + /// + /// Used when collection has nfts, but they are not owned by the same owner. + /// + /// Shouldn't be used as a regular call. + /// + /// On success emits `CollectionWithNftsDiffOwnersReceived` event. #[pallet::call_index(20)] #[pallet::weight(Weight::from_parts(10_000, 0) + T::DbWeight::get().writes(1))] - pub fn parse_collection_diff_owners( origin: OriginFor, config: CollectionConfigFor::, collection_metadata: BoundedVec ,nfts: Vec<(T::ItemId, AccountIdLookupOf ,BoundedVec)>, origin_para: ParaId, origin_collection_id: T::CollectionId) -> DispatchResultWithPostInfo { + pub fn parse_collection_diff_owners( + origin: OriginFor, + config: CollectionConfigFor, + collection_metadata: BoundedVec, + nfts: Vec<(T::ItemId, AccountIdLookupOf, BoundedVec)>, + origin_para: ParaId, + origin_collection_id: T::CollectionId, + ) -> DispatchResultWithPostInfo { let who = ensure_signed(origin.clone())?; - - //unlookup the signed_origin let signed_origin_lookup = T::Lookup::unlookup(who.clone()); //Get next collection id let mut next_collection_id = pallet_nfts::NextCollectionId::::get() - .or(T::CollectionId::initial_value()).unwrap(); + .or(T::CollectionId::initial_value()) + .unwrap(); - let collection = pallet_nfts::Pallet::::create( + match pallet_nfts::Pallet::::create( origin.clone(), signed_origin_lookup.clone(), - config.clone() - )?; + config.clone(), + ) { + Ok(_) => {}, + Err(e) => { + // Deposit event indicating failure to create collection + Self::deposit_event(Event::CollectionMintFailed { error: e }); + }, + } let mut user_collection = next_collection_id.clone(); - //just to be sure, check if user is collection owner - let col_owner = pallet_nfts::Pallet::::collection_owner(next_collection_id.clone()); - if col_owner.unwrap()!=who.clone(){ + + // just to be sure, check if user is collection owner + if pallet_nfts::Pallet::::collection_owner(next_collection_id.clone()).unwrap() != + who.clone() + { //Get current next_collection_id - let current_next_collection_id = pallet_nfts::NextCollectionId::::get().ok_or(Error::::NoNextCollectionId)?; - //Go from next_collection_id to current_next_collection_id and try to find the collection that is owned by the user - while next_collection_id!=current_next_collection_id{ - let col_owner = pallet_nfts::Pallet::::collection_owner(next_collection_id); - if col_owner.unwrap()==who.clone(){ - //We have users collection + let current_next_collection_id = pallet_nfts::NextCollectionId::::get() + .ok_or(Error::::NoNextCollectionId)?; + + // Go from next_collection_id to current_next_collection_id and try to find the + // collection that is owned by the user + while next_collection_id != current_next_collection_id { + if pallet_nfts::Pallet::::collection_owner(next_collection_id).unwrap() == + who.clone() + { + // We have users collection user_collection = next_collection_id.clone(); break; } - next_collection_id = next_collection_id.increment().ok_or(Error::::NoNextCollectionId)?; + next_collection_id = + next_collection_id.increment().ok_or(Error::::NoNextCollectionId)?; } } - //Set the collection metadata if present - if !collection_metadata.is_empty(){ - match pallet_nfts::Pallet::::set_collection_metadata(origin.clone(), user_collection.clone(), collection_metadata.clone()) { - Ok(_) => { - }, + // Set the collection metadata if present + if !collection_metadata.is_empty() { + match pallet_nfts::Pallet::::set_collection_metadata( + origin.clone(), + user_collection.clone(), + collection_metadata.clone(), + ) { + Ok(_) => {}, Err(e) => { // Deposit event indicating failure to set metadata Self::deposit_event(Event::CollectionMetadataSetFailed { @@ -2209,20 +2597,24 @@ use frame_system::pallet_prelude::*; owner: signed_origin_lookup.clone(), error: e, }); - } + }, } } - //Mint the NFTs + //Iterate through vector of nfts for nft in nfts.clone() { let item = nft.0; let nft_owner = nft.1; let data = nft.2; - //Mint the NFT - match pallet_nfts::Pallet::::mint(origin.clone(), user_collection.clone(), item.clone(), nft_owner.clone(), None) { - Ok(_) => { - }, + match pallet_nfts::Pallet::::mint( + origin.clone(), + user_collection.clone(), + item.clone(), + nft_owner.clone(), + None, + ) { + Ok(_) => {}, Err(e) => { // Deposit event indicating failure to mint NFT Self::deposit_event(Event::NFTMintFailed { @@ -2231,13 +2623,17 @@ use frame_system::pallet_prelude::*; owner: nft_owner.clone(), error: e, }); - } + }, } - //If empty metadata, skip - if !data.is_empty(){ - match pallet_nfts::Pallet::::set_metadata(origin.clone(), user_collection.clone(), item.clone(), data.clone()) { - Ok(_) => { - }, + + if !data.is_empty() { + match pallet_nfts::Pallet::::set_metadata( + origin.clone(), + user_collection.clone(), + item.clone(), + data.clone(), + ) { + Ok(_) => {}, Err(e) => { // Deposit event indicating failure to set metadata Self::deposit_event(Event::NFTMetadataSetFailed { @@ -2246,32 +2642,34 @@ use frame_system::pallet_prelude::*; owner: nft_owner.clone(), error: e, }); - } + }, } } //Check if the NFT was minted if storage contains the item - let item_exists = pallet_nfts::Item::::contains_key(&user_collection, &item); - ensure!(item_exists, Error::::NFTDoesNotExist); - + ensure!( + pallet_nfts::Item::::contains_key(&user_collection, &item), + Error::::NFTDoesNotExist + ); } //Add collection to received collections - ReceivedCollections::::insert(user_collection.clone(), ReceivedCols { - origin_para_id: origin_para.clone(), - origin_collection_id: origin_collection_id.clone(), - received_collection_id: user_collection.clone(), - }); - + ReceivedCollections::::insert( + user_collection.clone(), + ReceivedCols { + origin_para_id: origin_para.clone(), + origin_collection_id: origin_collection_id.clone(), + received_collection_id: user_collection.clone(), + }, + ); + //If all went up to this point, emit event about successful cross-chain operation Self::deposit_event(Event::CollectionWithNftsDiffOwnersReceived { collection_id: user_collection.clone(), items: nfts.clone(), }); - Ok(().into()) } } } -