difftreelog
feat(rmrk-rpc) nft resources and priorities
in: master
6 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
@@ -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 {
pallets/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,
primitives/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;
primitives/data-structs/src/rmrk.rsdiffbeforeafterboth1use codec::{Decode, Encode, MaxEncodedLen};2use scale_info::TypeInfo;34use derivative::Derivative;56#[cfg(feature = "std")]7use serde::Serialize;89use primitives::*;1011pub mod primitives {12 pub type CollectionId = u32;13 pub type ResourceId = u32;14 pub type NftId = u32;15 pub type BaseId = u32;16 pub type SlotId = u32;17 pub type PartId = u32;18 pub type ZIndex = u32;19}2021#[cfg(feature = "std")]22mod serialize {23 use core::convert::AsRef;24 use serde::ser::{self, Serialize};2526 pub mod vec {27 use super::*;2829 pub fn serialize<D, V, C>(value: &C, serializer: D) -> Result<D::Ok, D::Error>30 where31 D: ser::Serializer,32 V: Serialize,33 C: AsRef<[V]>,34 {35 value.as_ref().serialize(serializer)36 }37 }3839 pub mod opt_vec {40 use super::*;4142 pub fn serialize<D, V, C>(value: &Option<C>, serializer: D) -> Result<D::Ok, D::Error>43 where44 D: ser::Serializer,45 V: Serialize,46 C: AsRef<[V]>,47 {48 match value {49 Some(value) => super::vec::serialize(value, serializer),50 None => serializer.serialize_none()51 }52 }53 }54}5556/// Collection info.57#[cfg_attr(feature = "std", derive(PartialEq, Eq, Serialize))]58#[derive(Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]59#[cfg_attr(60 feature = "std",61 serde(62 bound = r#"63 AccountId: Serialize,64 BoundedString: AsRef<[u8]>,65 BoundedSymbol: AsRef<[u8]>66 "#67 )68)]69pub struct CollectionInfo<BoundedString, BoundedSymbol, AccountId> {70 /// Current bidder and bid price.71 pub issuer: AccountId,7273 #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]74 pub metadata: BoundedString,75 pub max: Option<u32>,7677 #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]78 pub symbol: BoundedSymbol,79 pub nfts_count: u32,80}8182#[derive(Encode, Decode, Eq, PartialEq, Copy, Clone, Debug, TypeInfo, MaxEncodedLen)]83#[cfg_attr(feature = "std", derive(Serialize))]84pub enum AccountIdOrCollectionNftTuple<AccountId> {85 AccountId(AccountId),86 CollectionAndNftTuple(CollectionId, NftId),87}8889/// Royalty information (recipient and amount)90#[cfg_attr(feature = "std", derive(PartialEq, Eq, Serialize))]91#[derive(Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]92pub struct RoyaltyInfo<AccountId, RoyaltyAmount> {93 /// Recipient (AccountId) of the royalty94 pub recipient: AccountId,95 /// Amount (Permill) of the royalty96 pub amount: RoyaltyAmount,97}9899/// Nft info.100#[cfg_attr(feature = "std", derive(PartialEq, Eq, Serialize))]101#[derive(Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]102#[cfg_attr(103 feature = "std",104 serde(105 bound = r#"106 AccountId: Serialize,107 RoyaltyAmount: Serialize,108 BoundedString: AsRef<[u8]>109 "#110 )111)]112pub struct NftInfo<AccountId, RoyaltyAmount, BoundedString> {113 /// The owner of the NFT, can be either an Account or a tuple (CollectionId, NftId)114 pub owner: AccountIdOrCollectionNftTuple<AccountId>,115 /// Royalty (optional)116 pub royalty: Option<RoyaltyInfo<AccountId, RoyaltyAmount>>,117118 /// Arbitrary data about an instance, e.g. IPFS hash119 #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]120 pub metadata: BoundedString,121122 /// Equipped state123 pub equipped: bool,124 /// Pending state (if sent to NFT)125 pub pending: bool,126}127128#[cfg_attr(feature = "std", derive(PartialEq, Eq, Serialize))]129#[derive(Encode, Decode, TypeInfo, MaxEncodedLen)]130pub struct NftChild {131 pub collection_id: CollectionId,132 pub nft_id: NftId133}134135#[cfg_attr(feature = "std", derive(Serialize))]136#[derive(Encode, Decode, PartialEq, TypeInfo)]137#[cfg_attr(138 feature = "std",139 serde(140 bound = r#"141 BoundedKey: AsRef<[u8]>,142 BoundedValue: AsRef<[u8]>143 "#144 )145)]146pub struct PropertyInfo<BoundedKey, BoundedValue>147{148 /// Key of the property149 #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]150 pub key: BoundedKey,151152 /// Value of the property153 #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]154 pub value: BoundedValue,155}156157#[derive(Encode, Decode, Eq, PartialEq, Clone, Debug, TypeInfo, MaxEncodedLen)]158#[cfg_attr(feature = "std", derive(Serialize))]159#[cfg_attr(160 feature = "std",161 serde(bound = "BoundedString: AsRef<[u8]>")162)]163pub struct BasicResource<BoundedString> {164 /// If the resource is Media, the base property is absent. Media src should be a URI like an165 /// IPFS hash.166 #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]167 pub src: Option<BoundedString>,168169 /// Reference to IPFS location of metadata170 #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]171 pub metadata: Option<BoundedString>,172173 /// Optional location or identier of license174 #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]175 pub license: Option<BoundedString>,176177 /// If the resource has the thumb property, this will be a URI to a thumbnail of the given178 /// resource. For example, if we have a composable NFT like a Kanaria bird, the resource is179 /// complex and too detailed to show in a search-results page or a list. Also, if a bird owns180 /// another bird, showing the full render of one bird inside the other's inventory might be a181 /// bit of a strain on the browser. For this reason, the thumb value can contain a URI to an182 /// image that is lighter and faster to load but representative of this resource.183 #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]184 pub thumb: Option<BoundedString>,185}186187#[derive(Encode, Decode, Eq, PartialEq, Clone, Debug, TypeInfo, MaxEncodedLen)]188#[cfg_attr(feature = "std", derive(Serialize))]189#[cfg_attr(190 feature = "std",191 serde(192 bound = r#"193 BoundedString: AsRef<[u8]>,194 BoundedParts: AsRef<[PartId]>195 "#196 )197)]198pub struct ComposableResource<BoundedString, BoundedParts> {199 /// If a resource is composed, it will have an array of parts that compose it200 #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]201 pub parts: BoundedParts,202203 /// A Base is uniquely identified by the combination of the word `base`, its minting block204 /// number, and user provided symbol during Base creation, glued by dashes `-`, e.g.205 /// base-4477293-kanaria_superbird.206 pub base: BaseId,207208 /// If the resource is Media, the base property is absent. Media src should be a URI like an209 /// IPFS hash.210 #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]211 pub src: Option<BoundedString>,212213 /// Reference to IPFS location of metadata214 #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]215 pub metadata: Option<BoundedString>,216217 /// If the resource has the slot property, it was designed to fit into a specific Base's slot.218 /// The baseslot will be composed of two dot-delimited values, like so:219 /// "base-4477293-kanaria_superbird.machine_gun_scope". This means: "This resource is220 /// compatible with the machine_gun_scope slot of base base-4477293-kanaria_superbird221222 /// Optional location or identier of license223 #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]224 pub license: Option<BoundedString>,225226 /// If the resource has the thumb property, this will be a URI to a thumbnail of the given227 /// resource. For example, if we have a composable NFT like a Kanaria bird, the resource is228 /// complex and too detailed to show in a search-results page or a list. Also, if a bird owns229 /// another bird, showing the full render of one bird inside the other's inventory might be a230 /// bit of a strain on the browser. For this reason, the thumb value can contain a URI to an231 /// image that is lighter and faster to load but representative of this resource.232 #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]233 pub thumb: Option<BoundedString>,234}235236#[derive(Encode, Decode, Eq, PartialEq, Clone, Debug, TypeInfo, MaxEncodedLen)]237#[cfg_attr(feature = "std", derive(Serialize))]238#[cfg_attr(239 feature = "std",240 serde(bound = "BoundedString: AsRef<[u8]>")241)]242pub struct SlotResource<BoundedString> {243 /// A Base is uniquely identified by the combination of the word `base`, its minting block244 /// number, and user provided symbol during Base creation, glued by dashes `-`, e.g.245 /// base-4477293-kanaria_superbird.246 pub base: BaseId,247248 /// If the resource is Media, the base property is absent. Media src should be a URI like an249 /// IPFS hash.250 #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]251 pub src: Option<BoundedString>,252253 /// Reference to IPFS location of metadata254 #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]255 pub metadata: Option<BoundedString>,256257 /// If the resource has the slot property, it was designed to fit into a specific Base's slot.258 /// The baseslot will be composed of two dot-delimited values, like so:259 /// "base-4477293-kanaria_superbird.machine_gun_scope". This means: "This resource is260 /// compatible with the machine_gun_scope slot of base base-4477293-kanaria_superbird261 pub slot: SlotId,262263 /// The license field, if present, should contain a link to a license (IPFS or static HTTP264 /// url), or an identifier, like RMRK_nocopy or ipfs://ipfs/someHashOfLicense.265 #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]266 pub license: Option<BoundedString>,267268 /// If the resource has the thumb property, this will be a URI to a thumbnail of the given269 /// resource. For example, if we have a composable NFT like a Kanaria bird, the resource is270 /// complex and too detailed to show in a search-results page or a list. Also, if a bird owns271 /// another bird, showing the full render of one bird inside the other's inventory might be a272 /// bit of a strain on the browser. For this reason, the thumb value can contain a URI to an273 /// image that is lighter and faster to load but representative of this resource.274 #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]275 pub thumb: Option<BoundedString>,276}277278#[derive(Encode, Decode, Eq, PartialEq, Clone, Debug, TypeInfo, MaxEncodedLen)]279#[cfg_attr(feature = "std", derive(Serialize))]280#[cfg_attr(281 feature = "std",282 serde(283 bound = r#"284 BoundedString: AsRef<[u8]>,285 BoundedParts: AsRef<[PartId]>286 "#287 )288)]289pub enum ResourceTypes<BoundedString, BoundedParts> {290 Basic(BasicResource<BoundedString>),291 Composable(ComposableResource<BoundedString, BoundedParts>),292 Slot(SlotResource<BoundedString>),293}294295296#[derive(Encode, Decode, Eq, PartialEq, Clone, Debug, TypeInfo, MaxEncodedLen)]297#[cfg_attr(feature = "std", derive(Serialize))]298#[cfg_attr(299 feature = "std",300 serde(301 bound = r#"302 BoundedResource: AsRef<[u8]>,303 BoundedString: AsRef<[u8]>,304 BoundedParts: AsRef<[PartId]>305 "#306 )307)]308pub struct ResourceInfo<BoundedResource, BoundedString, BoundedParts> {309 /// id is a 5-character string of reasonable uniqueness.310 /// The combination of base ID and resource id should be unique across the entire RMRK311 /// ecosystem which312 #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]313 pub id: BoundedResource,314315 /// Resource316 pub resource: ResourceTypes<BoundedString, BoundedParts>,317318 /// If resource is sent to non-rootowned NFT, pending will be false and need to be accepted319 pub pending: bool,320321 /// If resource removal request is sent by non-rootowned NFT, pending will be true and need to be accepted322 pub pending_removal: bool,323}324325#[cfg_attr(feature = "std", derive(PartialEq, Eq, Serialize))]326#[derive(Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]327#[cfg_attr(328 feature = "std",329 serde(330 bound = r#"331 AccountId: Serialize,332 BoundedString: AsRef<[u8]>333 "#334 )335)]336pub struct BaseInfo<AccountId, BoundedString> {337 /// Original creator of the Base338 pub issuer: AccountId,339340 /// Specifies how an NFT should be rendered, ie "svg"341 #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]342 pub base_type: BoundedString,343344 /// User provided symbol during Base creation345 #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]346 pub symbol: BoundedString,347}348349#[cfg_attr(feature = "std", derive(Serialize))]350#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, Eq, MaxEncodedLen)]351#[cfg_attr(352 feature = "std",353 serde(bound = "BoundedString: AsRef<[u8]>")354)]355pub struct FixedPart<BoundedString> {356 pub id: PartId,357 pub z: ZIndex,358359 #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]360 pub src: BoundedString,361}362363#[cfg_attr(feature = "std", derive(Serialize))]364#[derive(Encode, Decode, Debug, Derivative, TypeInfo, Clone, PartialEq, Eq, MaxEncodedLen)]365#[cfg_attr(366 feature = "std",367 serde(bound = "BoundedCollectionList: AsRef<[CollectionId]>")368)]369#[derivative(Default(bound=""))]370pub enum EquippableList<BoundedCollectionList> {371 All,372373 #[derivative(Default)]374 Empty,375376 Custom(377 #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]378 BoundedCollectionList379 ),380}381382#[cfg_attr(feature = "std", derive(Serialize))]383#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, Eq, MaxEncodedLen)]384#[cfg_attr(385 feature = "std",386 serde(387 bound = r#"388 BoundedString: AsRef<[u8]>,389 BoundedCollectionList: AsRef<[CollectionId]>390 "#391 )392)]393pub struct SlotPart<BoundedString, BoundedCollectionList> {394 pub id: PartId,395 pub equippable: EquippableList<BoundedCollectionList>,396397 #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]398 pub src: BoundedString,399400 pub z: ZIndex,401}402403#[cfg_attr(feature = "std", derive(Serialize))]404#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, Eq, MaxEncodedLen)]405#[cfg_attr(406 feature = "std",407 serde(408 bound = r#"409 BoundedString: AsRef<[u8]>,410 BoundedCollectionList: AsRef<[CollectionId]>411 "#412 )413)]414pub enum PartType<BoundedString, BoundedCollectionList> {415 FixedPart(FixedPart<BoundedString>),416 SlotPart(SlotPart<BoundedString, BoundedCollectionList>),417}418419impl<BoundedString, BoundedCollectionList> PartType<BoundedString, BoundedCollectionList> {420 pub fn id(&self) -> PartId {421 match self {422 Self::FixedPart(part) => part.id,423 Self::SlotPart(part) => part.id424 }425 }426427 pub fn src(&self) -> &BoundedString {428 match self {429 Self::FixedPart(part) => &part.src,430 Self::SlotPart(part) => &part.src431 }432 }433434 pub fn z_index(&self) -> ZIndex {435 match self {436 Self::FixedPart(part) => part.z,437 Self::SlotPart(part) => part.z438 }439 }440}441442#[cfg_attr(feature = "std", derive(Eq, Serialize))]443#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq)]444#[cfg_attr(445 feature = "std",446 serde(447 bound = r#"448 BoundedString: AsRef<[u8]>,449 PropertyList: AsRef<[ThemeProperty<BoundedString>]>,450 "#451 )452)]453pub struct Theme<BoundedString, PropertyList> {454 /// Name of the theme455 #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]456 pub name: BoundedString,457458 /// Theme properties459 #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]460 pub properties: PropertyList,461 /// Inheritability462 pub inherit: bool,463}464465#[cfg_attr(feature = "std", derive(Eq, Serialize))]466#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq)]467#[cfg_attr(468 feature = "std",469 serde(bound = "BoundedString: AsRef<[u8]>")470)]471pub struct ThemeProperty<BoundedString> {472 /// Key of the property473 #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]474 pub key: BoundedString,475476 /// Value of the property477 #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]478 pub value: BoundedString,479}runtime/common/src/runtime_apis.rsdiffbeforeafterboth--- a/runtime/common/src/runtime_apis.rs
+++ b/runtime/common/src/runtime_apis.rs
@@ -146,9 +146,7 @@
}
fn collection_by_id(collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {
- use frame_support::BoundedVec;
- use scale_info::prelude::string::String;
- use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, RmrkRebind, RmrkDecode}};
+ use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, RmrkDecode}};
let collection_id = CollectionId(collection_id);
let collection = match RmrkCore::get_typed_nft_collection(collection_id, CollectionType::Regular) {
@@ -156,20 +154,18 @@
Err(_) => return Ok(None),
};
- let nfts_count = (dispatch_unique_runtime!(collection_id.total_supply()) as Result<u32, DispatchError>)?;
- //<Runtime as up_rpc::UniqueApi>::total_supply(collection_id); // todo can't find UniqueApi with disabled default features
+ let nfts_count = dispatch_unique_runtime!(collection_id.total_supply())?;
Ok(Some(RmrkCollectionInfo {
issuer: collection.owner.clone(),
metadata: RmrkCore::get_collection_property(collection_id, RmrkProperty::Metadata)?.decode_or_default(),
max: collection.limits.token_limit,
- symbol: collection.token_prefix.rebind(), // change
+ symbol: collection.token_prefix.decode_or_default(),
nfts_count
}))
}
fn nft_by_id(collection_id: RmrkCollectionId, nft_by_id: RmrkNftId) -> Result<Option<RmrkInstanceInfo<AccountId>>, DispatchError> {
- use frame_support::BoundedVec;
use up_data_structs::mapping::TokenAddressMapping;
use pallet_proxy_rmrk_core::{RmrkProperty, misc::RmrkDecode};
@@ -177,7 +173,7 @@
let nft_id = TokenId(nft_by_id);
if !RmrkCore::nft_exists(collection_id, nft_id) { return Ok(None); }
- let owner = match (dispatch_unique_runtime!(collection_id.token_owner(nft_id)) as Result<Option<CrossAccountId>, DispatchError>)? {
+ let owner = match dispatch_unique_runtime!(collection_id.token_owner(nft_id))? {
Some(owner) => match <Runtime as pallet_common::Config>::CrossTokenAddressMapping::address_to_token(&owner) {
Some((col, tok)) => RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(col.0, tok.0),
None => RmrkAccountIdOrCollectionNftTuple::AccountId(owner.as_sub().clone())
@@ -197,16 +193,17 @@
}
fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {
+ use pallet_proxy_rmrk_core::misc::CollectionType;
+
let cross_account_id = CrossAccountId::from_sub(account_id);
let collection_id = CollectionId(collection_id);
- if !RmrkCore::collection_exists(collection_id) { return Ok(Vec::new()); }
+ if RmrkCore::ensure_collection_type(collection_id, CollectionType::Regular).is_err() { return Ok(Vec::new()); }
Ok(
- (dispatch_unique_runtime!(collection_id.account_tokens(cross_account_id)) as Result<Vec<TokenId>, DispatchError>)?
- //<Runtime as up_rpc::UniqueApi<Block, CrossAccountId, AccountId>>::account_tokens(collection_id, cross_account_id)?
+ dispatch_unique_runtime!(collection_id.account_tokens(cross_account_id))?
.into_iter()
.map(|token| token.0)
- .collect::<Vec<_>>()
+ .collect()
)
}
@@ -226,8 +223,7 @@
.map(|(child_id, _)| RmrkNftChild {
collection_id: collection_id.0, // todo make sure they're always from this collection // spoiler: they're not
nft_id: child_id.0,
- })
- .collect()
+ }).collect()
)
}
@@ -277,28 +273,70 @@
fn nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {
use frame_support::BoundedVec;
- use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType}};
+ use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, RmrkDecode}};
let collection_id = CollectionId(collection_id);
- if RmrkCore::ensure_collection_type(collection_id, CollectionType::Resource).is_err() { return Ok(Vec::new()); }
+ if !RmrkCore::collection_exists(collection_id) { return Ok(Vec::new()); } // todo make sure the collection type doesn't matter
let nft_id = TokenId(nft_id);
if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Resource).is_err() { return Ok(Vec::new()); }
- Ok(Vec::new(/*[RmrkResourceInfo {
+ let resource_collection_id: CollectionId = RmrkCore::get_nft_property(collection_id, nft_id, RmrkProperty::ResourceCollection)
+ .unwrap()
+ .decode_or_default();
+ if RmrkCore::ensure_collection_type(collection_id, CollectionType::Resource).is_err() { return Ok(Vec::new()); }
- }]*/))
+ let resources = pallet_nonfungible::TokenProperties::<Runtime>::iter_prefix((resource_collection_id,))
+ .filter_map(|(resource_id, properties)| Some(RmrkResourceInfo {
+ id: BoundedVec::default(), // todo ResourceId property
+ pending: RmrkCore::get_nft_property(resource_collection_id, resource_id, RmrkProperty::PendingResourceAccept).unwrap().decode_or_default(),
+ pending_removal: RmrkCore::get_nft_property(resource_collection_id, resource_id, RmrkProperty::PendingResourceRemoval).unwrap().decode_or_default(),
+ resource: RmrkCore::get_nft_property(resource_collection_id, resource_id, RmrkProperty::ResourceType).unwrap().decode_or_default(),/* {
+ RmrkResourceTypes::Basic(resource) => RmrkResourceTypes::Basic(),/*(RmrkBasicResource {
+ src: RmrkCore::get_nft_property_inner(properties, RmrkProperty::Src).unwrap().decode_or_default(),
+ metadata: RmrkCore::get_nft_property_inner(properties, RmrkProperty::Metadata).unwrap().decode_or_default(),
+ license: RmrkCore::get_nft_property_inner(properties, RmrkProperty::License).unwrap().decode_or_default(),
+ thumb: RmrkCore::get_nft_property_inner(properties, RmrkProperty::Thumb).unwrap().decode_or_default(),
+ },*///BasicResource<BoundedString>)
+ _ => todo!(), //RmrkResourceTypes::Composable(ComposableResource<BoundedString, BoundedParts>),
+ //RmrkResourceTypes::Slot(SlotResource<BoundedString>),
+ },*/
+ }))
+ .collect();
+
+ Ok(resources)
}
fn nft_resource_priorities(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkResourceId>, DispatchError> {
- todo!()
+ use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, RmrkDecode}};
+
+ let collection_id = CollectionId(collection_id);
+ if !RmrkCore::collection_exists(collection_id) { return Ok(Vec::new()); } // todo ensure the collection type doesn't matter
+
+ let nft_id = TokenId(nft_id);
+ if RmrkCore::ensure_nft_type(collection_id, nft_id, NftType::Resource).is_err() { return Ok(Vec::new()); }
+
+ /*let resource_collection_id: CollectionId = RmrkCore::get_nft_property(collection_id, nft_id, RmrkProperty::ResourceCollection)
+ .unwrap()
+ .decode_or_default();
+ if RmrkCore::ensure_collection_type(collection_id, CollectionType::Resource).is_err() { return Ok(Vec::new()); }
+
+ let resources = pallet_nonfungible::TokenProperties::<Runtime>::iter_prefix((resource_collection_id,))
+ .filter_map(|(resource_id, properties)| Some((
+ resource_id, // ResourceId property
+ RmrkCore::get_nft_property(resource_collection_id, resource_id, RmrkProperty::Priority).unwrap().decode_or_default(),
+ )))
+ .collect()
+ .sort_by_key(|(_, index)| *index)
+ .into_iter().map(|(resource_id, _)| resource_id)*/
+ let priorities = RmrkCore::get_nft_property(collection_id, nft_id, RmrkProperty::ResourcePriorities)?.decode_or_default();
+
+ Ok(priorities)
}
fn base(base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {
- use frame_support::BoundedVec;
- use scale_info::prelude::string::String;
use pallet_proxy_rmrk_core::{
- RmrkProperty, misc::{CollectionType, RmrkRebind, RmrkDecode},
+ RmrkProperty, misc::{CollectionType, RmrkDecode},
};
let collection_id = CollectionId(base_id);
@@ -310,18 +348,17 @@
Ok(Some(RmrkBaseInfo {
issuer: collection.owner.clone(),
base_type: RmrkCore::get_collection_property(collection_id, RmrkProperty::BaseType)?.decode_or_default(),
- symbol: collection.token_prefix.rebind(),
+ symbol: collection.token_prefix.decode_or_default(),
}))
}
fn base_parts(base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {
- use frame_support::BoundedVec;
use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, RmrkDecode}};
let collection_id = CollectionId(base_id);
if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() { return Ok(Vec::new()); }
- let parts = (dispatch_unique_runtime!(collection_id.collection_tokens()))?
+ let parts = dispatch_unique_runtime!(collection_id.collection_tokens())?
.into_iter()
.filter_map(|token_id| {
let nft_type = RmrkCore::get_nft_type(collection_id, token_id).ok()?;
@@ -347,7 +384,6 @@
}
fn theme_names(base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {
- use frame_support::BoundedVec;
use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, RmrkDecode}};
let collection_id = CollectionId(base_id);
@@ -355,7 +391,7 @@
return Ok(Vec::new());
}
- let theme_names = (dispatch_unique_runtime!(collection_id.collection_tokens()))?
+ let theme_names = dispatch_unique_runtime!(collection_id.collection_tokens())?
.iter()
.filter_map(|token_id| {
let nft_type = RmrkCore::get_nft_type(collection_id, *token_id).unwrap();
@@ -373,7 +409,6 @@
}
fn theme(base_id: RmrkBaseId, theme_name: RmrkThemeName, filter_keys: Option<Vec<RmrkPropertyKey>>) -> Result<Option<RmrkTheme>, DispatchError> {
- use frame_support::BoundedVec;
use pallet_proxy_rmrk_core::{
RmrkProperty,
misc::{CollectionType, NftType, RmrkDecode}
@@ -384,7 +419,7 @@
return Ok(None);
}
- let theme_info = (dispatch_unique_runtime!(collection_id.collection_tokens()))?
+ let theme_info = dispatch_unique_runtime!(collection_id.collection_tokens())?
.into_iter()
.find_map(|token_id| {
RmrkCore::ensure_nft_type(collection_id, token_id, NftType::Theme).ok()?;
tests/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) {