git.delta.rocks / unique-network / refs/commits / 51e15a07c4a1

difftreelog

fix(rmrk) include pending children into nft_children RPC

Daniel Shiposha2022-06-30parent: #66c5541.patch.diff
in: master

3 files changed

modifiedpallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth
20 pallet_prelude::*,
21 transactional,
22 BoundedVec,
23 dispatch::DispatchResult,
24};
20use frame_system::{pallet_prelude::*, ensure_signed};25use frame_system::{pallet_prelude::*, ensure_signed};
21use sp_runtime::{DispatchError, Permill, traits::StaticLookup};26use sp_runtime::{DispatchError, Permill, traits::StaticLookup};
22use sp_std::vec::Vec;27use sp_std::{vec::Vec, collections::btree_set::BTreeSet};
23use up_data_structs::{*, mapping::TokenAddressMapping};28use up_data_structs::{*, mapping::TokenAddressMapping};
24use pallet_common::{29use pallet_common::{
25 Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations,30 Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations,
4853
49pub const NESTING_BUDGET: u32 = 5;54pub const NESTING_BUDGET: u32 = 5;
55
56type PendingTarget = (CollectionId, TokenId);
57type PendingChild = (RmrkCollectionId, RmrkNftId);
58type PendingChildrenMap = BTreeSet<PendingChild>;
5059
51#[frame_support::pallet]60#[frame_support::pallet]
52pub mod pallet {61pub mod pallet {
383 [392 [
384 Self::rmrk_property(TokenType, &NftType::Regular)?,393 Self::rmrk_property(TokenType, &NftType::Regular)?,
385 Self::rmrk_property(Transferable, &transferable)?,394 Self::rmrk_property(Transferable, &transferable)?,
386 Self::rmrk_property(PendingNftAccept, &false)?,395 Self::rmrk_property(PendingNftAccept, &None::<PendingTarget>)?,
387 Self::rmrk_property(RoyaltyInfo, &royalty_info)?,396 Self::rmrk_property(RoyaltyInfo, &royalty_info)?,
388 Self::rmrk_property(Metadata, &metadata)?,397 Self::rmrk_property(Metadata, &metadata)?,
389 Self::rmrk_property(Equipped, &false)?,398 Self::rmrk_property(Equipped, &false)?,
390 Self::rmrk_property(ResourcePriorities, &<Vec<u8>>::new())?,399 Self::rmrk_property(ResourcePriorities, &<Vec<u8>>::new())?,
391 Self::rmrk_property(NextResourceId, &(0 as RmrkResourceId))?,400 Self::rmrk_property(NextResourceId, &(0 as RmrkResourceId))?,
401 Self::rmrk_property(PendingChildren, &PendingChildrenMap::new())?,
392 ]402 ]
393 .into_iter(),403 .into_iter(),
394 )404 )
483 );493 );
484494
485 ensure!(495 ensure!(
486 !Self::get_nft_property_decoded(496 Self::get_nft_property_decoded::<Option<PendingTarget>>(
487 collection_id,497 collection_id,
488 nft_id,498 nft_id,
489 RmrkProperty::PendingNftAccept499 RmrkProperty::PendingNftAccept
490 )?,500 )?.is_none(),
491 <Error<T>>::NoPermission501 <Error<T>>::NoPermission
492 );502 );
493503
524 collection.id,534 collection.id,
525 nft_id,535 nft_id,
526 PropertyScope::Rmrk,536 PropertyScope::Rmrk,
527 Self::rmrk_property(PendingNftAccept, &approval_required)?,537 Self::rmrk_property::<Option<PendingTarget>>(
538 PendingNftAccept,
539 &Some((target_collection_id, target_nft_id.into()))
540 )?,
528 )?;541 )?;
542
543 Self::insert_pending_child(
544 (target_collection_id, target_nft_id.into()),
545 (rmrk_collection_id, rmrk_nft_id),
546 )?;
529 } else {547 } else {
530 target_owner = T::CrossTokenAddressMapping::token_to_address(548 target_owner = T::CrossTokenAddressMapping::token_to_address(
531 target_collection_id,549 target_collection_id,
618 }636 }
619 })?;637 })?;
638
639 let pending_target = Self::get_nft_property_decoded::<Option<PendingTarget>>(
640 collection_id,
641 nft_id,
642 RmrkProperty::PendingNftAccept
643 )?;
644
645 if let Some(pending_target) = pending_target {
646 Self::remove_pending_child(pending_target, (rmrk_collection_id, rmrk_nft_id))?;
620647
621 <PalletNft<T>>::set_scoped_token_property(648 <PalletNft<T>>::set_scoped_token_property(
622 collection.id,649 collection.id,
623 nft_id,650 nft_id,
624 PropertyScope::Rmrk,651 PropertyScope::Rmrk,
625 Self::rmrk_property(PendingNftAccept, &false)?,652 Self::rmrk_property(PendingNftAccept, &None::<PendingTarget>)?,
626 )?;653 )?;
654 }
627655
628 Self::deposit_event(Event::NFTAccepted {656 Self::deposit_event(Event::NFTAccepted {
629 sender,657 sender,
663 <Error<T>>::NoAvailableNftId691 <Error<T>>::NoAvailableNftId
664 );692 );
665693
666 ensure!(694
667 Self::get_nft_property_decoded(695 let pending_target = Self::get_nft_property_decoded::<Option<PendingTarget>>(
668 collection_id,696 collection_id,
669 nft_id,697 nft_id,
670 RmrkProperty::PendingNftAccept698 RmrkProperty::PendingNftAccept
671 )?,699 )?;
672 <Error<T>>::CannotRejectNonPendingNft700
673 );701 match pending_target {
702 Some(pending_target) => Self::remove_pending_child(pending_target, (rmrk_collection_id, rmrk_nft_id))?,
703 None => return Err(<Error<T>>::CannotRejectNonPendingNft.into()),
704 }
674705
675 Self::destroy_nft(706 Self::destroy_nft(
676 cross_sender,707 cross_sender,
1147 )1178 )
1148 }1179 }
1180
1181 fn insert_pending_child(
1182 target: (CollectionId, TokenId),
1183 child: (RmrkCollectionId, RmrkNftId),
1184 ) -> DispatchResult {
1185 Self::mutate_pending_child(target, |pending_children| {
1186 pending_children.insert(child);
1187 })
1188 }
1189
1190 fn remove_pending_child(
1191 target: (CollectionId, TokenId),
1192 child: (RmrkCollectionId, RmrkNftId),
1193 ) -> DispatchResult {
1194 Self::mutate_pending_child(target, |pending_children| {
1195 pending_children.remove(&child);
1196 })
1197 }
1198
1199 fn mutate_pending_child(
1200 (target_collection_id, target_nft_id): (CollectionId, TokenId),
1201 f: impl FnOnce(&mut PendingChildrenMap),
1202 ) -> DispatchResult {
1203 <PalletNft<T>>::try_mutate_token_aux_property(
1204 target_collection_id,
1205 target_nft_id,
1206 PropertyScope::Rmrk,
1207 Self::rmrk_property_key(PendingChildren)?,
1208 |pending_children| -> DispatchResult {
1209 let mut map = match pending_children {
1210 Some(map) => Self::decode_property(map)?,
1211 None => PendingChildrenMap::new(),
1212 };
1213
1214 f(&mut map);
1215
1216 *pending_children = Some(Self::encode_property(&map)?);
1217
1218 Ok(())
1219 },
1220 )
1221 }
1222
1223 fn iterate_pending_children(collection_id: CollectionId, nft_id: TokenId) -> Result<impl Iterator<Item=PendingChild>, DispatchError> {
1224 let property = <PalletNft<T>>::token_aux_property((
1225 collection_id,
1226 nft_id,
1227 PropertyScope::Rmrk,
1228 Self::rmrk_property_key(PendingChildren)?
1229 ));
1230
1231 let pending_children = match property {
1232 Some(map) => Self::decode_property(&map)?,
1233 None => PendingChildrenMap::new(),
1234 };
1235
1236 Ok(pending_children.into_iter())
1237 }
11491238
1150 fn acquire_next_resource_id(1239 fn acquire_next_resource_id(
1151 collection_id: CollectionId,1240 collection_id: CollectionId,
1526 Value: Decode + Default,1615 Value: Decode + Default,
1527 Mapper: Fn(Key, Value) -> R,1616 Mapper: Fn(Key, Value) -> R,
1528 {1617 {
1529 let key_prefix = Self::rmrk_property_key(UserProperty(b""))?;
1530
1531 let properties = match token_id {1618 let properties = match token_id {
1532 Some(token_id) => <PalletNft<T>>::token_properties((collection_id, token_id)),1619 Some(token_id) => <PalletNft<T>>::token_properties((collection_id, token_id)),
1533 None => <PalletCommon<T>>::collection_properties(collection_id),1620 None => <PalletCommon<T>>::collection_properties(collection_id),
1534 };1621 };
15351622
1536 let properties = properties.into_iter().filter_map(move |(key, value)| {1623 let properties = properties.into_iter().filter_map(move |(key, value)| {
1537 let key = key.as_slice().strip_prefix(key_prefix.as_slice())?;1624 let key = strip_key_prefix(&key, USER_PROPERTY_PREFIX)?;
15381625
1539 let key: Key = key.to_vec().try_into().ok()?;1626 let key: Key = key.to_vec().try_into().ok()?;
1540 let value: Value = value.decode().ok()?;1627 let value: Value = value.decode().ok()?;
modifiedpallets/proxy-rmrk-core/src/property.rsdiffbeforeafterboth
15// 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/>.
1616
17use super::*;17use super::*;
18use up_data_structs::PropertyScope;
18use core::convert::AsRef;19use core::convert::AsRef;
1920
20const RESOURCE_ID_PREFIX: &str = "rsid-";21pub const RESOURCE_ID_PREFIX: &str = "rsid-";
22pub const USER_PROPERTY_PREFIX: &str = "userprop-";
2123
22pub 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}
94
95pub 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()?;
98
99 key.as_slice().strip_prefix(key_prefix.as_slice())?
100 .to_vec().try_into().ok()
101}
102
103pub fn is_valid_key_prefix(key: &PropertyKey, prefix: &str) -> bool {
104 strip_key_prefix(key, prefix).is_some()
105}
90106
modifiedpallets/proxy-rmrk-core/src/rpc.rsdiffbeforeafterboth
131131
132 Ok(132 Ok(
133 pallet_nonfungible::TokenChildren::<T>::iter_prefix((collection_id, nft_id))133 pallet_nonfungible::TokenChildren::<T>::iter_prefix((collection_id, nft_id))
134 .filter_map(|((child_collection, child_token), _)| {134 .filter_map(|((child_collection, child_token), _)| {
135 let is_pending = <Pallet<T>>::get_nft_property_decoded(
136 child_collection,
137 child_token,
138 RmrkProperty::PendingNftAccept,
139 )
140 .ok()?;
141
142 if is_pending {
143 return None;
144 }
145
146 let rmrk_child_collection =135 let rmrk_child_collection =
147 <Pallet<T>>::rmrk_collection_id(child_collection).ok()?;136 <Pallet<T>>::rmrk_collection_id(child_collection).ok()?;
150 collection_id: rmrk_child_collection,139 collection_id: rmrk_child_collection,
151 nft_id: child_token.0,140 nft_id: child_token.0,
152 })141 })
153 })142 })
143 .chain(
144 <Pallet<T>>::iterate_pending_children(collection_id, nft_id)?
145 .map(|(child_collection, child_nft_id)| RmrkNftChild {
146 collection_id: child_collection,
147 nft_id: child_nft_id,
148 })
149 )
154 .collect(),150 .collect(),
155 )151 )
156}152}
224 nft_id,220 nft_id,
225 PropertyScope::Rmrk,221 PropertyScope::Rmrk,
226 )222 )
227 .filter_map(|(_, value)| {223 .filter_map(|(key, value)| {
224 if !is_valid_key_prefix(&key, RESOURCE_ID_PREFIX) {
225 return None;
226 }
227
228 let resource_info: RmrkResourceInfo = <Pallet<T>>::decode_property(&value).ok()?;228 let resource_info: RmrkResourceInfo = <Pallet<T>>::decode_property(&value).ok()?;
229229