* Copy Uniques into Nfts

* Connect new pallet

* Update weights

* Nfts: Multiple approvals (#12178)

* multiple approvals

* clear

* tests & clean up

* fix in logic & fmt

* fix benchmarks

* deadline

* test deadline

* current_block + deadline

* update ApprovedTransfer event

* benchmark

* docs

* Update frame/nfts/src/lib.rs

Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com>

* fmt fix

* Update frame/nfts/src/lib.rs

Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com>

* update tests

* anyone can cancel

* Update frame/nfts/src/tests.rs

Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com>

* fmt

* fix logic

* unnecessary line

* ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts

* Update frame/nfts/src/lib.rs

* Update lib.rs

* fmt

* Update frame/nfts/src/lib.rs

Co-authored-by: Squirrel <gilescope@gmail.com>

* Update frame/nfts/src/lib.rs

Co-authored-by: Squirrel <gilescope@gmail.com>

* fmt

* Update frame/nfts/src/lib.rs

Co-authored-by: Squirrel <gilescope@gmail.com>

* suggestion

* new line

* ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts

Co-authored-by: Jegor Sidorenko <5252494+jsidorenko@users.noreply.github.com>
Co-authored-by: command-bot <>
Co-authored-by: Squirrel <gilescope@gmail.com>

* Fixes

* cargo fmt

* Fixes

* Fixes

* Fix CI

* Nfts: Fix Auto-Increment (#12223)

* commit

* passing benchmarks

* clean up

* sync

* runtime implementation

* fix

* fmt

* fix benchmark

* cfg

* remove try-increment-id

* remove unused error

* impl Incrementable for unsigned types

* clean up

* fix in tests

* not needed anymore

* Use OptionQuery

Co-authored-by: Keith Yeung <kungfukeith11@gmail.com>

* Rename Origin to RuntimeOrigin

* [Uniques V2] Tips (#12168)

* Allow to add tips when buying an NFT

* Chore

* Rework tips feature

* Add weights + benchmarks

* Convert tuple to struct

* Fix benchmark

* ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts

* Update frame/nfts/src/benchmarking.rs

Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* Fix benchmarks

* Revert the bounded_vec![] approach

* ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts

Co-authored-by: command-bot <>
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>

* [Uniques V2] Atomic NFTs swap (#12285)

* Atomic NFTs swap

* Fmt

* Fix benchmark

* Rename swap -> atomic_swap

* Update target balance

* Rollback

* Fix

* ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts

* Make desired item optional

* Apply suggestions

* Update frame/nfts/src/features/atomic_swap.rs

Co-authored-by: Squirrel <gilescope@gmail.com>

* Rename fields

* Optimisation

* Add a comment

* deadline -> maybe_deadline

* Add docs

* Change comments

* Add price direction field

* ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts

* Wrap price and direction

* Fix benchmarks

* Use ensure! instead of if {}

* Make duration param mandatory and limit it to MaxDeadlineDuration

* Make the code safer

* Fix clippy

* Chore

* Remove unused vars

* try

* try 2

* try 3

Co-authored-by: command-bot <>
Co-authored-by: Squirrel <gilescope@gmail.com>

* [Uniques V2] Feature flags (#12367)

* Basics

* WIP: change the data format

* Refactor

* Remove redundant new() method

* Rename settings

* Enable tests

* Chore

* Change params order

* Delete the config on collection removal

* Chore

* Remove redundant system features

* Rename force_item_status to force_collection_status

* Update node runtime

* Chore

* Remove thaw_collection

* Chore

* Connect collection.is_frozen to config

* Allow to lock the collection in a new way

* Move free_holding into settings

* Connect collection's metadata locker to feature flags

* DRY

* Chore

* Connect pallet level feature flags

* Prepare tests for the new changes

* Implement Item settings

* Allow to lock the metadata or attributes of an item

* Common -> Settings

* Extract settings related code to a separate file

* Move feature flag checks inside the do_* methods

* Split settings.rs into parts

* Extract repeated code into macro

* Extract macros into their own file

* Chore

* Fix traits

* Fix traits

* Test SystemFeatures

* Fix benchmarks

* Add missing benchmark

* Fix node/runtime/lib.rs

* ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts

* Keep item's config on burn if it's not empty

* Fix the merge artifacts

* Fmt

* Add SystemFeature::NoSwaps check

* Rename SystemFeatures to PalletFeatures

* Rename errors

* Add docs

* Change error message

* Rework pallet features

* Move macros

* Change comments

* Fmt

* Refactor Incrementable

* Use pub(crate) for do_* functions

* Update comments

* Refactor freeze and lock functions

* Rework Collection config and Item confg api

* Chore

* Make clippy happy

* Chore

* Update comment

* RequiredDeposit => DepositRequired

* Address comments

Co-authored-by: command-bot <>

* [Uniques V2] Refactor roles (#12437)

* Basics

* WIP: change the data format

* Refactor

* Remove redundant new() method

* Rename settings

* Enable tests

* Chore

* Change params order

* Delete the config on collection removal

* Chore

* Remove redundant system features

* Rename force_item_status to force_collection_status

* Update node runtime

* Chore

* Remove thaw_collection

* Chore

* Connect collection.is_frozen to config

* Allow to lock the collection in a new way

* Move free_holding into settings

* Connect collection's metadata locker to feature flags

* DRY

* Chore

* Connect pallet level feature flags

* Prepare tests for the new changes

* Implement Item settings

* Allow to lock the metadata or attributes of an item

* Common -> Settings

* Extract settings related code to a separate file

* Move feature flag checks inside the do_* methods

* Split settings.rs into parts

* Extract repeated code into macro

* Extract macros into their own file

* Chore

* Fix traits

* Fix traits

* Test SystemFeatures

* Fix benchmarks

* Add missing benchmark

* Fix node/runtime/lib.rs

* ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts

* Keep item's config on burn if it's not empty

* Fix the merge artifacts

* Fmt

* Add SystemFeature::NoSwaps check

* Refactor roles structure

* Rename SystemFeatures to PalletFeatures

* Rename errors

* Add docs

* Change error message

* Rework pallet features

* Move macros

* Change comments

* Fmt

* Refactor Incrementable

* Use pub(crate) for do_* functions

* Update comments

* Refactor freeze and lock functions

* Rework Collection config and Item confg api

* Chore

* Make clippy happy

* Chore

* Fix artifacts

* Address comments

* Further refactoring

* Add comments

* Add tests for group_roles_by_account()

* Update frame/nfts/src/impl_nonfungibles.rs

* Add test

* Replace Itertools group_by with a custom implementation

* ItemsNotTransferable => ItemsNonTransferable

* Update frame/nfts/src/features/roles.rs

Co-authored-by: Muharem Ismailov <ismailov.m.h@gmail.com>

* Address PR comments

* Add missed comment

Co-authored-by: command-bot <>
Co-authored-by: Muharem Ismailov <ismailov.m.h@gmail.com>

* Fix copy

* Remove storage_prefix

* Remove transactional

* Update comment

* [Uniques V2] Minting options (#12483)

* Basics

* WIP: change the data format

* Refactor

* Remove redundant new() method

* Rename settings

* Enable tests

* Chore

* Change params order

* Delete the config on collection removal

* Chore

* Remove redundant system features

* Rename force_item_status to force_collection_status

* Update node runtime

* Chore

* Remove thaw_collection

* Chore

* Connect collection.is_frozen to config

* Allow to lock the collection in a new way

* Move free_holding into settings

* Connect collection's metadata locker to feature flags

* DRY

* Chore

* Connect pallet level feature flags

* Prepare tests for the new changes

* Implement Item settings

* Allow to lock the metadata or attributes of an item

* Common -> Settings

* Extract settings related code to a separate file

* Move feature flag checks inside the do_* methods

* Split settings.rs into parts

* Extract repeated code into macro

* Extract macros into their own file

* Chore

* Fix traits

* Fix traits

* Test SystemFeatures

* Fix benchmarks

* Add missing benchmark

* Fix node/runtime/lib.rs

* ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts

* Keep item's config on burn if it's not empty

* Fix the merge artifacts

* Fmt

* Add SystemFeature::NoSwaps check

* Rename SystemFeatures to PalletFeatures

* Rename errors

* Add docs

* Change error message

* Change the format of CollectionConfig to store more data

* Move max supply to the CollectionConfig and allow to change it

* Remove ItemConfig from the mint() function and use the one set in mint settings

* Add different mint options

* Allow to change the mint settings

* Add a force_mint() method

* Check mint params

* Some optimisations

* Cover with tests

* Remove merge artifacts

* Chore

* Use the new has_role() method

* Rework item deposits

* More tests

* Refactoring

* Address comments

* Refactor lock_collection()

* Update frame/nfts/src/types.rs

Co-authored-by: Squirrel <gilescope@gmail.com>

* Update frame/nfts/src/types.rs

Co-authored-by: Squirrel <gilescope@gmail.com>

* Update frame/nfts/src/lib.rs

Co-authored-by: Squirrel <gilescope@gmail.com>

* Update frame/nfts/src/lib.rs

Co-authored-by: Squirrel <gilescope@gmail.com>

* Private => Issuer

* Add more tests

* Fix benchmarks

* Add benchmarks for new methods

* [Uniques v2] Refactoring (#12570)

* Move do_set_price() and do_buy_item() to buy_sell.rs

* Move approvals to feature file

* Move metadata to feature files

* Move the rest of methods to feature files

* Remove artifacts

* Split force_collection_status into 2 methods

* Fix benchmarks

* Fix benchmarks

* Update deps

Co-authored-by: command-bot <>
Co-authored-by: Squirrel <gilescope@gmail.com>

* [Uniques V2] Smart attributes (#12702)

* Basics

* WIP: change the data format

* Refactor

* Remove redundant new() method

* Rename settings

* Enable tests

* Chore

* Change params order

* Delete the config on collection removal

* Chore

* Remove redundant system features

* Rename force_item_status to force_collection_status

* Update node runtime

* Chore

* Remove thaw_collection

* Chore

* Connect collection.is_frozen to config

* Allow to lock the collection in a new way

* Move free_holding into settings

* Connect collection's metadata locker to feature flags

* DRY

* Chore

* Connect pallet level feature flags

* Prepare tests for the new changes

* Implement Item settings

* Allow to lock the metadata or attributes of an item

* Common -> Settings

* Extract settings related code to a separate file

* Move feature flag checks inside the do_* methods

* Split settings.rs into parts

* Extract repeated code into macro

* Extract macros into their own file

* Chore

* Fix traits

* Fix traits

* Test SystemFeatures

* Fix benchmarks

* Add missing benchmark

* Fix node/runtime/lib.rs

* ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts

* Keep item's config on burn if it's not empty

* Fix the merge artifacts

* Fmt

* Add SystemFeature::NoSwaps check

* Rename SystemFeatures to PalletFeatures

* Rename errors

* Add docs

* Change error message

* Change the format of CollectionConfig to store more data

* Move max supply to the CollectionConfig and allow to change it

* Remove ItemConfig from the mint() function and use the one set in mint settings

* Add different mint options

* Allow to change the mint settings

* Add a force_mint() method

* Check mint params

* Some optimisations

* Cover with tests

* Remove merge artifacts

* Chore

* Use the new has_role() method

* Rework item deposits

* More tests

* Refactoring

* Address comments

* Refactor lock_collection()

* Update frame/nfts/src/types.rs

Co-authored-by: Squirrel <gilescope@gmail.com>

* Update frame/nfts/src/types.rs

Co-authored-by: Squirrel <gilescope@gmail.com>

* Update frame/nfts/src/lib.rs

Co-authored-by: Squirrel <gilescope@gmail.com>

* Update frame/nfts/src/lib.rs

Co-authored-by: Squirrel <gilescope@gmail.com>

* Private => Issuer

* Add more tests

* Fix benchmarks

* Add benchmarks for new methods

* [Uniques v2] Refactoring (#12570)

* Move do_set_price() and do_buy_item() to buy_sell.rs

* Move approvals to feature file

* Move metadata to feature files

* Move the rest of methods to feature files

* Remove artifacts

* Smart attributes

* Split force_collection_status into 2 methods

* Fix benchmarks

* Fix benchmarks

* Update deps

* Fix merge artifact

* Weights + benchmarks + docs

* Change params order

* Chore

* Update frame/nfts/src/lib.rs

Co-authored-by: Squirrel <gilescope@gmail.com>

* Update frame/nfts/src/lib.rs

Co-authored-by: Squirrel <gilescope@gmail.com>

* Update docs

* Update frame/nfts/src/lib.rs

Co-authored-by: Squirrel <gilescope@gmail.com>

* Add PalletId

* Chore

* Add tests

* More tests

* Add doc

* Update errors snapshots

* Ensure we track the owner_deposit field correctly

Co-authored-by: command-bot <>
Co-authored-by: Squirrel <gilescope@gmail.com>

* [Uniques V2] Final improvements (#12736)

* Use KeyPrefixIterator instead of Box

* Change create_collection()

* Restrict from claiming NFTs twice

* Update Readme

* Remove dead code

* Refactoring

* Update readme

* Fix clippy

* Update frame/nfts/src/lib.rs

Co-authored-by: Squirrel <gilescope@gmail.com>

* ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts

* Update docs

* Typo

* Fix benchmarks

* Add more docs

* DepositRequired setting should affect only the attributes within the CollectionOwner namespace

* [NFTs] Implement missed methods to set the attributes from other pallets (#12919)

* Implement missed methods to set the attributes from other pallets

* Revert snapshots

* Update snapshot

* Update snapshot

* Revert snapshot changes

* Update snapshots

* Yet another snapshot update..

* Update frame/support/src/traits/tokens/nonfungible_v2.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update frame/support/src/traits/tokens/nonfungible_v2.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update frame/support/src/traits/tokens/nonfungible_v2.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update frame/support/src/traits/tokens/nonfungibles_v2.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update frame/nfts/src/lib.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update frame/nfts/src/lib.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update frame/nfts/src/lib.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update frame/nfts/src/lib.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update frame/nfts/src/lib.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update frame/support/src/traits/tokens/nonfungible_v2.rs

* Update frame/nfts/src/lib.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update frame/support/src/traits/tokens/nonfungibles_v2.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update frame/nfts/src/lib.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update frame/nfts/src/lib.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update frame/nfts/src/lib.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update frame/nfts/src/lib.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Address comments

* [NFTs] Add the new `owner` param to mint() method (#12997)

* Add the new `owner` param to mint() method

* Fmt

* Address comments

* ".git/.scripts/bench-bot.sh" pallet dev pallet_nfts

* Update frame/nfts/src/common_functions.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update frame/nfts/src/types.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update frame/nfts/src/types.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update frame/nfts/src/types.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update frame/nfts/src/types.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Update frame/nfts/src/types.rs

Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>

* Add call indexes

* Update snapshots

Co-authored-by: Sergej Sakac <73715684+Szegoo@users.noreply.github.com>
Co-authored-by: Squirrel <gilescope@gmail.com>
Co-authored-by: Keith Yeung <kungfukeith11@gmail.com>
Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
Co-authored-by: Muharem Ismailov <ismailov.m.h@gmail.com>
Co-authored-by: command-bot <>
Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>
This commit is contained in:
Jegor Sidorenko
2022-12-23 18:07:27 +02:00
committed by GitHub
parent 34eb463d99
commit 0edab31776
36 changed files with 9269 additions and 13 deletions
+4 -2
View File
@@ -23,9 +23,11 @@ pub mod fungibles;
pub mod imbalance;
mod misc;
pub mod nonfungible;
pub mod nonfungible_v2;
pub mod nonfungibles;
pub mod nonfungibles_v2;
pub use imbalance::Imbalance;
pub use misc::{
AssetId, Balance, BalanceConversion, BalanceStatus, DepositConsequence, ExistenceRequirement,
Locker, WithdrawConsequence, WithdrawReasons,
AssetId, AttributeNamespace, Balance, BalanceConversion, BalanceStatus, DepositConsequence,
ExistenceRequirement, Locker, WithdrawConsequence, WithdrawReasons,
};
@@ -126,6 +126,21 @@ pub enum BalanceStatus {
Reserved,
}
/// Attribute namespaces for non-fungible tokens.
#[derive(
Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, scale_info::TypeInfo, MaxEncodedLen,
)]
pub enum AttributeNamespace<AccountId> {
/// An attribute was set by the pallet.
Pallet,
/// An attribute was set by collection's owner.
CollectionOwner,
/// An attribute was set by item's owner.
ItemOwner,
/// An attribute was set by pre-approved account.
Account(AccountId),
}
bitflags::bitflags! {
/// Reasons for moving funds out of an account.
#[derive(Encode, Decode, MaxEncodedLen)]
@@ -0,0 +1,248 @@
// This file is part of Substrate.
// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd.
// 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.
//! Traits for dealing with a single non-fungible item.
//!
//! This assumes a single-level namespace identified by `Inspect::ItemId`, and could
//! reasonably be implemented by pallets that want to expose a single collection of NFT-like
//! objects.
//!
//! For an NFT API that has dual-level namespacing, the traits in `nonfungibles` are better to
//! use.
use super::nonfungibles_v2 as nonfungibles;
use crate::{
dispatch::DispatchResult,
traits::{tokens::misc::AttributeNamespace, Get},
};
use codec::{Decode, Encode};
use sp_runtime::TokenError;
use sp_std::prelude::*;
/// Trait for providing an interface to a read-only NFT-like item.
pub trait Inspect<AccountId> {
/// Type for identifying an item.
type ItemId;
/// Returns the owner of `item`, or `None` if the item doesn't exist or has no
/// owner.
fn owner(item: &Self::ItemId) -> Option<AccountId>;
/// Returns the attribute value of `item` corresponding to `key`.
///
/// By default this is `None`; no attributes are defined.
fn attribute(
_item: &Self::ItemId,
_namespace: &AttributeNamespace<AccountId>,
_key: &[u8],
) -> Option<Vec<u8>> {
None
}
/// Returns the strongly-typed attribute value of `item` corresponding to `key`.
///
/// By default this just attempts to use `attribute`.
fn typed_attribute<K: Encode, V: Decode>(
item: &Self::ItemId,
namespace: &AttributeNamespace<AccountId>,
key: &K,
) -> Option<V> {
key.using_encoded(|d| Self::attribute(item, namespace, d))
.and_then(|v| V::decode(&mut &v[..]).ok())
}
/// Returns `true` if the `item` may be transferred.
///
/// Default implementation is that all items are transferable.
fn can_transfer(_item: &Self::ItemId) -> bool {
true
}
}
/// Interface for enumerating items in existence or owned by a given account over a collection
/// of NFTs.
pub trait InspectEnumerable<AccountId>: Inspect<AccountId> {
/// The iterator type for [`Self::items`].
type ItemsIterator: Iterator<Item = Self::ItemId>;
/// The iterator type for [`Self::owned`].
type OwnedIterator: Iterator<Item = Self::ItemId>;
/// Returns an iterator of the items within a `collection` in existence.
fn items() -> Self::ItemsIterator;
/// Returns an iterator of the items of all collections owned by `who`.
fn owned(who: &AccountId) -> Self::OwnedIterator;
}
/// Trait for providing an interface for NFT-like items which may be minted, burned and/or have
/// attributes set on them.
pub trait Mutate<AccountId, ItemConfig>: Inspect<AccountId> {
/// Mint some `item` to be owned by `who`.
///
/// By default, this is not a supported operation.
fn mint_into(
_item: &Self::ItemId,
_who: &AccountId,
_config: &ItemConfig,
_deposit_collection_owner: bool,
) -> DispatchResult {
Err(TokenError::Unsupported.into())
}
/// Burn some `item`.
///
/// By default, this is not a supported operation.
fn burn(_item: &Self::ItemId, _maybe_check_owner: Option<&AccountId>) -> DispatchResult {
Err(TokenError::Unsupported.into())
}
/// Set attribute `value` of `item`'s `key`.
///
/// By default, this is not a supported operation.
fn set_attribute(_item: &Self::ItemId, _key: &[u8], _value: &[u8]) -> DispatchResult {
Err(TokenError::Unsupported.into())
}
/// Attempt to set the strongly-typed attribute `value` of `item`'s `key`.
///
/// By default this just attempts to use `set_attribute`.
fn set_typed_attribute<K: Encode, V: Encode>(
item: &Self::ItemId,
key: &K,
value: &V,
) -> DispatchResult {
key.using_encoded(|k| value.using_encoded(|v| Self::set_attribute(item, k, v)))
}
}
/// Trait for transferring a non-fungible item.
pub trait Transfer<AccountId>: Inspect<AccountId> {
/// Transfer `item` into `destination` account.
fn transfer(item: &Self::ItemId, destination: &AccountId) -> DispatchResult;
}
/// Convert a `nonfungibles` trait implementation into a `nonfungible` trait implementation by
/// identifying a single item.
pub struct ItemOf<
F: nonfungibles::Inspect<AccountId>,
A: Get<<F as nonfungibles::Inspect<AccountId>>::CollectionId>,
AccountId,
>(sp_std::marker::PhantomData<(F, A, AccountId)>);
impl<
F: nonfungibles::Inspect<AccountId>,
A: Get<<F as nonfungibles::Inspect<AccountId>>::CollectionId>,
AccountId,
> Inspect<AccountId> for ItemOf<F, A, AccountId>
{
type ItemId = <F as nonfungibles::Inspect<AccountId>>::ItemId;
fn owner(item: &Self::ItemId) -> Option<AccountId> {
<F as nonfungibles::Inspect<AccountId>>::owner(&A::get(), item)
}
fn attribute(
item: &Self::ItemId,
namespace: &AttributeNamespace<AccountId>,
key: &[u8],
) -> Option<Vec<u8>> {
<F as nonfungibles::Inspect<AccountId>>::attribute(&A::get(), item, namespace, key)
}
fn typed_attribute<K: Encode, V: Decode>(
item: &Self::ItemId,
namespace: &AttributeNamespace<AccountId>,
key: &K,
) -> Option<V> {
<F as nonfungibles::Inspect<AccountId>>::typed_attribute(&A::get(), item, namespace, key)
}
fn can_transfer(item: &Self::ItemId) -> bool {
<F as nonfungibles::Inspect<AccountId>>::can_transfer(&A::get(), item)
}
}
impl<
F: nonfungibles::InspectEnumerable<AccountId>,
A: Get<<F as nonfungibles::Inspect<AccountId>>::CollectionId>,
AccountId,
> InspectEnumerable<AccountId> for ItemOf<F, A, AccountId>
{
type ItemsIterator = <F as nonfungibles::InspectEnumerable<AccountId>>::ItemsIterator;
type OwnedIterator =
<F as nonfungibles::InspectEnumerable<AccountId>>::OwnedInCollectionIterator;
fn items() -> Self::ItemsIterator {
<F as nonfungibles::InspectEnumerable<AccountId>>::items(&A::get())
}
fn owned(who: &AccountId) -> Self::OwnedIterator {
<F as nonfungibles::InspectEnumerable<AccountId>>::owned_in_collection(&A::get(), who)
}
}
impl<
F: nonfungibles::Mutate<AccountId, ItemConfig>,
A: Get<<F as nonfungibles::Inspect<AccountId>>::CollectionId>,
AccountId,
ItemConfig,
> Mutate<AccountId, ItemConfig> for ItemOf<F, A, AccountId>
{
fn mint_into(
item: &Self::ItemId,
who: &AccountId,
config: &ItemConfig,
deposit_collection_owner: bool,
) -> DispatchResult {
<F as nonfungibles::Mutate<AccountId, ItemConfig>>::mint_into(
&A::get(),
item,
who,
config,
deposit_collection_owner,
)
}
fn burn(item: &Self::ItemId, maybe_check_owner: Option<&AccountId>) -> DispatchResult {
<F as nonfungibles::Mutate<AccountId, ItemConfig>>::burn(&A::get(), item, maybe_check_owner)
}
fn set_attribute(item: &Self::ItemId, key: &[u8], value: &[u8]) -> DispatchResult {
<F as nonfungibles::Mutate<AccountId, ItemConfig>>::set_attribute(
&A::get(),
item,
key,
value,
)
}
fn set_typed_attribute<K: Encode, V: Encode>(
item: &Self::ItemId,
key: &K,
value: &V,
) -> DispatchResult {
<F as nonfungibles::Mutate<AccountId, ItemConfig>>::set_typed_attribute(
&A::get(),
item,
key,
value,
)
}
}
impl<
F: nonfungibles::Transfer<AccountId>,
A: Get<<F as nonfungibles::Inspect<AccountId>>::CollectionId>,
AccountId,
> Transfer<AccountId> for ItemOf<F, A, AccountId>
{
fn transfer(item: &Self::ItemId, destination: &AccountId) -> DispatchResult {
<F as nonfungibles::Transfer<AccountId>>::transfer(&A::get(), item, destination)
}
}
@@ -0,0 +1,257 @@
// This file is part of Substrate.
// Copyright (C) 2019-2022 Parity Technologies (UK) Ltd.
// 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.
//! Traits for dealing with multiple collections of non-fungible items.
//!
//! This assumes a dual-level namespace identified by `Inspect::ItemId`, and could
//! reasonably be implemented by pallets which want to expose multiple independent collections of
//! NFT-like objects.
//!
//! For an NFT API which has single-level namespacing, the traits in `nonfungible` are better to
//! use.
//!
//! Implementations of these traits may be converted to implementations of corresponding
//! `nonfungible` traits by using the `nonfungible::ItemOf` type adapter.
use crate::{
dispatch::{DispatchError, DispatchResult},
traits::tokens::misc::AttributeNamespace,
};
use codec::{Decode, Encode};
use sp_runtime::TokenError;
use sp_std::prelude::*;
/// Trait for providing an interface to many read-only NFT-like sets of items.
pub trait Inspect<AccountId> {
/// Type for identifying an item.
type ItemId;
/// Type for identifying a collection (an identifier for an independent collection of
/// items).
type CollectionId;
/// Returns the owner of `item` of `collection`, or `None` if the item doesn't exist
/// (or somehow has no owner).
fn owner(collection: &Self::CollectionId, item: &Self::ItemId) -> Option<AccountId>;
/// Returns the owner of the `collection`, if there is one. For many NFTs this may not
/// make any sense, so users of this API should not be surprised to find a collection
/// results in `None` here.
fn collection_owner(_collection: &Self::CollectionId) -> Option<AccountId> {
None
}
/// Returns the attribute value of `item` of `collection` corresponding to `key`.
///
/// By default this is `None`; no attributes are defined.
fn attribute(
_collection: &Self::CollectionId,
_item: &Self::ItemId,
_namespace: &AttributeNamespace<AccountId>,
_key: &[u8],
) -> Option<Vec<u8>> {
None
}
/// Returns the strongly-typed attribute value of `item` of `collection` corresponding to
/// `key`.
///
/// By default this just attempts to use `attribute`.
fn typed_attribute<K: Encode, V: Decode>(
collection: &Self::CollectionId,
item: &Self::ItemId,
namespace: &AttributeNamespace<AccountId>,
key: &K,
) -> Option<V> {
key.using_encoded(|d| Self::attribute(collection, item, namespace, d))
.and_then(|v| V::decode(&mut &v[..]).ok())
}
/// Returns the attribute value of `collection` corresponding to `key`.
///
/// By default this is `None`; no attributes are defined.
fn collection_attribute(_collection: &Self::CollectionId, _key: &[u8]) -> Option<Vec<u8>> {
None
}
/// Returns the strongly-typed attribute value of `collection` corresponding to `key`.
///
/// By default this just attempts to use `collection_attribute`.
fn typed_collection_attribute<K: Encode, V: Decode>(
collection: &Self::CollectionId,
key: &K,
) -> Option<V> {
key.using_encoded(|d| Self::collection_attribute(collection, d))
.and_then(|v| V::decode(&mut &v[..]).ok())
}
/// 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 {
true
}
}
/// Interface for enumerating items in existence or owned by a given account over many collections
/// of NFTs.
pub trait InspectEnumerable<AccountId>: Inspect<AccountId> {
/// The iterator type for [`Self::collections`].
type CollectionsIterator: Iterator<Item = Self::CollectionId>;
/// The iterator type for [`Self::items`].
type ItemsIterator: Iterator<Item = Self::ItemId>;
/// The iterator type for [`Self::owned`].
type OwnedIterator: Iterator<Item = (Self::CollectionId, Self::ItemId)>;
/// The iterator type for [`Self::owned_in_collection`].
type OwnedInCollectionIterator: Iterator<Item = Self::ItemId>;
/// Returns an iterator of the collections in existence.
fn collections() -> Self::CollectionsIterator;
/// Returns an iterator of the items of a `collection` in existence.
fn items(collection: &Self::CollectionId) -> Self::ItemsIterator;
/// Returns an iterator of the items of all collections owned by `who`.
fn owned(who: &AccountId) -> Self::OwnedIterator;
/// Returns an iterator of the items of `collection` owned by `who`.
fn owned_in_collection(
collection: &Self::CollectionId,
who: &AccountId,
) -> Self::OwnedInCollectionIterator;
}
/// Trait for providing the ability to create collections of nonfungible items.
pub trait Create<AccountId, CollectionConfig>: Inspect<AccountId> {
/// Create a `collection` of nonfungible items to be owned by `who` and managed by `admin`.
fn create_collection(
who: &AccountId,
admin: &AccountId,
config: &CollectionConfig,
) -> Result<Self::CollectionId, DispatchError>;
}
/// Trait for providing the ability to destroy collections of nonfungible items.
pub trait Destroy<AccountId>: Inspect<AccountId> {
/// The witness data needed to destroy an item.
type DestroyWitness;
/// Provide the appropriate witness data needed to destroy an item.
fn get_destroy_witness(collection: &Self::CollectionId) -> Option<Self::DestroyWitness>;
/// Destroy an existing fungible item.
/// * `collection`: The `CollectionId` to be destroyed.
/// * `witness`: Any witness data that needs to be provided to complete the operation
/// successfully.
/// * `maybe_check_owner`: An optional `AccountId` that can be used to authorize the destroy
/// command. If not provided, we will not do any authorization checks before destroying the
/// item.
///
/// If successful, this function will return the actual witness data from the destroyed item.
/// This may be different than the witness data provided, and can be used to refund weight.
fn destroy(
collection: Self::CollectionId,
witness: Self::DestroyWitness,
maybe_check_owner: Option<AccountId>,
) -> Result<Self::DestroyWitness, DispatchError>;
}
/// Trait for providing an interface for multiple collections of NFT-like items which may be
/// minted, burned and/or have attributes set on them.
pub trait Mutate<AccountId, ItemConfig>: Inspect<AccountId> {
/// Mint some `item` of `collection` to be owned by `who`.
///
/// By default, this is not a supported operation.
fn mint_into(
_collection: &Self::CollectionId,
_item: &Self::ItemId,
_who: &AccountId,
_config: &ItemConfig,
_deposit_collection_owner: bool,
) -> DispatchResult {
Err(TokenError::Unsupported.into())
}
/// Burn some `item` of `collection`.
///
/// By default, this is not a supported operation.
fn burn(
_collection: &Self::CollectionId,
_item: &Self::ItemId,
_maybe_check_owner: Option<&AccountId>,
) -> DispatchResult {
Err(TokenError::Unsupported.into())
}
/// Set attribute `value` of `item` of `collection`'s `key`.
///
/// By default, this is not a supported operation.
fn set_attribute(
_collection: &Self::CollectionId,
_item: &Self::ItemId,
_key: &[u8],
_value: &[u8],
) -> DispatchResult {
Err(TokenError::Unsupported.into())
}
/// Attempt to set the strongly-typed attribute `value` of `item` of `collection`'s `key`.
///
/// By default this just attempts to use `set_attribute`.
fn set_typed_attribute<K: Encode, V: Encode>(
collection: &Self::CollectionId,
item: &Self::ItemId,
key: &K,
value: &V,
) -> DispatchResult {
key.using_encoded(|k| value.using_encoded(|v| Self::set_attribute(collection, item, k, v)))
}
/// Set attribute `value` of `collection`'s `key`.
///
/// By default, this is not a supported operation.
fn set_collection_attribute(
_collection: &Self::CollectionId,
_key: &[u8],
_value: &[u8],
) -> DispatchResult {
Err(TokenError::Unsupported.into())
}
/// Attempt to set the strongly-typed attribute `value` of `collection`'s `key`.
///
/// By default this just attempts to use `set_attribute`.
fn set_typed_collection_attribute<K: Encode, V: Encode>(
collection: &Self::CollectionId,
key: &K,
value: &V,
) -> DispatchResult {
key.using_encoded(|k| {
value.using_encoded(|v| Self::set_collection_attribute(collection, k, v))
})
}
}
/// Trait for transferring non-fungible sets of items.
pub trait Transfer<AccountId>: Inspect<AccountId> {
/// Transfer `item` of `collection` into `destination` account.
fn transfer(
collection: &Self::CollectionId,
item: &Self::ItemId,
destination: &AccountId,
) -> DispatchResult;
}