// This file is part of Bizinikiwi. // Copyright (C) Parity Technologies (UK) Ltd. and Dijital Kurdistan Tech Institute // SPDX-License-Identifier: Apache-2.0 // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //! Implementations for `nonfungibles` traits. use super::*; use alloc::vec::Vec; use pezframe_support::{ storage::KeyPrefixIterator, traits::{tokens::nonfungibles::*, Get}, BoundedSlice, }; use pezsp_runtime::{DispatchError, DispatchResult}; impl, I: 'static> Inspect<::AccountId> for Pezpallet { type ItemId = T::ItemId; type CollectionId = T::CollectionId; fn owner( collection: &Self::CollectionId, item: &Self::ItemId, ) -> Option<::AccountId> { Item::::get(collection, item).map(|a| a.owner) } fn collection_owner(collection: &Self::CollectionId) -> Option<::AccountId> { Collection::::get(collection).map(|a| a.owner) } /// Returns the attribute value of `item` of `collection` corresponding to `key`. /// /// When `key` is empty, we return the item metadata value. /// /// By default this is `None`; no attributes are defined. fn attribute( collection: &Self::CollectionId, item: &Self::ItemId, key: &[u8], ) -> Option> { if key.is_empty() { // We make the empty key map to the item metadata value. ItemMetadataOf::::get(collection, item).map(|m| m.data.into()) } else { let key = BoundedSlice::<_, _>::try_from(key).ok()?; Attribute::::get((collection, Some(item), key)).map(|a| a.0.into()) } } /// Returns the attribute value of `item` of `collection` corresponding to `key`. /// /// When `key` is empty, we return the item metadata value. /// /// By default this is `None`; no attributes are defined. fn collection_attribute(collection: &Self::CollectionId, key: &[u8]) -> Option> { if key.is_empty() { // We make the empty key map to the item metadata value. CollectionMetadataOf::::get(collection).map(|m| m.data.into()) } else { let key = BoundedSlice::<_, _>::try_from(key).ok()?; Attribute::::get((collection, Option::::None, key)).map(|a| a.0.into()) } } /// Returns `true` if the `item` of `collection` may be transferred. /// /// Default implementation is that all items are transferable. fn can_transfer(collection: &Self::CollectionId, item: &Self::ItemId) -> bool { match (Collection::::get(collection), Item::::get(collection, item)) { (Some(cd), Some(id)) if !cd.is_frozen && !id.is_frozen => true, _ => false, } } } impl, I: 'static> Create<::AccountId> for Pezpallet { /// Create a `collection` of nonfungible items to be owned by `who` and managed by `admin`. fn create_collection( collection: &Self::CollectionId, who: &T::AccountId, admin: &T::AccountId, ) -> DispatchResult { Self::do_create_collection( collection.clone(), who.clone(), admin.clone(), T::CollectionDeposit::get(), false, Event::Created { collection: collection.clone(), creator: who.clone(), owner: admin.clone(), }, ) } } impl, I: 'static> Destroy<::AccountId> for Pezpallet { type DestroyWitness = DestroyWitness; fn get_destroy_witness(collection: &Self::CollectionId) -> Option { Collection::::get(collection).map(|a| a.destroy_witness()) } fn destroy( collection: Self::CollectionId, witness: Self::DestroyWitness, maybe_check_owner: Option, ) -> Result { Self::do_destroy_collection(collection, witness, maybe_check_owner) } } impl, I: 'static> Mutate<::AccountId> for Pezpallet { fn mint_into( collection: &Self::CollectionId, item: &Self::ItemId, who: &T::AccountId, ) -> DispatchResult { Self::do_mint(collection.clone(), *item, who.clone(), |_| Ok(())) } fn burn( collection: &Self::CollectionId, item: &Self::ItemId, maybe_check_owner: Option<&T::AccountId>, ) -> DispatchResult { Self::do_burn(collection.clone(), *item, |_, d| { if let Some(check_owner) = maybe_check_owner { if &d.owner != check_owner { return Err(Error::::NoPermission.into()); } } Ok(()) }) } } impl, I: 'static> Transfer for Pezpallet { fn transfer( collection: &Self::CollectionId, item: &Self::ItemId, destination: &T::AccountId, ) -> DispatchResult { Self::do_transfer(collection.clone(), *item, destination.clone(), |_, _| Ok(())) } } impl, I: 'static> InspectEnumerable for Pezpallet { type CollectionsIterator = KeyPrefixIterator<>::CollectionId>; type ItemsIterator = KeyPrefixIterator<>::ItemId>; type OwnedIterator = KeyPrefixIterator<(>::CollectionId, >::ItemId)>; type OwnedInCollectionIterator = KeyPrefixIterator<>::ItemId>; /// Returns an iterator of the collections in existence. /// /// NOTE: iterating this list invokes a storage read per item. fn collections() -> Self::CollectionsIterator { CollectionMetadataOf::::iter_keys() } /// Returns an iterator of the items of a `collection` in existence. /// /// NOTE: iterating this list invokes a storage read per item. fn items(collection: &Self::CollectionId) -> Self::ItemsIterator { ItemMetadataOf::::iter_key_prefix(collection) } /// Returns an iterator of the items of all collections owned by `who`. /// /// NOTE: iterating this list invokes a storage read per item. fn owned(who: &T::AccountId) -> Self::OwnedIterator { Account::::iter_key_prefix((who,)) } /// Returns an iterator of the items of `collection` owned by `who`. /// /// NOTE: iterating this list invokes a storage read per item. fn owned_in_collection( collection: &Self::CollectionId, who: &T::AccountId, ) -> Self::OwnedInCollectionIterator { Account::::iter_key_prefix((who, collection)) } }