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.rsdiffbeforeafterboth1#![cfg_attr(not(feature = "std"), no_std)]23use pallet_common::CommonCollectionOperations;4use sp_std::collections::btree_set::BTreeSet;56use frame_support::dispatch::{DispatchError, DispatchResult, DispatchResultWithPostInfo};7use frame_support::fail;8pub use pallet::*;9use pallet_common::{dispatch::CollectionDispatch, CollectionHandle};10use up_data_structs::{CollectionId, TokenId, mapping::TokenAddressMapping, budget::Budget};1112#[cfg(feature = "runtime-benchmarks")]13pub mod benchmarking;14pub mod weights;1516pub type SelfWeightOf<T> = <T as crate::Config>::WeightInfo;1718#[frame_support::pallet]19pub mod pallet {20 use frame_support::Parameter;21 use frame_support::dispatch::{GetDispatchInfo, UnfilteredDispatchable};22 use frame_support::pallet_prelude::*;2324 use super::*;2526 #[pallet::error]27 pub enum Error<T> {28 /// While searched for owner, got already checked account29 OuroborosDetected,30 /// While searched for owner, encountered depth limit31 DepthLimit,32 /// While iterating over children, encountered breadth limit33 BreadthLimit,34 /// While searched for owner, found token owner by not-yet-existing token35 TokenNotFound,36 }3738 #[pallet::event]39 pub enum Event<T> {40 /// Executed call on behalf of token41 Executed(DispatchResult),42 }4344 #[pallet::config]45 pub trait Config: frame_system::Config + pallet_common::Config {46 type WeightInfo: weights::WeightInfo;47 type Event: IsType<<Self as frame_system::Config>::Event> + From<Event<Self>>;48 type Call: Parameter + UnfilteredDispatchable<Origin = Self::Origin> + GetDispatchInfo;49 }5051 #[pallet::pallet]52 pub struct Pallet<T>(_);5354 #[pallet::call]55 impl<T: Config> Pallet<T> {56 // #[pallet::weight({57 // let dispatch_info = call.get_dispatch_info();5859 // (60 // dispatch_info.weight61 // // Cost of dereferencing parent62 // .saturating_add(T::DbWeight::get().reads(2 * *max_depth as Weight))63 // .saturating_add(4000 * *max_depth as Weight),64 // dispatch_info.class)65 // })]66 // pub fn execute(67 // origin: OriginFor<T>,68 // call: Box<<T as Config>::Call>,69 // max_depth: u32,70 // ) -> DispatchResult {71 }72}7374#[derive(PartialEq)]75pub enum Parent<CrossAccountId> {76 /// Token owned by normal account77 User(CrossAccountId),78 /// Passed token not found79 TokenNotFound,80 /// Token owner is another token (target token still may not exist)81 Token(CollectionId, TokenId),82}8384impl<T: Config> Pallet<T> {85 pub fn find_parent(86 collection: CollectionId,87 token: TokenId,88 ) -> Result<Parent<T::CrossAccountId>, DispatchError> {89 // TODO: Reduce cost by not reading collection config90 let handle = match CollectionHandle::try_get(collection) {91 Ok(v) => v,92 Err(_) => return Ok(Parent::TokenNotFound),93 };94 let handle = T::CollectionDispatch::dispatch(handle);95 let handle = handle.as_dyn();9697 Ok(match handle.token_owner(token) {98 Some(owner) => match T::CrossTokenAddressMapping::address_to_token(&owner) {99 Some((collection, token)) => Parent::Token(collection, token),100 None => Parent::User(owner),101 },102 None => Parent::TokenNotFound,103 })104 }105106 pub fn parent_chain(107 mut collection: CollectionId,108 mut token: TokenId,109 ) -> impl Iterator<Item = Result<Parent<T::CrossAccountId>, DispatchError>> {110 let mut finished = false;111 let mut visited = BTreeSet::new();112 visited.insert((collection, token));113 core::iter::from_fn(move || {114 if finished {115 return None;116 }117 let parent = Self::find_parent(collection, token);118 match parent {119 Ok(Parent::Token(new_collection, new_token)) => {120 collection = new_collection;121 token = new_token;122 if !visited.insert((new_collection, new_token)) {123 finished = true;124 return Some(Err(<Error<T>>::OuroborosDetected.into()));125 }126 }127 _ => finished = true,128 }129 Some(parent as Result<_, DispatchError>)130 })131 }132133 /// Try to dereference address, until finding top level owner134 ///135 /// May return token address if parent token not yet exists136 pub fn find_topmost_owner(137 collection: CollectionId,138 token: TokenId,139 budget: &dyn Budget,140 ) -> Result<T::CrossAccountId, DispatchError> {141 let owner = Self::parent_chain(collection, token)142 .take_while(|_| budget.consume())143 .find(|p| matches!(p, Ok(Parent::User(_) | Parent::TokenNotFound)))144 .ok_or(<Error<T>>::DepthLimit)??;145146 Ok(match owner {147 Parent::User(v) => v,148 _ => fail!(<Error<T>>::TokenNotFound),149 })150 }151152 /// Check if token indirectly owned by specified user153 pub fn check_indirectly_owned(154 user: T::CrossAccountId,155 collection: CollectionId,156 token: TokenId,157 for_nest: Option<(CollectionId, TokenId)>,158 budget: &dyn Budget,159 ) -> Result<bool, DispatchError> {160 let target_parent = match T::CrossTokenAddressMapping::address_to_token(&user) {161 Some((collection, token)) => Self::find_topmost_owner(collection, token, budget)?,162 None => user,163 };164165 // Tried to nest token in itself166 if Some((collection, token)) == for_nest {167 return Err(<Error<T>>::OuroborosDetected.into());168 }169170 for parent in Self::parent_chain(collection, token).take_while(|_| budget.consume()) {171 match parent? {172 // Tried to nest token in chain, which has this token as one of parents173 Parent::Token(collection, token) if Some((collection, token)) == for_nest => {174 return Err(<Error<T>>::OuroborosDetected.into())175 }176 // Found needed parent, token is indirecty owned177 Parent::User(user) if user == target_parent => return Ok(true),178 // Token is owned by other user179 Parent::User(_) => return Ok(false),180 Parent::TokenNotFound => return Err(<Error<T>>::TokenNotFound.into()),181 // Continue parent chain182 Parent::Token(_, _) => {}183 }184 }185186 Err(<Error<T>>::DepthLimit.into())187 }188189 pub fn burn_item_recursively(190 from: T::CrossAccountId,191 collection: CollectionId,192 token: TokenId,193 self_budget: &dyn Budget,194 breadth_budget: &dyn Budget,195 ) -> DispatchResultWithPostInfo {196 let handle = <CollectionHandle<T>>::try_get(collection)?;197 let dispatch = T::CollectionDispatch::dispatch(handle);198 let dispatch = dispatch.as_dyn();199 dispatch.burn_item_recursively(from.clone(), token, self_budget, breadth_budget)200 }201202 pub fn check_nesting(203 from: T::CrossAccountId,204 under: &T::CrossAccountId,205 collection_id: CollectionId,206 token_id: TokenId,207 nesting_budget: &dyn Budget,208 ) -> DispatchResult {209 Self::try_exec_if_owner_is_valid_nft(under, |collection, parent_id| {210 collection.check_nesting(from, (collection_id, token_id), parent_id, nesting_budget)211 })212 }213214 pub fn nest_if_sent_to_token(215 from: T::CrossAccountId,216 under: &T::CrossAccountId,217 collection_id: CollectionId,218 token_id: TokenId,219 nesting_budget: &dyn Budget,220 ) -> DispatchResult {221 Self::try_exec_if_owner_is_valid_nft(under, |collection, parent_id| {222 collection.check_nesting(from, (collection_id, token_id), parent_id, nesting_budget)?;223224 collection.nest(parent_id, (collection_id, token_id));225226 Ok(())227 })228 }229230 pub fn nest_if_sent_to_token_unchecked(231 owner: &T::CrossAccountId,232 collection_id: CollectionId,233 token_id: TokenId,234 ) {235 Self::exec_if_owner_is_valid_nft(owner, |collection, parent_id| {236 collection.nest(parent_id, (collection_id, token_id))237 });238 }239240 pub fn unnest_if_nested(241 owner: &T::CrossAccountId,242 collection_id: CollectionId,243 token_id: TokenId,244 ) {245 Self::exec_if_owner_is_valid_nft(owner, |collection, parent_id| {246 collection.unnest(parent_id, (collection_id, token_id))247 });248 }249250 fn exec_if_owner_is_valid_nft(251 account: &T::CrossAccountId,252 action: impl FnOnce(&dyn CommonCollectionOperations<T>, TokenId),253 ) {254 Self::try_exec_if_owner_is_valid_nft(account, |collection, id| {255 action(collection, id);256 Ok(())257 })258 .unwrap();259 }260261 fn try_exec_if_owner_is_valid_nft(262 account: &T::CrossAccountId,263 action: impl FnOnce(&dyn CommonCollectionOperations<T>, TokenId) -> DispatchResult,264 ) -> DispatchResult {265 let account = T::CrossTokenAddressMapping::address_to_token(account);266267 if account.is_none() {268 return Ok(());269 }270271 let account = account.unwrap();272273 let handle = <CollectionHandle<T>>::try_get(account.0);274275 if handle.is_err() {276 return Ok(());277 }278279 let handle = handle.unwrap();280281 let dispatch = T::CollectionDispatch::dispatch(handle);282 let dispatch = dispatch.as_dyn();283284 action(dispatch, account.1)285 }286}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.rsdiffbeforeafterboth--- a/runtime/common/src/runtime_apis.rs
+++ b/runtime/common/src/runtime_apis.rs
@@ -147,7 +147,11 @@
use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};
use pallet_common::CommonCollectionOperations;
- let collection_id = RmrkCore::unique_collection_id(collection_id)?;
+ let collection_id = match RmrkCore::unique_collection_id(collection_id) {
+ Ok(id) => id,
+ Err(_) => return Ok(None)
+ };
+
let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {
Ok(c) => c,
Err(_) => return Ok(None),
@@ -169,7 +173,10 @@
use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};
use pallet_common::CommonCollectionOperations;
- let collection_id = RmrkCore::unique_collection_id(collection_id)?;
+ let collection_id = match RmrkCore::unique_collection_id(collection_id) {
+ Ok(id) => id,
+ Err(_) => return Ok(None)
+ };
let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {
Ok(c) => c,
Err(_) => return Ok(None),
@@ -180,7 +187,11 @@
let owner = match collection.token_owner(nft_id) {
Some(owner) => match <Runtime as pallet_common::Config>::CrossTokenAddressMapping::address_to_token(&owner) {
- Some((col, tok)) => RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(col.0, tok.0),
+ Some((col, tok)) => {
+ let rmrk_collection = RmrkCore::rmrk_collection_id(col)?;
+
+ RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(rmrk_collection, tok.0)
+ }
None => RmrkAccountIdOrCollectionNftTuple::AccountId(owner.as_sub().clone())
},
None => return Ok(None)
@@ -202,11 +213,11 @@
use pallet_common::CommonCollectionOperations;
let cross_account_id = CrossAccountId::from_sub(account_id);
- let collection_id = RmrkCore::unique_collection_id(collection_id)?;
- let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {
- Ok(c) => c,
- Err(_) => return Ok(Vec::new()),
+ let collection_id = match RmrkCore::unique_collection_id(collection_id) {
+ Ok(id) => id,
+ Err(_) => return Ok(Vec::new())
};
+ if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }
Ok(
collection.account_tokens(cross_account_id)
@@ -217,28 +228,35 @@
}
fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {
- let collection_id = RmrkCore::unique_collection_id(collection_id)?;
+ let collection_id = match RmrkCore::unique_collection_id(collection_id) {
+ Ok(id) => id,
+ Err(_) => return Ok(Vec::new())
+ };
let nft_id = TokenId(nft_id);
if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(Vec::new()); }
Ok(
pallet_nonfungible::TokenChildren::<Runtime>::iter_prefix((collection_id, nft_id))
- .filter_map(|(child_id, is_child)|
- match is_child {
- true => Some(RmrkNftChild {
- collection_id: child_id.0.0,
- nft_id: child_id.1.0,
- }),
- false => None,
- }
- ).collect()
+ .filter_map(|((child_collection, child_token), _)| {
+ let rmrk_child_collection = RmrkCore::rmrk_collection_id(
+ child_collection
+ ).ok()?;
+
+ Some(RmrkNftChild {
+ collection_id: rmrk_child_collection,
+ nft_id: child_token.0,
+ })
+ }).collect()
)
}
fn collection_properties(collection_id: RmrkCollectionId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
use pallet_proxy_rmrk_core::misc::CollectionType;
- let collection_id = RmrkCore::unique_collection_id(collection_id)?;
+ let collection_id = match RmrkCore::unique_collection_id(collection_id) {
+ Ok(id) => id,
+ Err(_) => return Ok(Vec::new())
+ };
if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() {
return Ok(Vec::new());
}
@@ -259,7 +277,10 @@
fn nft_properties(collection_id: RmrkCollectionId, nft_id: RmrkNftId, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
use pallet_proxy_rmrk_core::misc::NftType;
- let collection_id = RmrkCore::unique_collection_id(collection_id)?;
+ let collection_id = match RmrkCore::unique_collection_id(collection_id) {
+ Ok(id) => id,
+ Err(_) => return Ok(Vec::new())
+ };
let token_id = TokenId(nft_id);
if RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Regular).is_err() {
@@ -283,7 +304,10 @@
use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, ResourceType}};
use pallet_common::CommonCollectionOperations;
- let collection_id = RmrkCore::unique_collection_id(collection_id)?;
+ let collection_id = match RmrkCore::unique_collection_id(collection_id) {
+ Ok(id) => id,
+ Err(_) => return Ok(Vec::new())
+ };
if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }
let nft_id = TokenId(nft_id);
@@ -332,7 +356,10 @@
fn nft_resource_priorities(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceId>, DispatchError> {
use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};
- let collection_id = RmrkCore::unique_collection_id(collection_id)?;
+ let collection_id = match RmrkCore::unique_collection_id(collection_id) {
+ Ok(id) => id,
+ Err(_) => return Ok(Vec::new())
+ };
if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }
let nft_id = TokenId(nft_id);
@@ -360,7 +387,10 @@
RmrkProperty, misc::{CollectionType},
};
- let collection_id = RmrkCore::unique_collection_id(base_id)?;
+ let collection_id = match RmrkCore::unique_collection_id(base_id) {
+ Ok(id) => id,
+ Err(_) => return Ok(None)
+ };
let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {
Ok(c) => c,
Err(_) => return Ok(None),
@@ -377,12 +407,11 @@
use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};
use pallet_common::CommonCollectionOperations;
- let collection_id = RmrkCore::unique_collection_id(base_id)?;
- let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {
- Ok(c) => c,
- Err(_) => return Ok(Vec::new()),
+ let collection_id = match RmrkCore::unique_collection_id(base_id) {
+ Ok(id) => id,
+ Err(_) => return Ok(Vec::new())
};
-
+ if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() { return Ok(Vec::new()); }
let parts = collection.collection_tokens()
.into_iter()
@@ -413,11 +442,13 @@
use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};
use pallet_common::CommonCollectionOperations;
- let collection_id = RmrkCore::unique_collection_id(base_id)?;
- let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {
- Ok(c) => c,
- Err(_) => return Ok(Vec::new()),
+ let collection_id = match RmrkCore::unique_collection_id(base_id) {
+ Ok(id) => id,
+ Err(_) => return Ok(Vec::new())
};
+ if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() {
+ return Ok(Vec::new());
+ }
let theme_names = collection.collection_tokens()
@@ -444,11 +475,13 @@
};
use pallet_common::CommonCollectionOperations;
- let collection_id = RmrkCore::unique_collection_id(base_id)?;
- let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Base) {
- Ok(c) => c,
- Err(_) => return Ok(None),
+ let collection_id = match RmrkCore::unique_collection_id(base_id) {
+ Ok(id) => id,
+ Err(_) => return Ok(None)
};
+ if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() {
+ return Ok(None);
+ }
let theme_info = collection.collection_tokens()
.into_iter()