--- a/pallets/proxy-rmrk-core/src/lib.rs +++ b/pallets/proxy-rmrk-core/src/lib.rs @@ -134,6 +134,7 @@ CannotSendToDescendentOrSelf, CannotAcceptNonOwnedNft, CannotRejectNonOwnedNft, + ResourceNotPending, } #[pallet::call] @@ -540,6 +541,52 @@ #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))] #[transactional] + pub fn accept_resource( + origin: OriginFor, + rmrk_collection_id: RmrkCollectionId, + rmrk_nft_id: RmrkNftId, + rmrk_resource_id: RmrkResourceId, + ) -> DispatchResult { + let sender = ensure_signed(origin)?; + let cross_sender = T::CrossAccountId::from_sub(sender); + + let collection_id = Self::unique_collection_id(rmrk_collection_id) + .map_err(|_| >::ResourceDoesntExist)?; + + let nft_id = rmrk_nft_id.into(); + let resource_id = rmrk_resource_id.into(); + + let budget = budget::Value::new(NESTING_BUDGET); + + let nft_owner = >::find_topmost_owner( + collection_id, + nft_id, + &budget, + ).map_err(|_| >::ResourceDoesntExist)?; + + let resource_collection_id: CollectionId = + Self::get_nft_property_decoded(collection_id, nft_id, ResourceCollection) + .map_err(|_| >::ResourceDoesntExist)?; + + let is_pending: bool = Self::get_nft_property_decoded(resource_collection_id, resource_id, PendingResourceAccept) + .map_err(|_| >::ResourceDoesntExist)?; + + ensure!(is_pending, >::ResourceNotPending); + + ensure!(cross_sender == nft_owner, >::NoPermission); + + >::set_scoped_token_property( + resource_collection_id, + resource_id, + PropertyScope::Rmrk, + Self::rmrk_property(PendingResourceAccept, &false)?, + )?; + + Ok(()) + } + + #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))] + #[transactional] pub fn set_property( origin: OriginFor, #[pallet::compact] rmrk_collection_id: RmrkCollectionId, @@ -835,14 +882,18 @@ let collection = Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?; ensure!(collection.owner == sender, Error::::NoPermission); - - // Check NFT lock status // todo depends on market, maybe later - //ensure!(!Pallet::::is_locked(collection_id, nft_id), pallet_uniques::Error::::Locked); let sender = T::CrossAccountId::from_sub(sender); let budget = budget::Value::new(NESTING_BUDGET); - let pending = Self::ensure_nft_owner(collection_id, token_id, &sender, &budget).is_err(); + let nft_owner = >::find_topmost_owner( + collection_id, + token_id, + &budget, + ).map_err(Self::map_unique_err_to_proxy)?; + + let pending = sender != nft_owner; + let resource_collection_id: CollectionId = Self::get_nft_property_decoded(collection_id, token_id, ResourceCollection)?; let resource_collection = @@ -851,8 +902,8 @@ // todo probably add extra connections to bases, slots, etc., when RMRK starts to use them let resource_id = Self::create_nft( - &sender, // todo owner of the nft? &sender, + &nft_owner, &resource_collection, resource_properties.chain( [