difftreelog
fix(rmrk) sending nft
in: master
5 files changed
pallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth25 Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations,25 Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations,26};26};27use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle, TokenData};27use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle, TokenData};28use pallet_structure::Pallet as PalletStructure;28use pallet_structure::{Pallet as PalletStructure, Error as StructureError};29use pallet_evm::account::CrossAccountId;29use pallet_evm::account::CrossAccountId;30use core::convert::AsRef;30use core::convert::AsRef;3131128 NoAvailableNftId,128 NoAvailableNftId,129 CollectionUnknown,129 CollectionUnknown,130 NoPermission,130 NoPermission,131 NonTransferable,131 CollectionFullOrLocked,132 CollectionFullOrLocked,132 ResourceDoesntExist,133 ResourceDoesntExist,134 CannotSendToDescendentOrSelf,133 }135 }134136135 #[pallet::call]137 #[pallet::call]207 );209 );208210209 <PalletNft<T>>::destroy_collection(collection, &cross_sender)211 <PalletNft<T>>::destroy_collection(collection, &cross_sender)210 .map_err(Self::map_common_err_to_proxy)?;212 .map_err(Self::map_unique_err_to_proxy)?;211213212 Self::deposit_event(Event::CollectionDestroyed {214 Self::deposit_event(Event::CollectionDestroyed {213 issuer: sender,215 issuer: sender,283 recipient: Option<T::AccountId>,285 recipient: Option<T::AccountId>,284 royalty_amount: Option<Permill>,286 royalty_amount: Option<Permill>,285 metadata: RmrkString,287 metadata: RmrkString,288 transferable: bool,286 ) -> DispatchResult {289 ) -> DispatchResult {287 let sender = ensure_signed(origin)?;290 let sender = ensure_signed(origin)?;288 let sender = T::CrossAccountId::from_sub(sender);291 let sender = T::CrossAccountId::from_sub(sender);304 &collection,307 &collection,305 [308 [306 Self::rmrk_property(TokenType, &NftType::Regular)?,309 Self::rmrk_property(TokenType, &NftType::Regular)?,310 Self::rmrk_property(Transferable, &transferable)?,311 Self::rmrk_property(PendingNftAccept, &false)?,307 Self::rmrk_property(RoyaltyInfo, &royalty_info)?,312 Self::rmrk_property(RoyaltyInfo, &royalty_info)?,308 Self::rmrk_property(Metadata, &metadata)?,313 Self::rmrk_property(Metadata, &metadata)?,309 Self::rmrk_property(Equipped, &false)?,314 Self::rmrk_property(Equipped, &false)?,327 )332 )328 .map_err(|err| match err {333 .map_err(|err| match err {329 DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),334 DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),330 err => Self::map_common_err_to_proxy(err),335 err => Self::map_unique_err_to_proxy(err),331 })?;336 })?;332337333 Self::deposit_event(Event::NftMinted {338 Self::deposit_event(Event::NftMinted {373 new_owner: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,378 new_owner: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,374 ) -> DispatchResult {379 ) -> DispatchResult {375 let sender = ensure_signed(origin.clone())?;380 let sender = ensure_signed(origin.clone())?;376 let cross_sender = T::CrossAccountId::from_sub(sender.clone());381 let cross_sender = T::CrossAccountId::from_sub(sender);377382378 let collection_id = Self::unique_collection_id(rmrk_collection_id)?;383 let collection_id = Self::unique_collection_id(rmrk_collection_id)?;379 let nft_id = rmrk_nft_id.into();384 let nft_id = rmrk_nft_id.into();388 misc::CollectionType::Regular,393 misc::CollectionType::Regular,389 )?;394 )?;395396 if !Self::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Transferable)? {397 return Err(<Error<T>>::NonTransferable.into());398 }390399391 let budget = budget::Value::new(NESTING_BUDGET);400 if Self::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::PendingNftAccept)? {401 return Err(<Error<T>>::NoPermission.into());402 }392403393 let target_owner;404 let target_owner;394405399 RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(target_collection_id, target_nft_id) => {410 RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(target_collection_id, target_nft_id) => {400 let target_collection_id = Self::unique_collection_id(target_collection_id)?;411 let target_collection_id = Self::unique_collection_id(target_collection_id)?;401412402 target_owner = T::CrossTokenAddressMapping::token_to_address(413 let target_nft_budget = budget::Value::new(NESTING_BUDGET);403 target_collection_id,404 target_nft_id.into(),405 );406414407 let spender = <PalletStructure<T>>::get_indirect_owner(415 let target_nft_owner = <PalletStructure<T>>::get_checked_indirect_owner(408 target_collection_id,416 target_collection_id,409 target_nft_id.into(),417 target_nft_id.into(),410 Some((collection_id, nft_id)),418 Some((collection_id, nft_id)),411 &budget,419 &target_nft_budget,412 )?;420 ).map_err(Self::map_unique_err_to_proxy)?;413421414 let is_approval_required = cross_sender != spender;422 let is_approval_required = cross_sender != target_nft_owner;415423416 if is_approval_required {424 if is_approval_required {417 // FIXME425 target_owner = target_nft_owner;418 // <PalletNft<T>>::set_allowance(426419 // &collection,427 <PalletNft<T>>::set_scoped_token_property(420 // &cross_sender,428 collection.id,421 // nft_id,429 nft_id,422 // Some(&spender),430 PropertyScope::Rmrk,423 // &budget431 Self::rmrk_property(PendingNftAccept, &is_approval_required)?,424 // ).map_err(Self::map_common_err_to_proxy)?;432 )?;425433 } else {426 return Ok(());434 target_owner = T::CrossTokenAddressMapping::token_to_address(435 target_collection_id,436 target_nft_id.into(),437 );427 }438 }428 }439 }429 }440 }441442 let src_nft_budget = budget::Value::new(NESTING_BUDGET);430443431 <PalletNft<T>>::transfer_from(444 <PalletNft<T>>::transfer_from(432 &collection,445 &collection,433 &cross_sender,446 &cross_sender,434 &from,447 &from,435 &target_owner,448 &target_owner,436 nft_id,449 nft_id,437 &budget450 &src_nft_budget438 ).map_err(Self::map_common_err_to_proxy)?;451 ).map_err(Self::map_unique_err_to_proxy)?;439452440 Ok(())453 Ok(())441 }454 }719 let collection = Self::get_typed_nft_collection(collection_id, collection_type)?;732 let collection = Self::get_typed_nft_collection(collection_id, collection_type)?;720733721 <PalletNft<T>>::burn(&collection, &sender, token_id)734 <PalletNft<T>>::burn(&collection, &sender, token_id)722 .map_err(Self::map_common_err_to_proxy)?;735 .map_err(Self::map_unique_err_to_proxy)?;723736724 Ok(())737 Ok(())725 }738 }762 )775 )763 .map_err(|err| match err {776 .map_err(|err| match err {764 DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),777 DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),765 err => Self::map_common_err_to_proxy(err),778 err => Self::map_unique_err_to_proxy(err),766 })?;779 })?;767780768 Ok(resource_id.0)781 Ok(resource_id.0)794 let sender = T::CrossAccountId::from_sub(sender);807 let sender = T::CrossAccountId::from_sub(sender);795 if topmost_owner == sender {808 if topmost_owner == sender {796 <PalletNft<T>>::burn(&resource_collection, &sender, resource_id)809 <PalletNft<T>>::burn(&resource_collection, &sender, resource_id)797 .map_err(Self::map_common_err_to_proxy)?;810 .map_err(Self::map_unique_err_to_proxy)?;798 } else {811 } else {799 <PalletNft<T>>::set_scoped_token_property(812 <PalletNft<T>>::set_scoped_token_property(800 resource_collection_id,813 resource_collection_id,828 ) -> DispatchResult {841 ) -> DispatchResult {829 collection842 collection830 .check_is_owner(account)843 .check_is_owner(account)831 .map_err(Self::map_common_err_to_proxy)844 .map_err(Self::map_unique_err_to_proxy)832 }845 }833846834 pub fn last_collection_idx() -> RmrkCollectionId {847 pub fn last_collection_idx() -> RmrkCollectionId {1064 Ok(properties)1077 Ok(properties)1065 }1078 }106610791067 fn map_common_err_to_proxy(err: DispatchError) -> DispatchError {1080 fn map_unique_err_to_proxy(err: DispatchError) -> DispatchError {1068 map_common_err_to_proxy! {1081 map_unique_err_to_proxy! {1069 match err {1082 match err {1070 NoPermission => NoPermission,1083 CommonError::NoPermission => NoPermission,1071 CollectionTokenLimitExceeded => CollectionFullOrLocked,1084 CommonError::CollectionTokenLimitExceeded => CollectionFullOrLocked,1072 PublicMintingNotAllowed => NoPermission,1085 CommonError::PublicMintingNotAllowed => NoPermission,1073 TokenNotFound => NoAvailableNftId,1086 CommonError::TokenNotFound => NoAvailableNftId,1074 ApprovedValueTooLow => NoPermission1087 CommonError::ApprovedValueTooLow => NoPermission,1088 StructureError::TokenNotFound => NoAvailableNftId,1089 StructureError::OuroborosDetected => CannotSendToDescendentOrSelf1075 }1090 }1076 }1091 }1077 }1092 }pallets/proxy-rmrk-core/src/misc.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-core/src/misc.rs
+++ b/pallets/proxy-rmrk-core/src/misc.rs
@@ -2,10 +2,10 @@
use codec::{Encode, Decode, Error};
#[macro_export]
-macro_rules! map_common_err_to_proxy {
- (match $err:ident { $($common_err:ident => $proxy_err:ident),+ }) => {
+macro_rules! map_unique_err_to_proxy {
+ (match $err:ident { $($unique_err_ty:ident :: $unique_err:ident => $proxy_err:ident),+ }) => {
$(
- if $err == <CommonError<T>>::$common_err.into() {
+ if $err == <$unique_err_ty<T>>::$unique_err.into() {
return <Error<T>>::$proxy_err.into()
} else
)+ {
pallets/proxy-rmrk-core/src/property.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-core/src/property.rs
+++ b/pallets/proxy-rmrk-core/src/property.rs
@@ -5,11 +5,13 @@
Metadata,
CollectionType,
TokenType,
+ Transferable,
RoyaltyInfo,
Equipped,
ResourceCollection,
ResourcePriorities,
ResourceType,
+ PendingNftAccept,
PendingResourceAccept,
PendingResourceRemoval,
Parts,
@@ -49,13 +51,15 @@
Self::Metadata => key!("metadata"),
Self::CollectionType => key!("collection-type"),
Self::TokenType => key!("token-type"),
+ Self::Transferable => key!("transferable"),
Self::RoyaltyInfo => key!("royalty-info"),
Self::Equipped => key!("equipped"),
Self::ResourceCollection => key!("resource-collection"),
Self::ResourcePriorities => key!("resource-priorities"),
Self::ResourceType => key!("resource-type"),
- Self::PendingResourceAccept => key!("pending-accept"),
- Self::PendingResourceRemoval => key!("pending-removal"),
+ Self::PendingNftAccept => key!("pending-nft-accept"),
+ Self::PendingResourceAccept => key!("pending-resource-accept"),
+ Self::PendingResourceRemoval => key!("pending-resource-removal"),
Self::Parts => key!("parts"),
Self::Base => key!("base"),
Self::Src => key!("src"),
pallets/structure/src/lib.rsdiffbeforeafterboth--- a/pallets/structure/src/lib.rs
+++ b/pallets/structure/src/lib.rs
@@ -149,7 +149,7 @@
})
}
- pub fn get_indirect_owner(
+ pub fn get_checked_indirect_owner(
collection: CollectionId,
token: TokenId,
for_nest: Option<(CollectionId, TokenId)>,
@@ -203,7 +203,7 @@
None => user,
};
- Self::get_indirect_owner(
+ Self::get_checked_indirect_owner(
collection,
token,
for_nest,
runtime/common/src/runtime_apis.rsdiffbeforeafterboth--- a/runtime/common/src/runtime_apis.rs
+++ b/runtime/common/src/runtime_apis.rs
@@ -188,19 +188,17 @@
None => return Ok(None)
};
- let allowance = pallet_nonfungible::Allowance::<Runtime>::get((collection_id, nft_id));
-
Ok(Some(RmrkInstanceInfo {
owner: owner,
royalty: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::RoyaltyInfo)?,
metadata: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Metadata)?,
equipped: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Equipped)?,
- pending: allowance.is_some(),
+ pending: RmrkCore::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::PendingNftAccept)?,
}))
}
fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {
- use pallet_proxy_rmrk_core::misc::CollectionType;
+ use pallet_proxy_rmrk_core::{RmrkProperty, misc::CollectionType};
use pallet_common::CommonCollectionOperations;
let cross_account_id = CrossAccountId::from_sub(account_id);
@@ -210,15 +208,26 @@
Err(_) => return Ok(Vec::new()),
};
- Ok(
- collection.account_tokens(cross_account_id)
- .into_iter()
- .map(|token| token.0)
- .collect()
- )
+ let tokens = collection.account_tokens(cross_account_id)
+ .into_iter()
+ .filter(|token| {
+ let is_pending = RmrkCore::get_nft_property_decoded(
+ collection_id,
+ *token,
+ RmrkProperty::PendingNftAccept
+ ).unwrap_or(true);
+
+ !is_pending
+ })
+ .map(|token| token.0)
+ .collect();
+
+ Ok(tokens)
}
fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {
+ use pallet_proxy_rmrk_core::RmrkProperty;
+
let collection_id = match RmrkCore::unique_collection_id(collection_id) {
Ok(id) => id,
Err(_) => return Ok(Vec::new())
@@ -229,6 +238,16 @@
Ok(
pallet_nonfungible::TokenChildren::<Runtime>::iter_prefix((collection_id, nft_id))
.filter_map(|((child_collection, child_token), _)| {
+ let is_pending = RmrkCore::get_nft_property_decoded(
+ child_collection,
+ child_token,
+ RmrkProperty::PendingNftAccept
+ ).ok()?;
+
+ if is_pending {
+ return None;
+ }
+
let rmrk_child_collection = RmrkCore::rmrk_collection_id(
child_collection
).ok()?;
@@ -398,7 +417,7 @@
Ok(c) => c,
Err(_) => return Ok(Vec::new()),
};
-
+
let parts = collection.collection_tokens()
.into_iter()
.filter_map(|token_id| {