git.delta.rocks / unique-network / refs/commits / 7c4183b4cb3a

difftreelog

feat(rmrk-rpc) nft resources and priorities

Fahrrader2022-05-26parent: #5c5d937.patch.diff
in: master

6 files changed

modifiedpallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth
--- a/pallets/proxy-rmrk-core/src/lib.rs
+++ b/pallets/proxy-rmrk-core/src/lib.rs
@@ -486,9 +486,8 @@
         }
     }
 
-    // should this even be here, might displace it to common/nonfungible -- but they did not need it, only rmrk does
     pub fn collection_exists(collection_id: CollectionId) -> bool {
-        <pallet_common::CollectionById<T>>::contains_key(collection_id)
+        <CollectionHandle<T>>::try_get(collection_id).is_ok()
     }
 
     pub fn nft_exists(collection_id: CollectionId, nft_id: TokenId) -> bool {
modifiedpallets/proxy-rmrk-core/src/misc.rsdiffbeforeafterboth
--- a/pallets/proxy-rmrk-core/src/misc.rs
+++ b/pallets/proxy-rmrk-core/src/misc.rs
@@ -26,18 +26,6 @@
     }
 }
 
-pub trait RmrkRebind<T, S> {
-    fn rebind(&self) -> BoundedVec<u8, S>;
-}
-
-impl<T, S> RmrkRebind<T, S> for BoundedVec<u8, T> where BoundedVec<u8, S>: TryFrom<Vec<u8>> {
-    fn rebind(&self) -> BoundedVec<u8, S> {
-        BoundedVec::<u8, S>::try_from(
-            self.clone().into_inner()
-        ).unwrap_or_default()
-    }
-}
-
 #[derive(Encode, Decode, PartialEq, Eq)]
 pub enum CollectionType {
     Regular,
modifiedprimitives/data-structs/src/lib.rsdiffbeforeafterboth
--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -49,6 +49,7 @@
 	},
 	NftChild as RmrkNftChild, AccountIdOrCollectionNftTuple as RmrkAccountIdOrCollectionNftTuple,
 	FixedPart as RmrkFixedPart, SlotPart as RmrkSlotPart, EquippableList as RmrkEquippableList,
+	BasicResource as RmrkBasicResource, ComposableResource as RmrkComposableResource, SlotResource as RmrkSlotResource,
 };
 
 mod bounded;
@@ -925,17 +926,14 @@
 	}
 }
 
-pub type RmrkCollectionSymbol = BoundedVec<u8, RmrkCollectionSymbolLimit>;
 pub type RmrkCollectionInfo<AccountId> =
 	CollectionInfo<RmrkString, RmrkCollectionSymbol, AccountId>;
 pub type RmrkInstanceInfo<AccountId> = NftInfo<AccountId, Permill, RmrkString>;
 pub type RmrkResourceInfo = ResourceInfo<
-	BoundedVec<u8, RmrkResourceSymbolLimit>,
+	RmrkBoundedResource,
 	RmrkString,
-	BoundedVec<RmrkPartId, RmrkPartsLimit>,
+	RmrkBoundedParts,
 >;
-pub type RmrkKeyString = BoundedVec<u8, RmrkKeyLimit>;
-pub type RmrkValueString = BoundedVec<u8, RmrkValueLimit>;
 pub type RmrkPropertyInfo = PropertyInfo<RmrkKeyString, RmrkValueString>;
 pub type RmrkBaseInfo<AccountId> = BaseInfo<AccountId, RmrkString>;
 pub type RmrkPartType =
@@ -943,6 +941,13 @@
 pub type RmrkThemeProperty = ThemeProperty<RmrkString>;
 pub type RmrkTheme = Theme<RmrkString, Vec<RmrkThemeProperty>>;
 
+pub type RmrkCollectionSymbol = BoundedVec<u8, RmrkCollectionSymbolLimit>;
+pub type RmrkKeyString = BoundedVec<u8, RmrkKeyLimit>;
+pub type RmrkValueString = BoundedVec<u8, RmrkValueLimit>;
+
+type RmrkBoundedResource = BoundedVec<u8, RmrkResourceSymbolLimit>;
+type RmrkBoundedParts = BoundedVec<RmrkPartId, RmrkPartsLimit>;
+
 pub type RmrkRpcString = Vec<u8>;
 pub type RmrkThemeName = RmrkRpcString;
 pub type RmrkPropertyKey = RmrkRpcString;
modifiedprimitives/data-structs/src/rmrk.rsdiffbeforeafterboth
--- a/primitives/data-structs/src/rmrk.rs
+++ b/primitives/data-structs/src/rmrk.rs
@@ -154,7 +154,7 @@
 	pub value: BoundedValue,
 }
 
-#[derive(Encode, Decode, Eq, PartialEq, Clone, Debug, TypeInfo, MaxEncodedLen)]
+#[derive(Encode, Decode, Default, Eq, PartialEq, Clone, Debug, TypeInfo, MaxEncodedLen)]
 #[cfg_attr(feature = "std", derive(Serialize))]
 #[cfg_attr(
 	feature = "std",
@@ -275,7 +275,7 @@
 	pub thumb: Option<BoundedString>,
 }
 
-#[derive(Encode, Decode, Eq, PartialEq, Clone, Debug, TypeInfo, MaxEncodedLen)]
+#[derive(Encode, Decode, Derivative, Eq, PartialEq, Clone, Debug, TypeInfo, MaxEncodedLen)]
 #[cfg_attr(feature = "std", derive(Serialize))]
 #[cfg_attr(
 	feature = "std",
@@ -286,7 +286,9 @@
 		"#
 	)
 )]
-pub enum ResourceTypes<BoundedString, BoundedParts> {
+#[derivative(Default(bound=""))]
+pub enum ResourceTypes<BoundedString: Default, BoundedParts> {
+	#[derivative(Default)]
 	Basic(BasicResource<BoundedString>),
 	Composable(ComposableResource<BoundedString, BoundedParts>),
 	Slot(SlotResource<BoundedString>),
@@ -305,7 +307,7 @@
 		"#
 	)
 )]
-pub struct ResourceInfo<BoundedResource, BoundedString, BoundedParts> {
+pub struct ResourceInfo<BoundedResource, BoundedString: Default, BoundedParts> {
 	/// id is a 5-character string of reasonable uniqueness.
 	/// The combination of base ID and resource id should be unique across the entire RMRK
 	/// ecosystem which
modifiedruntime/common/src/runtime_apis.rsdiffbeforeafterboth
146 }146 }
147147
148 fn collection_by_id(collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {148 fn collection_by_id(collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {
149 use frame_support::BoundedVec;
150 use scale_info::prelude::string::String;
151 use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, RmrkRebind, RmrkDecode}};149 use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, RmrkDecode}};
152150
153 let collection_id = CollectionId(collection_id);151 let collection_id = CollectionId(collection_id);
154 let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {152 let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {
155 Ok(c) => c,153 Ok(c) => c,
156 Err(_) => return Ok(None),154 Err(_) => return Ok(None),
157 };155 };
158156
159 let nfts_count = (dispatch_unique_runtime!(collection_id.total_supply()) as Result<u32, DispatchError>)?;157 let nfts_count = dispatch_unique_runtime!(collection_id.total_supply())?;
160 //<Runtime as up_rpc::UniqueApi>::total_supply(collection_id); // todo can't find UniqueApi with disabled default features
161158
162 Ok(Some(RmrkCollectionInfo {159 Ok(Some(RmrkCollectionInfo {
163 issuer: collection.owner.clone(),160 issuer: collection.owner.clone(),
164 metadata: RmrkCore::get_collection_property(collection_id, RmrkProperty::Metadata)?.decode_or_default(),161 metadata: RmrkCore::get_collection_property(collection_id, RmrkProperty::Metadata)?.decode_or_default(),
165 max: collection.limits.token_limit,162 max: collection.limits.token_limit,
166 symbol: collection.token_prefix.rebind(), // change163 symbol: collection.token_prefix.decode_or_default(),
167 nfts_count164 nfts_count
168 }))165 }))
169 }166 }
170167
171 fn nft_by_id(collection_id: RmrkCollectionId, nft_by_id: RmrkNftId) -> Result<Option<RmrkInstanceInfo<AccountId>>, DispatchError> {168 fn nft_by_id(collection_id: RmrkCollectionId, nft_by_id: RmrkNftId) -> Result<Option<RmrkInstanceInfo<AccountId>>, DispatchError> {
172 use frame_support::BoundedVec;
173 use up_data_structs::mapping::TokenAddressMapping;169 use up_data_structs::mapping::TokenAddressMapping;
174 use pallet_proxy_rmrk_core::{RmrkProperty, misc::RmrkDecode};170 use pallet_proxy_rmrk_core::{RmrkProperty, misc::RmrkDecode};
175171
176 let collection_id = CollectionId(collection_id);172 let collection_id = CollectionId(collection_id);
177 let nft_id = TokenId(nft_by_id);173 let nft_id = TokenId(nft_by_id);
178 if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(None); }174 if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(None); }
179175
180 let owner = match (dispatch_unique_runtime!(collection_id.token_owner(nft_id)) as Result<Option<CrossAccountId>, DispatchError>)? {176 let owner = match dispatch_unique_runtime!(collection_id.token_owner(nft_id))? {
181 Some(owner) => match <Runtime as pallet_common::Config>::CrossTokenAddressMapping::address_to_token(&owner) {177 Some(owner) => match <Runtime as pallet_common::Config>::CrossTokenAddressMapping::address_to_token(&owner) {
182 Some((col, tok)) => RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(col.0, tok.0),178 Some((col, tok)) => RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(col.0, tok.0),
183 None => RmrkAccountIdOrCollectionNftTuple::AccountId(owner.as_sub().clone())179 None => RmrkAccountIdOrCollectionNftTuple::AccountId(owner.as_sub().clone())
197 }193 }
198194
199 fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {195 fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {
196 use pallet_proxy_rmrk_core::misc::CollectionType;
197
200 let cross_account_id = CrossAccountId::from_sub(account_id);198 let cross_account_id = CrossAccountId::from_sub(account_id);
201 let collection_id = CollectionId(collection_id);199 let collection_id = CollectionId(collection_id);
202 if !RmrkCore::collection_exists(collection_id) { return Ok(Vec::new()); }200 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }
203201
204 Ok(202 Ok(
205 (dispatch_unique_runtime!(collection_id.account_tokens(cross_account_id)) as Result<Vec<TokenId>, DispatchError>)?203 dispatch_unique_runtime!(collection_id.account_tokens(cross_account_id))?
206 //<Runtime as up_rpc::UniqueApi<Block, CrossAccountId, AccountId>>::account_tokens(collection_id, cross_account_id)?
207 .into_iter()204 .into_iter()
208 .map(|token| token.0)205 .map(|token| token.0)
209 .collect::<Vec<_>>()206 .collect()
210 )207 )
211 }208 }
212209
277273
278 fn nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {274 fn nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {
279 use frame_support::BoundedVec;275 use frame_support::BoundedVec;
280 use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};276 use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, RmrkDecode}};
281277
282 let collection_id = CollectionId(collection_id);278 let collection_id = CollectionId(collection_id);
283 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Resource).is_err() { return Ok(Vec::new()); }279 if !RmrkCore::collection_exists(collection_id) { return Ok(Vec::new()); } // todo make sure the collection type doesn't matter
284280
285 let nft_id = TokenId(nft_id);281 let nft_id = TokenId(nft_id);
286 if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Resource).is_err() { return Ok(Vec::new()); }282 if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Resource).is_err() { return Ok(Vec::new()); }
287283
284 let resource_collection_id: CollectionId = RmrkCore::get_nft_property(collection_id, nft_id, RmrkProperty::ResourceCollection)
285 .unwrap()
286 .decode_or_default();
288 Ok(Vec::new(/*[RmrkResourceInfo {287 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Resource).is_err() { return Ok(Vec::new()); }
289288
290 }]*/))289 let resources = pallet_nonfungible::TokenProperties::<Runtime>::iter_prefix((resource_collection_id,))
290 .filter_map(|(resource_id, properties)| Some(RmrkResourceInfo {
291 id: BoundedVec::default(), // todo ResourceId property
292 pending: RmrkCore::get_nft_property(resource_collection_id, resource_id, RmrkProperty::PendingResourceAccept).unwrap().decode_or_default(),
293 pending_removal: RmrkCore::get_nft_property(resource_collection_id, resource_id, RmrkProperty::PendingResourceRemoval).unwrap().decode_or_default(),
294 resource: RmrkCore::get_nft_property(resource_collection_id, resource_id, RmrkProperty::ResourceType).unwrap().decode_or_default(),/* {
295 RmrkResourceTypes::Basic(resource) => RmrkResourceTypes::Basic(),/*(RmrkBasicResource {
296 src: RmrkCore::get_nft_property_inner(properties, RmrkProperty::Src).unwrap().decode_or_default(),
297 metadata: RmrkCore::get_nft_property_inner(properties, RmrkProperty::Metadata).unwrap().decode_or_default(),
298 license: RmrkCore::get_nft_property_inner(properties, RmrkProperty::License).unwrap().decode_or_default(),
299 thumb: RmrkCore::get_nft_property_inner(properties, RmrkProperty::Thumb).unwrap().decode_or_default(),
300 },*///BasicResource<BoundedString>)
301 _ => todo!(), //RmrkResourceTypes::Composable(ComposableResource<BoundedString, BoundedParts>),
302 //RmrkResourceTypes::Slot(SlotResource<BoundedString>),
303 },*/
304 }))
305 .collect();
306
307 Ok(resources)
291 }308 }
292309
293 fn nft_resource_priorities(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceId>, DispatchError> {310 fn nft_resource_priorities(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceId>, DispatchError> {
311 use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, RmrkDecode}};
312
313 let collection_id = CollectionId(collection_id);
294 todo!()314 if !RmrkCore::collection_exists(collection_id) { return Ok(Vec::new()); } // todo ensure the collection type doesn't matter
315
316 let nft_id = TokenId(nft_id);
317 if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Resource).is_err() { return Ok(Vec::new()); }
318
319 /*let resource_collection_id: CollectionId = RmrkCore::get_nft_property(collection_id, nft_id, RmrkProperty::ResourceCollection)
320 .unwrap()
321 .decode_or_default();
322 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Resource).is_err() { return Ok(Vec::new()); }
323
324 let resources = pallet_nonfungible::TokenProperties::<Runtime>::iter_prefix((resource_collection_id,))
325 .filter_map(|(resource_id, properties)| Some((
326 resource_id, // ResourceId property
327 RmrkCore::get_nft_property(resource_collection_id, resource_id, RmrkProperty::Priority).unwrap().decode_or_default(),
328 )))
329 .collect()
330 .sort_by_key(|(_, index)| *index)
331 .into_iter().map(|(resource_id, _)| resource_id)*/
332 let priorities = RmrkCore::get_nft_property(collection_id, nft_id, RmrkProperty::ResourcePriorities)?.decode_or_default();
333
334 Ok(priorities)
295 }335 }
296336
297 fn base(base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {337 fn base(base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {
298 use frame_support::BoundedVec;
299 use scale_info::prelude::string::String;
300 use pallet_proxy_rmrk_core::{338 use pallet_proxy_rmrk_core::{
301 RmrkProperty, misc::{CollectionType, RmrkRebind, RmrkDecode},339 RmrkProperty, misc::{CollectionType, RmrkDecode},
302 };340 };
303341
304 let collection_id = CollectionId(base_id);342 let collection_id = CollectionId(base_id);
310 Ok(Some(RmrkBaseInfo {348 Ok(Some(RmrkBaseInfo {
311 issuer: collection.owner.clone(),349 issuer: collection.owner.clone(),
312 base_type: RmrkCore::get_collection_property(collection_id, RmrkProperty::BaseType)?.decode_or_default(),350 base_type: RmrkCore::get_collection_property(collection_id, RmrkProperty::BaseType)?.decode_or_default(),
313 symbol: collection.token_prefix.rebind(),351 symbol: collection.token_prefix.decode_or_default(),
314 }))352 }))
315 }353 }
316354
317 fn base_parts(base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {355 fn base_parts(base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {
318 use frame_support::BoundedVec;
319 use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, RmrkDecode}};356 use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, RmrkDecode}};
320357
321 let collection_id = CollectionId(base_id);358 let collection_id = CollectionId(base_id);
322 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() { return Ok(Vec::new()); }359 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() { return Ok(Vec::new()); }
323360
324 let parts = (dispatch_unique_runtime!(collection_id.collection_tokens()))?361 let parts = dispatch_unique_runtime!(collection_id.collection_tokens())?
325 .into_iter()362 .into_iter()
326 .filter_map(|token_id| {363 .filter_map(|token_id| {
327 let nft_type = RmrkCore::get_nft_type(collection_id, token_id).ok()?;364 let nft_type = RmrkCore::get_nft_type(collection_id, token_id).ok()?;
347 }384 }
348385
349 fn theme_names(base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {386 fn theme_names(base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {
350 use frame_support::BoundedVec;
351 use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, RmrkDecode}};387 use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, RmrkDecode}};
352388
353 let collection_id = CollectionId(base_id);389 let collection_id = CollectionId(base_id);
354 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() {390 if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() {
355 return Ok(Vec::new());391 return Ok(Vec::new());
356 }392 }
357393
358 let theme_names = (dispatch_unique_runtime!(collection_id.collection_tokens()))?394 let theme_names = dispatch_unique_runtime!(collection_id.collection_tokens())?
359 .iter()395 .iter()
360 .filter_map(|token_id| {396 .filter_map(|token_id| {
361 let nft_type = RmrkCore::get_nft_type(collection_id, *token_id).unwrap();397 let nft_type = RmrkCore::get_nft_type(collection_id, *token_id).unwrap();
373 }409 }
374410
375 fn theme(base_id: RmrkBaseId, theme_name: RmrkThemeName, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Option<RmrkTheme>, DispatchError> {411 fn theme(base_id: RmrkBaseId, theme_name: RmrkThemeName, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Option<RmrkTheme>, DispatchError> {
376 use frame_support::BoundedVec;
377 use pallet_proxy_rmrk_core::{412 use pallet_proxy_rmrk_core::{
378 RmrkProperty,413 RmrkProperty,
379 misc::{CollectionType, NftType, RmrkDecode}414 misc::{CollectionType, NftType, RmrkDecode}
384 return Ok(None);419 return Ok(None);
385 }420 }
386421
387 let theme_info = (dispatch_unique_runtime!(collection_id.collection_tokens()))?422 let theme_info = dispatch_unique_runtime!(collection_id.collection_tokens())?
388 .into_iter()423 .into_iter()
389 .find_map(|token_id| {424 .find_map(|token_id| {
390 RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Theme).ok()?;425 RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Theme).ok()?;
modifiedtests/src/nesting/properties.test.tsdiffbeforeafterboth
--- a/tests/src/nesting/properties.test.ts
+++ b/tests/src/nesting/properties.test.ts
@@ -711,7 +711,7 @@
     });
   });
 
-  it('Forbids changing/deleting properties of a token if the property is permanent (constant)', async () => {
+  it('Forbids changing/deleting properties of a token if the property is permanent (immutable)', async () => {
     await usingApi(async api => {
       let i = -1;
       for (const permission of constitution) {