From c30ece2bd8dcbbf8b710a197e770424634c48d47 Mon Sep 17 00:00:00 2001 From: Alexander Popiak Date: Thu, 1 Jul 2021 23:34:17 +0200 Subject: [PATCH] Implement `InspectEnumerable` for Uniques (#9117) * implement InspectEnumerable in pallet_uniques * use `iter_keys` and `iter_key_prefix` * return an iterator instead of constructing a vec * update comments * additional warning about storage reads Co-authored-by: Shawn Tabrizi --- .../support/src/traits/tokens/nonfungible.rs | 14 ++++---- .../support/src/traits/tokens/nonfungibles.rs | 18 +++++------ .../frame/uniques/src/impl_nonfungibles.rs | 32 ++++++++++++++++++- 3 files changed, 45 insertions(+), 19 deletions(-) diff --git a/substrate/frame/support/src/traits/tokens/nonfungible.rs b/substrate/frame/support/src/traits/tokens/nonfungible.rs index 348d830c50..27e6cf8126 100644 --- a/substrate/frame/support/src/traits/tokens/nonfungible.rs +++ b/substrate/frame/support/src/traits/tokens/nonfungible.rs @@ -61,14 +61,12 @@ pub trait Inspect { /// Interface for enumerating assets in existence or owned by a given account over a collection /// of NFTs. -/// -/// WARNING: These may be a heavy operations. Do not use when execution time is limited. pub trait InspectEnumerable: Inspect { - /// Returns the instances of an asset `class` in existence. - fn instances() -> Vec; + /// Returns an iterator of the instances of an asset `class` in existence. + fn instances() -> Box>; - /// Returns the asset instances of all classes owned by `who`. - fn owned(who: &AccountId) -> Vec; + /// Returns an iterator of the asset instances of all classes owned by `who`. + fn owned(who: &AccountId) -> Box>; } /// Trait for providing an interface for NFT-like assets which may be minted, burned and/or have @@ -148,10 +146,10 @@ impl< A: Get<>::ClassId>, AccountId, > InspectEnumerable for ItemOf { - fn instances() -> Vec { + fn instances() -> Box> { >::instances(&A::get()) } - fn owned(who: &AccountId) -> Vec { + fn owned(who: &AccountId) -> Box> { >::owned_in_class(&A::get(), who) } } diff --git a/substrate/frame/support/src/traits/tokens/nonfungibles.rs b/substrate/frame/support/src/traits/tokens/nonfungibles.rs index 56db553d83..b50c5f4d98 100644 --- a/substrate/frame/support/src/traits/tokens/nonfungibles.rs +++ b/substrate/frame/support/src/traits/tokens/nonfungibles.rs @@ -95,20 +95,18 @@ pub trait Inspect { /// Interface for enumerating assets in existence or owned by a given account over many collections /// of NFTs. -/// -/// WARNING: These may be a heavy operations. Do not use when execution time is limited. pub trait InspectEnumerable: Inspect { - /// Returns the asset classes in existence. - fn classes() -> Vec; + /// Returns an iterator of the asset classes in existence. + fn classes() -> Box>; - /// Returns the instances of an asset `class` in existence. - fn instances(class: &Self::ClassId) -> Vec; + /// Returns an iterator of the instances of an asset `class` in existence. + fn instances(class: &Self::ClassId) -> Box>; - /// Returns the asset instances of all classes owned by `who`. - fn owned(who: &AccountId) -> Vec<(Self::ClassId, Self::InstanceId)>; + /// Returns an iterator of the asset instances of all classes owned by `who`. + fn owned(who: &AccountId) -> Box>; - /// Returns the asset instances of `class` owned by `who`. - fn owned_in_class(class: &Self::ClassId, who: &AccountId) -> Vec; + /// Returns an iterator of the asset instances of `class` owned by `who`. + fn owned_in_class(class: &Self::ClassId, who: &AccountId) -> Box>; } /// Trait for providing an interface for multiple classes of NFT-like assets which may be minted, diff --git a/substrate/frame/uniques/src/impl_nonfungibles.rs b/substrate/frame/uniques/src/impl_nonfungibles.rs index c856e2cc55..7113f31469 100644 --- a/substrate/frame/uniques/src/impl_nonfungibles.rs +++ b/substrate/frame/uniques/src/impl_nonfungibles.rs @@ -19,7 +19,7 @@ use super::*; use sp_std::convert::TryFrom; -use frame_support::traits::tokens::nonfungibles::{Inspect, Mutate, Transfer}; +use frame_support::traits::tokens::nonfungibles::{Inspect, InspectEnumerable, Mutate, Transfer}; use frame_support::BoundedSlice; use sp_runtime::DispatchResult; @@ -106,3 +106,33 @@ impl, I: 'static> Transfer for Pallet { Self::do_transfer(class.clone(), instance.clone(), destination.clone(), |_, _| Ok(())) } } + +impl, I: 'static> InspectEnumerable for Pallet { + /// Returns an iterator of the asset classes in existence. + /// + /// NOTE: iterating this list invokes a storage read per item. + fn classes() -> Box> { + Box::new(ClassMetadataOf::::iter_keys()) + } + + /// Returns an iterator of the instances of an asset `class` in existence. + /// + /// NOTE: iterating this list invokes a storage read per item. + fn instances(class: &Self::ClassId) -> Box> { + Box::new(InstanceMetadataOf::::iter_key_prefix(class)) + } + + /// Returns an iterator of the asset instances of all classes owned by `who`. + /// + /// NOTE: iterating this list invokes a storage read per item. + fn owned(who: &T::AccountId) -> Box> { + Box::new(Account::::iter_key_prefix((who,))) + } + + /// Returns an iterator of the asset instances of `class` owned by `who`. + /// + /// NOTE: iterating this list invokes a storage read per item. + fn owned_in_class(class: &Self::ClassId, who: &T::AccountId) -> Box> { + Box::new(Account::::iter_key_prefix((who, class))) + } +}