difftreelog
fix(rmrk) include pending children into nft_children RPC
in: master
3 files changed
pallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-core/src/lib.rs
+++ b/pallets/proxy-rmrk-core/src/lib.rs
@@ -16,10 +16,15 @@
#![cfg_attr(not(feature = "std"), no_std)]
-use frame_support::{pallet_prelude::*, transactional, BoundedVec, dispatch::DispatchResult};
+use frame_support::{
+ pallet_prelude::*,
+ transactional,
+ BoundedVec,
+ dispatch::DispatchResult,
+};
use frame_system::{pallet_prelude::*, ensure_signed};
use sp_runtime::{DispatchError, Permill, traits::StaticLookup};
-use sp_std::vec::Vec;
+use sp_std::{vec::Vec, collections::btree_set::BTreeSet};
use up_data_structs::{*, mapping::TokenAddressMapping};
use pallet_common::{
Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations,
@@ -48,6 +53,10 @@
pub const NESTING_BUDGET: u32 = 5;
+type PendingTarget = (CollectionId, TokenId);
+type PendingChild = (RmrkCollectionId, RmrkNftId);
+type PendingChildrenMap = BTreeSet<PendingChild>;
+
#[frame_support::pallet]
pub mod pallet {
use super::*;
@@ -383,12 +392,13 @@
[
Self::rmrk_property(TokenType, &NftType::Regular)?,
Self::rmrk_property(Transferable, &transferable)?,
- Self::rmrk_property(PendingNftAccept, &false)?,
+ Self::rmrk_property(PendingNftAccept, &None::<PendingTarget>)?,
Self::rmrk_property(RoyaltyInfo, &royalty_info)?,
Self::rmrk_property(Metadata, &metadata)?,
Self::rmrk_property(Equipped, &false)?,
Self::rmrk_property(ResourcePriorities, &<Vec<u8>>::new())?,
Self::rmrk_property(NextResourceId, &(0 as RmrkResourceId))?,
+ Self::rmrk_property(PendingChildren, &PendingChildrenMap::new())?,
]
.into_iter(),
)
@@ -483,11 +493,11 @@
);
ensure!(
- !Self::get_nft_property_decoded(
+ Self::get_nft_property_decoded::<Option<PendingTarget>>(
collection_id,
nft_id,
RmrkProperty::PendingNftAccept
- )?,
+ )?.is_none(),
<Error<T>>::NoPermission
);
@@ -524,7 +534,15 @@
collection.id,
nft_id,
PropertyScope::Rmrk,
- Self::rmrk_property(PendingNftAccept, &approval_required)?,
+ Self::rmrk_property::<Option<PendingTarget>>(
+ PendingNftAccept,
+ &Some((target_collection_id, target_nft_id.into()))
+ )?,
+ )?;
+
+ Self::insert_pending_child(
+ (target_collection_id, target_nft_id.into()),
+ (rmrk_collection_id, rmrk_nft_id),
)?;
} else {
target_owner = T::CrossTokenAddressMapping::token_to_address(
@@ -618,13 +636,23 @@
}
})?;
- <PalletNft<T>>::set_scoped_token_property(
- collection.id,
+ let pending_target = Self::get_nft_property_decoded::<Option<PendingTarget>>(
+ collection_id,
nft_id,
- PropertyScope::Rmrk,
- Self::rmrk_property(PendingNftAccept, &false)?,
+ RmrkProperty::PendingNftAccept
)?;
+ if let Some(pending_target) = pending_target {
+ Self::remove_pending_child(pending_target, (rmrk_collection_id, rmrk_nft_id))?;
+
+ <PalletNft<T>>::set_scoped_token_property(
+ collection.id,
+ nft_id,
+ PropertyScope::Rmrk,
+ Self::rmrk_property(PendingNftAccept, &None::<PendingTarget>)?,
+ )?;
+ }
+
Self::deposit_event(Event::NFTAccepted {
sender,
recipient: new_owner,
@@ -663,15 +691,18 @@
<Error<T>>::NoAvailableNftId
);
- ensure!(
- Self::get_nft_property_decoded(
- collection_id,
- nft_id,
- RmrkProperty::PendingNftAccept
- )?,
- <Error<T>>::CannotRejectNonPendingNft
- );
+ let pending_target = Self::get_nft_property_decoded::<Option<PendingTarget>>(
+ collection_id,
+ nft_id,
+ RmrkProperty::PendingNftAccept
+ )?;
+
+ match pending_target {
+ Some(pending_target) => Self::remove_pending_child(pending_target, (rmrk_collection_id, rmrk_nft_id))?,
+ None => return Err(<Error<T>>::CannotRejectNonPendingNft.into()),
+ }
+
Self::destroy_nft(
cross_sender,
collection_id,
@@ -1147,6 +1178,64 @@
)
}
+ fn insert_pending_child(
+ target: (CollectionId, TokenId),
+ child: (RmrkCollectionId, RmrkNftId),
+ ) -> DispatchResult {
+ Self::mutate_pending_child(target, |pending_children| {
+ pending_children.insert(child);
+ })
+ }
+
+ fn remove_pending_child(
+ target: (CollectionId, TokenId),
+ child: (RmrkCollectionId, RmrkNftId),
+ ) -> DispatchResult {
+ Self::mutate_pending_child(target, |pending_children| {
+ pending_children.remove(&child);
+ })
+ }
+
+ fn mutate_pending_child(
+ (target_collection_id, target_nft_id): (CollectionId, TokenId),
+ f: impl FnOnce(&mut PendingChildrenMap),
+ ) -> DispatchResult {
+ <PalletNft<T>>::try_mutate_token_aux_property(
+ target_collection_id,
+ target_nft_id,
+ PropertyScope::Rmrk,
+ Self::rmrk_property_key(PendingChildren)?,
+ |pending_children| -> DispatchResult {
+ let mut map = match pending_children {
+ Some(map) => Self::decode_property(map)?,
+ None => PendingChildrenMap::new(),
+ };
+
+ f(&mut map);
+
+ *pending_children = Some(Self::encode_property(&map)?);
+
+ Ok(())
+ },
+ )
+ }
+
+ fn iterate_pending_children(collection_id: CollectionId, nft_id: TokenId) -> Result<impl Iterator<Item=PendingChild>, DispatchError> {
+ let property = <PalletNft<T>>::token_aux_property((
+ collection_id,
+ nft_id,
+ PropertyScope::Rmrk,
+ Self::rmrk_property_key(PendingChildren)?
+ ));
+
+ let pending_children = match property {
+ Some(map) => Self::decode_property(&map)?,
+ None => PendingChildrenMap::new(),
+ };
+
+ Ok(pending_children.into_iter())
+ }
+
fn acquire_next_resource_id(
collection_id: CollectionId,
nft_id: TokenId,
@@ -1526,15 +1615,13 @@
Value: Decode + Default,
Mapper: Fn(Key, Value) -> R,
{
- let key_prefix = Self::rmrk_property_key(UserProperty(b""))?;
-
let properties = match token_id {
Some(token_id) => <PalletNft<T>>::token_properties((collection_id, token_id)),
None => <PalletCommon<T>>::collection_properties(collection_id),
};
let properties = properties.into_iter().filter_map(move |(key, value)| {
- let key = key.as_slice().strip_prefix(key_prefix.as_slice())?;
+ let key = strip_key_prefix(&key, USER_PROPERTY_PREFIX)?;
let key: Key = key.to_vec().try_into().ok()?;
let value: Value = value.decode().ok()?;
pallets/proxy-rmrk-core/src/property.rsdiffbeforeafterboth15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.161617use super::*;17use super::*;18use up_data_structs::PropertyScope;18use core::convert::AsRef;19use core::convert::AsRef;192020const RESOURCE_ID_PREFIX: &str = "rsid-";21pub const RESOURCE_ID_PREFIX: &str = "rsid-";22pub const USER_PROPERTY_PREFIX: &str = "userprop-";212322pub enum RmrkProperty<'r> {24pub enum RmrkProperty<'r> {23 Metadata,25 Metadata,31 NextResourceId,33 NextResourceId,32 ResourceId(RmrkResourceId),34 ResourceId(RmrkResourceId),33 PendingNftAccept,35 PendingNftAccept,36 PendingChildren,34 Parts,37 Parts,35 Base,38 Base,36 Src,39 Src,73 Self::NextResourceId => key!("next-resource-id"),76 Self::NextResourceId => key!("next-resource-id"),74 Self::ResourceId(id) => key!(RESOURCE_ID_PREFIX, id.to_le_bytes()),77 Self::ResourceId(id) => key!(RESOURCE_ID_PREFIX, id.to_le_bytes()),75 Self::PendingNftAccept => key!("pending-nft-accept"),78 Self::PendingNftAccept => key!("pending-nft-accept"),79 Self::PendingChildren => key!("pending-children"),76 Self::Parts => key!("parts"),80 Self::Parts => key!("parts"),77 Self::Base => key!("base"),81 Self::Base => key!("base"),78 Self::Src => key!("src"),82 Self::Src => key!("src"),83 Self::ZIndex => key!("z-index"),87 Self::ZIndex => key!("z-index"),84 Self::ThemeName => key!("theme-name"),88 Self::ThemeName => key!("theme-name"),85 Self::ThemeInherit => key!("theme-inherit"),89 Self::ThemeInherit => key!("theme-inherit"),86 Self::UserProperty(name) => key!("userprop-", name),90 Self::UserProperty(name) => key!(USER_PROPERTY_PREFIX, name),87 }91 }88 }92 }89}93}9495pub fn strip_key_prefix(key: &PropertyKey, prefix: &str) -> Option<PropertyKey> {96 let key_prefix = PropertyKey::try_from(prefix.as_bytes().to_vec()).ok()?;97 let key_prefix = PropertyScope::Rmrk.apply(key_prefix).ok()?;9899 key.as_slice().strip_prefix(key_prefix.as_slice())?100 .to_vec().try_into().ok()101}102103pub fn is_valid_key_prefix(key: &PropertyKey, prefix: &str) -> bool {104 strip_key_prefix(key, prefix).is_some()105}90106pallets/proxy-rmrk-core/src/rpc.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-core/src/rpc.rs
+++ b/pallets/proxy-rmrk-core/src/rpc.rs
@@ -132,17 +132,6 @@
Ok(
pallet_nonfungible::TokenChildren::<T>::iter_prefix((collection_id, nft_id))
.filter_map(|((child_collection, child_token), _)| {
- let is_pending = <Pallet<T>>::get_nft_property_decoded(
- child_collection,
- child_token,
- RmrkProperty::PendingNftAccept,
- )
- .ok()?;
-
- if is_pending {
- return None;
- }
-
let rmrk_child_collection =
<Pallet<T>>::rmrk_collection_id(child_collection).ok()?;
@@ -151,6 +140,13 @@
nft_id: child_token.0,
})
})
+ .chain(
+ <Pallet<T>>::iterate_pending_children(collection_id, nft_id)?
+ .map(|(child_collection, child_nft_id)| RmrkNftChild {
+ collection_id: child_collection,
+ nft_id: child_nft_id,
+ })
+ )
.collect(),
)
}
@@ -224,7 +220,11 @@
nft_id,
PropertyScope::Rmrk,
)
- .filter_map(|(_, value)| {
+ .filter_map(|(key, value)| {
+ if !is_valid_key_prefix(&key, RESOURCE_ID_PREFIX) {
+ return None;
+ }
+
let resource_info: RmrkResourceInfo = <Pallet<T>>::decode_property(&value).ok()?;
Some(resource_info)