difftreelog
feat initial rmrk send impl
in: master
10 files changed
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -1298,6 +1298,7 @@
spender: T::CrossAccountId,
token: TokenId,
amount: u128,
+ nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo;
fn transfer_from(
&self,
pallets/fungible/src/common.rsdiffbeforeafterboth--- a/pallets/fungible/src/common.rs
+++ b/pallets/fungible/src/common.rs
@@ -226,6 +226,7 @@
spender: T::CrossAccountId,
token: TokenId,
amount: u128,
+ _nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo {
ensure!(
token == TokenId::default(),
pallets/nonfungible/src/common.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/common.rs
+++ b/pallets/nonfungible/src/common.rs
@@ -308,14 +308,15 @@
spender: T::CrossAccountId,
token: TokenId,
amount: u128,
+ nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo {
ensure!(amount <= 1, <Error<T>>::NonfungibleItemsHaveNoAmount);
with_weight(
if amount == 1 {
- <Pallet<T>>::set_allowance(self, &sender, token, Some(&spender))
+ <Pallet<T>>::set_allowance(self, &sender, token, Some(&spender), nesting_budget)
} else {
- <Pallet<T>>::set_allowance(self, &sender, token, None)
+ <Pallet<T>>::set_allowance(self, &sender, token, None, nesting_budget)
},
<CommonWeights<T>>::approve(),
)
pallets/nonfungible/src/erc.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -269,8 +269,11 @@
let caller = T::CrossAccountId::from_eth(caller);
let approved = T::CrossAccountId::from_eth(approved);
let token = token_id.try_into()?;
+ let budget = self
+ .recorder
+ .weight_calls_budget(<StructureWeight<T>>::find_parent());
- <Pallet<T>>::set_allowance(self, &caller, token, Some(&approved))
+ <Pallet<T>>::set_allowance(self, &caller, token, Some(&approved), &budget)
.map_err(dispatch_to_evm::<T>)?;
Ok(())
}
pallets/nonfungible/src/lib.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -878,6 +878,7 @@
sender: &T::CrossAccountId,
token: TokenId,
spender: Option<&T::CrossAccountId>,
+ nesting_budget: &dyn Budget,
) -> DispatchResult {
if collection.permissions.access() == AccessMode::AllowList {
collection.check_allowlist(sender)?;
@@ -889,9 +890,16 @@
if let Some(spender) = spender {
<PalletCommon<T>>::ensure_correct_receiver(spender)?;
}
- let token_data =
- <TokenData<T>>::get((collection.id, token)).ok_or(<CommonError<T>>::TokenNotFound)?;
- if &token_data.owner != sender {
+
+ let is_owned = <PalletStructure<T>>::check_indirectly_owned(
+ sender.clone(),
+ collection.id,
+ token,
+ None,
+ nesting_budget
+ )?;
+
+ if !is_owned {
ensure!(
collection.ignores_owned_amount(sender),
<CommonError<T>>::CantApproveMoreThanOwned
@@ -918,6 +926,9 @@
// `from`, `to` checked in [`transfer`]
collection.check_allowlist(spender)?;
}
+ if <Allowance<T>>::get((collection.id, token)).as_ref() == Some(spender) {
+ return Ok(());
+ }
if let Some(source) = T::CrossTokenAddressMapping::address_to_token(from) {
// TODO: should collection owner be allowed to perform this transfer?
ensure!(
@@ -930,9 +941,6 @@
)?,
<CommonError<T>>::ApprovedValueTooLow,
);
- return Ok(());
- }
- if <Allowance<T>>::get((collection.id, token)).as_ref() == Some(spender) {
return Ok(());
}
ensure!(
pallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-core/src/lib.rs
+++ b/pallets/proxy-rmrk-core/src/lib.rs
@@ -20,7 +20,7 @@
use frame_system::{pallet_prelude::*, ensure_signed};
use sp_runtime::{DispatchError, Permill, traits::StaticLookup};
use sp_std::vec::Vec;
-use up_data_structs::*;
+use up_data_structs::{*, mapping::TokenAddressMapping};
use pallet_common::{
Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations,
};
@@ -39,6 +39,8 @@
use RmrkProperty::*;
+const NESTING_BUDGET: u32 = 5;
+
#[frame_support::pallet]
pub mod pallet {
use super::*;
@@ -56,10 +58,13 @@
pub type CollectionIndex<T: Config> = StorageValue<_, RmrkCollectionId, ValueQuery>;
#[pallet::storage]
- #[pallet::getter(fn collection_index_map)]
- pub type CollectionIndexMap<T: Config> =
+ pub type UniqueCollectionId<T: Config> =
StorageMap<_, Twox64Concat, RmrkCollectionId, CollectionId, ValueQuery>;
+ #[pallet::storage]
+ pub type RmrkInernalCollectionId<T: Config> =
+ StorageMap<_, Twox64Concat, CollectionId, RmrkCollectionId, ValueQuery>;
+
#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
pub struct Pallet<T>(_);
@@ -151,10 +156,12 @@
.into_inner()
.try_into()
.map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,
+ permissions: Some(CollectionPermissions {
+ nesting: Some(NestingRule::Owner),
+ ..Default::default()
+ }),
..Default::default()
};
-
- <CollectionIndex<T>>::mutate(|n| *n += 1);
let unique_collection_id = Self::init_collection(
T::CrossAccountId::from_sub(sender.clone()),
@@ -167,7 +174,10 @@
)?;
let rmrk_collection_id = <CollectionIndex<T>>::get();
- <CollectionIndexMap<T>>::insert(rmrk_collection_id, unique_collection_id);
+ <UniqueCollectionId<T>>::insert(rmrk_collection_id, unique_collection_id);
+ <RmrkInernalCollectionId<T>>::insert(unique_collection_id, rmrk_collection_id);
+
+ <CollectionIndex<T>>::mutate(|n| *n += 1);
Self::deposit_event(Event::CollectionCreated {
issuer: sender,
@@ -356,6 +366,81 @@
#[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
#[transactional]
+ pub fn send(
+ origin: OriginFor<T>,
+ rmrk_collection_id: RmrkCollectionId,
+ rmrk_nft_id: RmrkNftId,
+ new_owner: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,
+ ) -> DispatchResult {
+ let sender = ensure_signed(origin.clone())?;
+ let cross_sender = T::CrossAccountId::from_sub(sender.clone());
+
+ let collection_id = Self::unique_collection_id(rmrk_collection_id)?;
+ let nft_id = rmrk_nft_id.into();
+
+ let token_data = <TokenData<T>>::get((collection_id, nft_id))
+ .ok_or(<Error<T>>::NoAvailableNftId)?;
+
+ let from = token_data.owner;
+
+ let collection = Self::get_typed_nft_collection(
+ collection_id,
+ misc::CollectionType::Regular,
+ )?;
+
+ let budget = budget::Value::new(NESTING_BUDGET);
+
+ let target_owner;
+
+ match new_owner {
+ RmrkAccountIdOrCollectionNftTuple::AccountId(account_id) => {
+ target_owner = T::CrossAccountId::from_sub(account_id);
+ },
+ RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(target_collection_id, target_nft_id) => {
+ let target_collection_id = Self::unique_collection_id(target_collection_id)?;
+
+ target_owner = T::CrossTokenAddressMapping::token_to_address(
+ target_collection_id,
+ target_nft_id.into(),
+ );
+
+ let spender = <PalletStructure<T>>::get_indirect_owner(
+ target_collection_id,
+ target_nft_id.into(),
+ Some((collection_id, nft_id)),
+ &budget,
+ )?;
+
+ let is_approval_required = cross_sender != spender;
+
+ if is_approval_required {
+ <PalletNft<T>>::set_allowance(
+ &collection,
+ &cross_sender,
+ nft_id,
+ Some(&spender),
+ &budget
+ ).map_err(Self::map_common_err_to_proxy)?;
+
+ return Ok(());
+ }
+ }
+ }
+
+ <PalletNft<T>>::transfer_from(
+ &collection,
+ &cross_sender,
+ &from,
+ &target_owner,
+ nft_id,
+ &budget
+ ).map_err(Self::map_common_err_to_proxy)?;
+
+ Ok(())
+ }
+
+ #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))]
+ #[transactional]
pub fn set_property(
origin: OriginFor<T>,
#[pallet::compact] rmrk_collection_id: RmrkCollectionId,
@@ -367,12 +452,13 @@
let sender = T::CrossAccountId::from_sub(sender);
let collection_id = Self::unique_collection_id(rmrk_collection_id)?;
+ let budget = budget::Value::new(NESTING_BUDGET);
match maybe_nft_id {
Some(nft_id) => {
let token_id: TokenId = nft_id.into();
- Self::ensure_nft_owner(collection_id, token_id, &sender)?;
+ Self::ensure_nft_owner(collection_id, token_id, &sender, &budget)?;
Self::ensure_nft_type(collection_id, token_id, NftType::Regular)?;
<PalletNft<T>>::set_scoped_token_property(
@@ -607,7 +693,7 @@
owner: owner.clone(),
};
- let budget = budget::Value::new(2);
+ let budget = budget::Value::new(NESTING_BUDGET);
<PalletNft<T>>::create_item(collection, sender, data, &budget)?;
@@ -651,14 +737,8 @@
//ensure!(!Pallet::<T>::is_locked(collection_id, nft_id), pallet_uniques::Error::<T>::Locked);
let sender = T::CrossAccountId::from_sub(sender);
- let budget = budget::Value::new(10);
- let pending = !<PalletStructure<T>>::check_indirectly_owned(
- sender.clone(),
- collection_id,
- token_id,
- None,
- &budget,
- )?;
+ let budget = budget::Value::new(NESTING_BUDGET);
+ let pending = Self::ensure_nft_owner(collection_id, token_id, &sender, &budget).is_err();
let resource_collection_id: CollectionId =
Self::get_nft_property_decoded(collection_id, token_id, ResourceCollection)?;
@@ -757,7 +837,14 @@
pub fn unique_collection_id(
rmrk_collection_id: RmrkCollectionId,
) -> Result<CollectionId, DispatchError> {
- <CollectionIndexMap<T>>::try_get(rmrk_collection_id)
+ <UniqueCollectionId<T>>::try_get(rmrk_collection_id)
+ .map_err(|_| <Error<T>>::CollectionUnknown.into())
+ }
+
+ pub fn rmrk_collection_id(
+ unique_collection_id: CollectionId
+ ) -> Result<RmrkCollectionId, DispatchError> {
+ <RmrkInernalCollectionId<T>>::try_get(unique_collection_id)
.map_err(|_| <Error<T>>::CollectionUnknown.into())
}
@@ -873,12 +960,18 @@
collection_id: CollectionId,
token_id: TokenId,
possible_owner: &T::CrossAccountId,
+ nesting_budget: &dyn budget::Budget
) -> DispatchResult {
- let token_data =
- <TokenData<T>>::get((collection_id, token_id)).ok_or(<Error<T>>::NoAvailableNftId)?;
+ let is_owned = <PalletStructure<T>>::check_indirectly_owned(
+ possible_owner.clone(),
+ collection_id,
+ token_id,
+ None,
+ nesting_budget,
+ )?;
ensure!(
- token_data.owner == *possible_owner,
+ is_owned,
<Error<T>>::NoPermission
);
@@ -965,7 +1058,8 @@
NoPermission => NoPermission,
CollectionTokenLimitExceeded => CollectionFullOrLocked,
PublicMintingNotAllowed => NoPermission,
- TokenNotFound => NoAvailableNftId
+ TokenNotFound => NoAvailableNftId,
+ ApprovedValueTooLow => NoPermission
}
}
}
pallets/refungible/src/common.rsdiffbeforeafterboth--- a/pallets/refungible/src/common.rs
+++ b/pallets/refungible/src/common.rs
@@ -254,6 +254,7 @@
spender: T::CrossAccountId,
token: TokenId,
amount: u128,
+ _nesting_budget: &dyn Budget,
) -> DispatchResultWithPostInfo {
with_weight(
<Pallet<T>>::set_allowance(self, &sender, &spender, token, amount),
pallets/structure/src/lib.rsdiffbeforeafterboth--- a/pallets/structure/src/lib.rs
+++ b/pallets/structure/src/lib.rs
@@ -149,19 +149,12 @@
})
}
- /// Check if token indirectly owned by specified user
- pub fn check_indirectly_owned(
- user: T::CrossAccountId,
+ pub fn get_indirect_owner(
collection: CollectionId,
token: TokenId,
for_nest: Option<(CollectionId, TokenId)>,
budget: &dyn Budget,
- ) -> Result<bool, DispatchError> {
- let target_parent = match T::CrossTokenAddressMapping::address_to_token(&user) {
- Some((collection, token)) => Self::find_topmost_owner(collection, token, budget)?,
- None => user,
- };
-
+ ) -> Result<T::CrossAccountId, DispatchError> {
// Tried to nest token in itself
if Some((collection, token)) == for_nest {
return Err(<Error<T>>::OuroborosDetected.into());
@@ -173,10 +166,8 @@
Parent::Token(collection, token) if Some((collection, token)) == for_nest => {
return Err(<Error<T>>::OuroborosDetected.into())
}
- // Found needed parent, token is indirecty owned
- Parent::User(user) if user == target_parent => return Ok(true),
// Token is owned by other user
- Parent::User(_) => return Ok(false),
+ Parent::User(user) => return Ok(user),
Parent::TokenNotFound => return Err(<Error<T>>::TokenNotFound.into()),
// Continue parent chain
Parent::Token(_, _) => {}
@@ -199,6 +190,27 @@
dispatch.burn_item_recursively(from.clone(), token, self_budget, breadth_budget)
}
+ /// Check if token indirectly owned by specified user
+ pub fn check_indirectly_owned(
+ user: T::CrossAccountId,
+ collection: CollectionId,
+ token: TokenId,
+ for_nest: Option<(CollectionId, TokenId)>,
+ budget: &dyn Budget,
+ ) -> Result<bool, DispatchError> {
+ let target_parent = match T::CrossTokenAddressMapping::address_to_token(&user) {
+ Some((collection, token)) => Self::find_topmost_owner(collection, token, budget)?,
+ None => user,
+ };
+
+ Self::get_indirect_owner(
+ collection,
+ token,
+ for_nest,
+ budget
+ ).map(|indirect_owner| indirect_owner == target_parent)
+ }
+
pub fn check_nesting(
from: T::CrossAccountId,
under: &T::CrossAccountId,
pallets/unique/src/lib.rsdiffbeforeafterboth--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -815,8 +815,9 @@
#[transactional]
pub fn approve(origin, spender: T::CrossAccountId, collection_id: CollectionId, item_id: TokenId, amount: u128) -> DispatchResultWithPostInfo {
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
+ let budget = budget::Value::new(NESTING_BUDGET);
- dispatch_call::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount))
+ dispatch_call::<T, _>(collection_id, |d| d.approve(sender, spender, item_id, amount, &budget))
}
/// Change ownership of a NFT on behalf of the owner. See Approve method for additional information. After this method executes, the approval is removed so that the approved address will not be able to transfer this NFT again from this owner.
runtime/common/src/runtime_apis.rsdiffbeforeafterboth147 use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};147 use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};148 use pallet_common::CommonCollectionOperations;148 use pallet_common::CommonCollectionOperations;149149150 let collection_id = RmrkCore::unique_collection_id(collection_id)?;150 let collection_id = match RmrkCore::unique_collection_id(collection_id) {151 Ok(id) => id,152 Err(_) => return Ok(None)153 };154151 let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {155 let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {152 Ok(c) => c,156 Ok(c) => c,169 use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};173 use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};170 use pallet_common::CommonCollectionOperations;174 use pallet_common::CommonCollectionOperations;171175172 let collection_id = RmrkCore::unique_collection_id(collection_id)?;176 let collection_id = match RmrkCore::unique_collection_id(collection_id) {177 Ok(id) => id,178 Err(_) => return Ok(None)179 };173 let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {180 let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {174 Ok(c) => c,181 Ok(c) => c,175 Err(_) => return Ok(None),182 Err(_) => return Ok(None),180187181 let owner = match collection.token_owner(nft_id) {188 let owner = match collection.token_owner(nft_id) {182 Some(owner) => match <Runtime as pallet_common::Config>::CrossTokenAddressMapping::address_to_token(&owner) {189 Some(owner) => match <Runtime as pallet_common::Config>::CrossTokenAddressMapping::address_to_token(&owner) {183 Some((col, tok)) => RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(col.0, tok.0),190 Some((col, tok)) => {191 let rmrk_collection = RmrkCore::rmrk_collection_id(col)?;192193 RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(rmrk_collection, tok.0)194 }184 None => RmrkAccountIdOrCollectionNftTuple::AccountId(owner.as_sub().clone())195 None => RmrkAccountIdOrCollectionNftTuple::AccountId(owner.as_sub().clone())185 },196 },186 None => return Ok(None)197 None => return Ok(None)202 use pallet_common::CommonCollectionOperations;213 use pallet_common::CommonCollectionOperations;203214204 let cross_account_id = CrossAccountId::from_sub(account_id);215 let cross_account_id = CrossAccountId::from_sub(account_id);205 let collection_id = RmrkCore::unique_collection_id(collection_id)?;216 let collection_id = match RmrkCore::unique_collection_id(collection_id) {217 Ok(id) => id,218 Err(_) => return Ok(Vec::new())219 };206 let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {220 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }207 Ok(c) => c,208 Err(_) => return Ok(Vec::new()),209 };210221211 Ok(222 Ok(212 collection.account_tokens(cross_account_id)223 collection.account_tokens(cross_account_id)217 }228 }218229219 fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {230 fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {220 let collection_id = RmrkCore::unique_collection_id(collection_id)?;231 let collection_id = match RmrkCore::unique_collection_id(collection_id) {232 Ok(id) => id,233 Err(_) => return Ok(Vec::new())234 };221 let nft_id = TokenId(nft_id);235 let nft_id = TokenId(nft_id);222 if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(Vec::new()); }236 if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(Vec::new()); }223237224 Ok(238 Ok(225 pallet_nonfungible::TokenChildren::<Runtime>::iter_prefix((collection_id, nft_id))239 pallet_nonfungible::TokenChildren::<Runtime>::iter_prefix((collection_id, nft_id))226 .filter_map(|(child_id, is_child)|240 .filter_map(|((child_collection, child_token), _)| {227 match is_child {241 let rmrk_child_collection = RmrkCore::rmrk_collection_id(242 child_collection243 ).ok()?;244228 true => Some(RmrkNftChild {245 Some(RmrkNftChild {229 collection_id: child_id.0.0,246 collection_id: rmrk_child_collection,230 nft_id: child_id.1.0,247 nft_id: child_token.0,231 }),248 })232 false => None,233 }249 }).collect()234 ).collect()235 )250 )236 }251 }237252238 fn collection_properties(collection_id: RmrkCollectionId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {253 fn collection_properties(collection_id: RmrkCollectionId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {239 use pallet_proxy_rmrk_core::misc::CollectionType;254 use pallet_proxy_rmrk_core::misc::CollectionType;240255241 let collection_id = RmrkCore::unique_collection_id(collection_id)?;256 let collection_id = match RmrkCore::unique_collection_id(collection_id) {257 Ok(id) => id,258 Err(_) => return Ok(Vec::new())259 };242 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() {260 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() {243 return Ok(Vec::new());261 return Ok(Vec::new());244 }262 }259 fn nft_properties(collection_id: RmrkCollectionId, nft_id: RmrkNftId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {277 fn nft_properties(collection_id: RmrkCollectionId, nft_id: RmrkNftId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {260 use pallet_proxy_rmrk_core::misc::NftType;278 use pallet_proxy_rmrk_core::misc::NftType;261279262 let collection_id = RmrkCore::unique_collection_id(collection_id)?;280 let collection_id = match RmrkCore::unique_collection_id(collection_id) {281 Ok(id) => id,282 Err(_) => return Ok(Vec::new())283 };263 let token_id = TokenId(nft_id);284 let token_id = TokenId(nft_id);264285265 if RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Regular).is_err() {286 if RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Regular).is_err() {283 use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, ResourceType}};304 use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, ResourceType}};284 use pallet_common::CommonCollectionOperations;305 use pallet_common::CommonCollectionOperations;285306286 let collection_id = RmrkCore::unique_collection_id(collection_id)?;307 let collection_id = match RmrkCore::unique_collection_id(collection_id) {308 Ok(id) => id,309 Err(_) => return Ok(Vec::new())310 };287 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }311 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }288312289 let nft_id = TokenId(nft_id);313 let nft_id = TokenId(nft_id);332 fn nft_resource_priorities(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceId>, DispatchError> {356 fn nft_resource_priorities(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceId>, DispatchError> {333 use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};357 use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};334358335 let collection_id = RmrkCore::unique_collection_id(collection_id)?;359 let collection_id = match RmrkCore::unique_collection_id(collection_id) {360 Ok(id) => id,361 Err(_) => return Ok(Vec::new())362 };336 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }363 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }337364338 let nft_id = TokenId(nft_id);365 let nft_id = TokenId(nft_id);360 RmrkProperty, misc::{CollectionType},387 RmrkProperty, misc::{CollectionType},361 };388 };362389363 let collection_id = RmrkCore::unique_collection_id(base_id)?;390 let collection_id = match RmrkCore::unique_collection_id(base_id) {391 Ok(id) => id,392 Err(_) => return Ok(None)393 };364 let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {394 let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {365 Ok(c) => c,395 Ok(c) => c,366 Err(_) => return Ok(None),396 Err(_) => return Ok(None),377 use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};407 use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};378 use pallet_common::CommonCollectionOperations;408 use pallet_common::CommonCollectionOperations;379409380 let collection_id = RmrkCore::unique_collection_id(base_id)?;410 let collection_id = match RmrkCore::unique_collection_id(base_id) {411 Ok(id) => id,412 Err(_) => return Ok(Vec::new())413 };381 let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {414 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() { return Ok(Vec::new()); }382 Ok(c) => c,383 Err(_) => return Ok(Vec::new()),384 };385386415387 let parts = collection.collection_tokens()416 let parts = collection.collection_tokens()413 use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};442 use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};414 use pallet_common::CommonCollectionOperations;443 use pallet_common::CommonCollectionOperations;415444416 let collection_id = RmrkCore::unique_collection_id(base_id)?;445 let collection_id = match RmrkCore::unique_collection_id(base_id) {446 Ok(id) => id,447 Err(_) => return Ok(Vec::new())448 };417 let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {449 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() {418 Ok(c) => c,419 Err(_) => return Ok(Vec::new()),450 return Ok(Vec::new());420 };451 }421452422453423 let theme_names = collection.collection_tokens()454 let theme_names = collection.collection_tokens()444 };475 };445 use pallet_common::CommonCollectionOperations;476 use pallet_common::CommonCollectionOperations;446477447 let collection_id = RmrkCore::unique_collection_id(base_id)?;478 let collection_id = match RmrkCore::unique_collection_id(base_id) {479 Ok(id) => id,480 Err(_) => return Ok(None)481 };448 let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {482 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() {449 Ok(c) => c,450 Err(_) => return Ok(None),483 return Ok(None);451 };484 }452485453 let theme_info = collection.collection_tokens()486 let theme_info = collection.collection_tokens()454 .into_iter()487 .into_iter()