difftreelog
refactor drop rmrk compatibility layer
in: master
85 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -5543,8 +5543,6 @@
"pallet-nonfungible",
"pallet-randomness-collective-flip",
"pallet-refungible",
- "pallet-rmrk-core",
- "pallet-rmrk-equip",
"pallet-session",
"pallet-structure",
"pallet-sudo",
@@ -5561,7 +5559,6 @@
"parity-scale-codec",
"polkadot-parachain",
"precompile-utils-macro",
- "rmrk-rpc",
"scale-info",
"serde",
"smallvec",
@@ -6772,43 +6769,6 @@
"parity-scale-codec",
"scale-info",
"sp-core",
- "sp-runtime",
- "sp-std",
- "up-data-structs",
-]
-
-[[package]]
-name = "pallet-rmrk-core"
-version = "0.1.2"
-dependencies = [
- "frame-benchmarking",
- "frame-support",
- "frame-system",
- "pallet-common",
- "pallet-evm",
- "pallet-nonfungible",
- "pallet-structure",
- "parity-scale-codec",
- "rmrk-traits",
- "scale-info",
- "sp-runtime",
- "sp-std",
- "up-data-structs",
-]
-
-[[package]]
-name = "pallet-rmrk-equip"
-version = "0.1.2"
-dependencies = [
- "frame-benchmarking",
- "frame-support",
- "frame-system",
- "pallet-common",
- "pallet-evm",
- "pallet-nonfungible",
- "pallet-rmrk-core",
- "parity-scale-codec",
- "scale-info",
"sp-runtime",
"sp-std",
"up-data-structs",
@@ -9009,8 +8969,6 @@
"pallet-nonfungible",
"pallet-randomness-collective-flip",
"pallet-refungible",
- "pallet-rmrk-core",
- "pallet-rmrk-equip",
"pallet-session",
"pallet-structure",
"pallet-sudo",
@@ -9026,7 +8984,6 @@
"parity-scale-codec",
"polkadot-parachain",
"precompile-utils-macro",
- "rmrk-rpc",
"scale-info",
"serde",
"smallvec",
@@ -9415,26 +9372,6 @@
]
[[package]]
-name = "rmrk-rpc"
-version = "0.0.2"
-dependencies = [
- "parity-scale-codec",
- "rmrk-traits",
- "sp-api",
- "sp-runtime",
- "sp-std",
-]
-
-[[package]]
-name = "rmrk-traits"
-version = "0.1.0"
-dependencies = [
- "parity-scale-codec",
- "scale-info",
- "serde",
-]
-
-[[package]]
name = "rocksdb"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -13026,7 +12963,6 @@
"pallet-evm",
"parity-scale-codec",
"quartz-runtime",
- "rmrk-rpc",
"sc-client-api",
"sc-executor",
"sc-rpc-api",
@@ -13132,7 +13068,6 @@
"polkadot-primitives",
"polkadot-service",
"quartz-runtime",
- "rmrk-rpc",
"sc-basic-authorship",
"sc-chain-spec",
"sc-cli",
@@ -13186,7 +13121,6 @@
"fp-storage",
"jsonrpsee",
"pallet-transaction-payment-rpc",
- "rmrk-rpc",
"sc-client-api",
"sc-finality-grandpa",
"sc-network",
@@ -13265,8 +13199,6 @@
"pallet-nonfungible",
"pallet-randomness-collective-flip",
"pallet-refungible",
- "pallet-rmrk-core",
- "pallet-rmrk-equip",
"pallet-session",
"pallet-structure",
"pallet-sudo",
@@ -13282,7 +13214,6 @@
"parity-scale-codec",
"polkadot-parachain",
"precompile-utils-macro",
- "rmrk-rpc",
"scale-info",
"serde",
"smallvec",
@@ -13361,7 +13292,6 @@
"frame-support",
"pallet-evm",
"parity-scale-codec",
- "rmrk-traits",
"scale-info",
"serde",
"sp-core",
Cargo.tomldiffbeforeafterboth--- a/Cargo.toml
+++ b/Cargo.toml
@@ -43,9 +43,6 @@
pallet-inflation = { path = "pallets/inflation", default-features = false }
pallet-maintenance = { default-features = false, path = "pallets/maintenance" }
pallet-nonfungible = { default-features = false, path = "pallets/nonfungible" }
-pallet-proxy-rmrk-core = { default-features = false, path = "pallets/proxy-rmrk-core", package = "pallet-rmrk-core" }
-pallet-proxy-rmrk-equip = { default-features = false, path = "pallets/proxy-rmrk-equip", package = "pallet-rmrk-equip" }
-rmrk-traits = { default-features = false, path = "primitives/rmrk-traits" }
pallet-refungible = { default-features = false, path = "pallets/refungible" }
pallet-structure = { default-features = false, path = "pallets/structure" }
pallet-unique = { path = "pallets/unique", default-features = false }
@@ -53,7 +50,6 @@
pallet-test-utils = { default-features = false, path = "test-pallets/utils" }
pallet-app-promotion = { path = "pallets/app-promotion", default-features = false }
app-promotion-rpc = { path = "primitives/app_promotion_rpc", default-features = false }
-rmrk-rpc = { path = "primitives/rmrk-rpc", default-features = false }
# Unique: Runtimes
unique-runtime = { path = "runtime/unique" }
Makefilediffbeforeafterboth--- a/Makefile
+++ b/Makefile
@@ -121,14 +121,6 @@
bench-scheduler:
make _bench PALLET=unique-scheduler-v2 PALLET_DIR=scheduler-v2
-.PHONY: bench-rmrk-core
-bench-rmrk-core:
- make _bench PALLET=proxy-rmrk-core
-
-.PHONY: bench-rmrk-equip
-bench-rmrk-equip:
- make _bench PALLET=proxy-rmrk-equip
-
.PHONY: bench-foreign-assets
bench-foreign-assets:
make _bench PALLET=foreign-assets
@@ -146,7 +138,7 @@
make _bench PALLET=app-promotion PALLET_DIR=app-promotion
.PHONY: bench
-# Disabled: bench-scheduler, bench-collator-selection, bench-identity, bench-rmrk-core, bench-rmrk-equip
+# Disabled: bench-scheduler, bench-collator-selection, bench-identity
bench: bench-common bench-evm-migration bench-unique bench-structure bench-fungible bench-refungible bench-nonfungible bench-configuration bench-foreign-assets
.PHONY: check
client/rpc/Cargo.tomldiffbeforeafterboth--- a/client/rpc/Cargo.toml
+++ b/client/rpc/Cargo.toml
@@ -14,7 +14,6 @@
codec = { workspace = true, package = "parity-scale-codec" }
app-promotion-rpc = { workspace = true }
-rmrk-rpc = { workspace = true }
up-common = { workspace = true }
up-data-structs = { workspace = true }
up-pov-estimate-rpc = { workspace = true, optional = true }
client/rpc/src/lib.rsdiffbeforeafterboth--- a/client/rpc/src/lib.rs
+++ b/client/rpc/src/lib.rs
@@ -17,7 +17,7 @@
// Original License
use std::sync::Arc;
-use codec::{Decode, Encode};
+use codec::Decode;
use jsonrpsee::{
core::{RpcResult as Result},
proc_macros::rpc,
@@ -32,15 +32,8 @@
use sp_blockchain::HeaderBackend;
use up_rpc::UniqueApi as UniqueRuntimeApi;
use app_promotion_rpc::AppPromotionApi as AppPromotionRuntimeApi;
-
-// RMRK
-use rmrk_rpc::RmrkApi as RmrkRuntimeApi;
-use up_data_structs::{
- RmrkCollectionId, RmrkNftId, RmrkBaseId, RmrkNftChild, RmrkThemeName, RmrkResourceId,
-};
pub use app_promotion_unique_rpc::AppPromotionApiServer;
-pub use rmrk_unique_rpc::RmrkApiServer;
#[cfg(feature = "pov-estimate")]
pub mod pov_estimate;
@@ -300,129 +293,7 @@
) -> Result<Vec<(BlockNumber, String)>>;
}
}
-
-mod rmrk_unique_rpc {
- use super::*;
-
- #[rpc(server)]
- #[async_trait]
- pub trait RmrkApi<
- BlockHash,
- AccountId,
- CollectionInfo,
- NftInfo,
- ResourceInfo,
- PropertyInfo,
- BaseInfo,
- PartType,
- Theme,
- >
- {
- /// Get the latest created collection ID.
- #[method(name = "rmrk_lastCollectionIdx")]
- fn last_collection_idx(&self, at: Option<BlockHash>) -> Result<RmrkCollectionId>;
-
- /// Get collection info by ID.
- #[method(name = "rmrk_collectionById")]
- fn collection_by_id(
- &self,
- id: RmrkCollectionId,
- at: Option<BlockHash>,
- ) -> Result<Option<CollectionInfo>>;
-
- /// Get NFT info by collection and NFT IDs.
- #[method(name = "rmrk_nftById")]
- fn nft_by_id(
- &self,
- collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
- at: Option<BlockHash>,
- ) -> Result<Option<NftInfo>>;
-
- /// Get tokens owned by an account in a collection.
- #[method(name = "rmrk_accountTokens")]
- fn account_tokens(
- &self,
- account_id: AccountId,
- collection_id: RmrkCollectionId,
- at: Option<BlockHash>,
- ) -> Result<Vec<RmrkNftId>>;
-
- /// Get tokens nested in an NFT - its direct children (not the children's children).
- #[method(name = "rmrk_nftChildren")]
- fn nft_children(
- &self,
- collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
- at: Option<BlockHash>,
- ) -> Result<Vec<RmrkNftChild>>;
-
- /// Get collection properties, created by the user - not the proxy-specific properties.
- #[method(name = "rmrk_collectionProperties")]
- fn collection_properties(
- &self,
- collection_id: RmrkCollectionId,
- filter_keys: Option<Vec<String>>,
- at: Option<BlockHash>,
- ) -> Result<Vec<PropertyInfo>>;
-
- /// Get NFT properties, created by the user - not the proxy-specific properties.
- #[method(name = "rmrk_nftProperties")]
- fn nft_properties(
- &self,
- collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
- filter_keys: Option<Vec<String>>,
- at: Option<BlockHash>,
- ) -> Result<Vec<PropertyInfo>>;
-
- /// Get data of resources of an NFT.
- #[method(name = "rmrk_nftResources")]
- fn nft_resources(
- &self,
- collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
- at: Option<BlockHash>,
- ) -> Result<Vec<ResourceInfo>>;
- /// Get the priority of a resource in an NFT.
- #[method(name = "rmrk_nftResourcePriority")]
- fn nft_resource_priority(
- &self,
- collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
- resource_id: RmrkResourceId,
- at: Option<BlockHash>,
- ) -> Result<Option<u32>>;
-
- /// Get base info by its ID.
- #[method(name = "rmrk_base")]
- fn base(&self, base_id: RmrkBaseId, at: Option<BlockHash>) -> Result<Option<BaseInfo>>;
-
- /// Get all parts of a base.
- #[method(name = "rmrk_baseParts")]
- fn base_parts(&self, base_id: RmrkBaseId, at: Option<BlockHash>) -> Result<Vec<PartType>>;
-
- /// Get the theme names belonging to a base.
- #[method(name = "rmrk_themeNames")]
- fn theme_names(
- &self,
- base_id: RmrkBaseId,
- at: Option<BlockHash>,
- ) -> Result<Vec<RmrkThemeName>>;
-
- /// Get theme info, including properties, optionally limited to the provided keys.
- #[method(name = "rmrk_themes")]
- fn theme(
- &self,
- base_id: RmrkBaseId,
- theme_name: String,
- filter_keys: Option<Vec<String>>,
- at: Option<BlockHash>,
- ) -> Result<Option<Theme>>;
- }
-}
-
#[macro_export]
macro_rules! define_struct_for_server_api {
($name:ident { $($arg:ident: $arg_ty:ty),+ $(,)? }) => {
@@ -454,12 +325,6 @@
}
}
-define_struct_for_server_api! {
- Rmrk {
- client: Arc<Client>
- }
-}
-
macro_rules! pass_method {
(
$method_name:ident(
@@ -508,12 +373,6 @@
macro_rules! app_promotion_api {
() => {
dyn AppPromotionRuntimeApi<Block, BlockNumber, CrossAccountId, AccountId>
- };
-}
-
-macro_rules! rmrk_api {
- () => {
- dyn RmrkRuntimeApi<Block, AccountId, CollectionInfo, NftInfo, ResourceInfo, PropertyInfo, BaseInfo, PartType, Theme>
};
}
@@ -627,94 +486,6 @@
.into_iter()
.map(|(b, a)| (b, a.to_string()))
.collect::<Vec<_>>(), app_promotion_api);
-}
-
-#[allow(deprecated)]
-impl<
- C,
- Block,
- AccountId,
- CollectionInfo,
- NftInfo,
- ResourceInfo,
- PropertyInfo,
- BaseInfo,
- PartType,
- Theme,
- >
- rmrk_unique_rpc::RmrkApiServer<
- <Block as BlockT>::Hash,
- AccountId,
- CollectionInfo,
- NftInfo,
- ResourceInfo,
- PropertyInfo,
- BaseInfo,
- PartType,
- Theme,
- > for Rmrk<C, Block>
-where
- C: Send + Sync + 'static + ProvideRuntimeApi<Block> + HeaderBackend<Block>,
- C::Api: RmrkRuntimeApi<
- Block,
- AccountId,
- CollectionInfo,
- NftInfo,
- ResourceInfo,
- PropertyInfo,
- BaseInfo,
- PartType,
- Theme,
- >,
- AccountId: Decode + Encode,
- CollectionInfo: Decode,
- NftInfo: Decode,
- ResourceInfo: Decode,
- PropertyInfo: Decode,
- BaseInfo: Decode,
- PartType: Decode,
- Theme: Decode,
- Block: BlockT,
-{
- pass_method!(last_collection_idx() -> RmrkCollectionId, rmrk_api);
- pass_method!(collection_by_id(id: RmrkCollectionId) -> Option<CollectionInfo>, rmrk_api);
- pass_method!(nft_by_id(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Option<NftInfo>, rmrk_api);
- pass_method!(account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Vec<RmrkNftId>, rmrk_api);
- pass_method!(nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Vec<RmrkNftChild>, rmrk_api);
- pass_method!(
- collection_properties(
- collection_id: RmrkCollectionId,
-
- #[map(|keys| string_keys_to_bytes_keys(keys))]
- filter_keys: Option<Vec<String>>
- ) -> Vec<PropertyInfo>,
- rmrk_api
- );
- pass_method!(
- nft_properties(
- collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
-
- #[map(|keys| string_keys_to_bytes_keys(keys))]
- filter_keys: Option<Vec<String>>
- ) -> Vec<PropertyInfo>,
- rmrk_api
- );
- pass_method!(nft_resources(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Vec<ResourceInfo>, rmrk_api);
- pass_method!(nft_resource_priority(collection_id: RmrkCollectionId, nft_id: RmrkNftId, resource_id: RmrkResourceId) -> Option<u32>, rmrk_api);
- pass_method!(base(base_id: RmrkBaseId) -> Option<BaseInfo>, rmrk_api);
- pass_method!(base_parts(base_id: RmrkBaseId) -> Vec<PartType>, rmrk_api);
- pass_method!(theme_names(base_id: RmrkBaseId) -> Vec<RmrkThemeName>, rmrk_api);
- pass_method!(
- theme(
- base_id: RmrkBaseId,
-
- #[map(|n| n.into_bytes())]
- theme_name: String,
-
- #[map(|keys| string_keys_to_bytes_keys(keys))]
- filter_keys: Option<Vec<String>>
- ) -> Option<Theme>, rmrk_api);
}
fn string_keys_to_bytes_keys(keys: Option<Vec<String>>) -> Option<Vec<Vec<u8>>> {
node/cli/Cargo.tomldiffbeforeafterboth--- a/node/cli/Cargo.toml
+++ b/node/cli/Cargo.toml
@@ -89,7 +89,6 @@
fp-rpc = { workspace = true }
app-promotion-rpc = { workspace = true }
-rmrk-rpc = { workspace = true }
uc-rpc = { workspace = true }
unique-rpc = { workspace = true }
up-pov-estimate-rpc = { workspace = true }
node/cli/src/service.rsdiffbeforeafterboth--- a/node/cli/src/service.rs
+++ b/node/cli/src/service.rs
@@ -71,12 +71,6 @@
#[cfg(feature = "pov-estimate")]
use crate::chain_spec::RuntimeIdentification;
-// RMRK
-use up_data_structs::{
- RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo, RmrkBaseInfo,
- RmrkPartType, RmrkTheme,
-};
-
/// Unique native executor instance.
#[cfg(feature = "unique-runtime")]
pub struct UniqueRuntimeExecutor;
@@ -403,17 +397,7 @@
+ sp_api::ApiExt<Block, StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>
+ up_rpc::UniqueApi<Block, Runtime::CrossAccountId, AccountId>
+ app_promotion_rpc::AppPromotionApi<Block, BlockNumber, Runtime::CrossAccountId, AccountId>
- + rmrk_rpc::RmrkApi<
- Block,
- AccountId,
- RmrkCollectionInfo<AccountId>,
- RmrkInstanceInfo<AccountId>,
- RmrkResourceInfo,
- RmrkPropertyInfo,
- RmrkBaseInfo<AccountId>,
- RmrkPartType,
- RmrkTheme,
- > + up_pov_estimate_rpc::PovEstimateApi<Block>
+ + up_pov_estimate_rpc::PovEstimateApi<Block>
+ substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
+ sp_api::Metadata<Block>
+ sp_offchain::OffchainWorkerApi<Block>
@@ -732,17 +716,7 @@
+ sp_api::ApiExt<Block, StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>
+ up_rpc::UniqueApi<Block, Runtime::CrossAccountId, AccountId>
+ app_promotion_rpc::AppPromotionApi<Block, BlockNumber, Runtime::CrossAccountId, AccountId>
- + rmrk_rpc::RmrkApi<
- Block,
- AccountId,
- RmrkCollectionInfo<AccountId>,
- RmrkInstanceInfo<AccountId>,
- RmrkResourceInfo,
- RmrkPropertyInfo,
- RmrkBaseInfo<AccountId>,
- RmrkPartType,
- RmrkTheme,
- > + up_pov_estimate_rpc::PovEstimateApi<Block>
+ + up_pov_estimate_rpc::PovEstimateApi<Block>
+ substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
+ sp_api::Metadata<Block>
+ sp_offchain::OffchainWorkerApi<Block>
@@ -882,17 +856,7 @@
+ sp_api::ApiExt<Block, StateBackend = sc_client_api::StateBackendFor<FullBackend, Block>>
+ up_rpc::UniqueApi<Block, Runtime::CrossAccountId, AccountId>
+ app_promotion_rpc::AppPromotionApi<Block, BlockNumber, Runtime::CrossAccountId, AccountId>
- + rmrk_rpc::RmrkApi<
- Block,
- AccountId,
- RmrkCollectionInfo<AccountId>,
- RmrkInstanceInfo<AccountId>,
- RmrkResourceInfo,
- RmrkPropertyInfo,
- RmrkBaseInfo<AccountId>,
- RmrkPartType,
- RmrkTheme,
- > + up_pov_estimate_rpc::PovEstimateApi<Block>
+ + up_pov_estimate_rpc::PovEstimateApi<Block>
+ substrate_frame_rpc_system::AccountNonceApi<Block, AccountId, Index>
+ sp_api::Metadata<Block>
+ sp_offchain::OffchainWorkerApi<Block>
node/rpc/Cargo.tomldiffbeforeafterboth--- a/node/rpc/Cargo.toml
+++ b/node/rpc/Cargo.toml
@@ -33,7 +33,6 @@
fp-storage = { workspace = true }
app-promotion-rpc = { workspace = true }
-rmrk-rpc = { workspace = true }
serde = { workspace = true }
uc-rpc = { workspace = true }
up-common = { workspace = true }
node/rpc/src/lib.rsdiffbeforeafterboth--- a/node/rpc/src/lib.rs
+++ b/node/rpc/src/lib.rs
@@ -42,12 +42,6 @@
use up_common::types::opaque::*;
-// RMRK
-use up_data_structs::{
- RmrkCollectionInfo, RmrkInstanceInfo, RmrkResourceInfo, RmrkPropertyInfo, RmrkBaseInfo,
- RmrkPartType, RmrkTheme,
-};
-
#[cfg(feature = "pov-estimate")]
type FullBackend = sc_service::TFullBackend<Block>;
@@ -164,17 +158,6 @@
<R as RuntimeInstance>::CrossAccountId,
AccountId,
>,
- C::Api: rmrk_rpc::RmrkApi<
- Block,
- AccountId,
- RmrkCollectionInfo<AccountId>,
- RmrkInstanceInfo<AccountId>,
- RmrkResourceInfo,
- RmrkPropertyInfo,
- RmrkBaseInfo<AccountId>,
- RmrkPartType,
- RmrkTheme,
- >,
C::Api: up_pov_estimate_rpc::PovEstimateApi<Block>,
B: sc_client_api::Backend<Block> + Send + Sync + 'static,
B::State: sc_client_api::backend::StateBackend<sp_runtime::traits::HashFor<Block>>,
@@ -193,9 +176,6 @@
#[cfg(not(feature = "unique-runtime"))]
use uc_rpc::{AppPromotionApiServer, AppPromotion};
- #[cfg(not(feature = "unique-runtime"))]
- use uc_rpc::{RmrkApiServer, Rmrk};
-
#[cfg(feature = "pov-estimate")]
use uc_rpc::pov_estimate::{PovEstimateApiServer, PovEstimate};
@@ -267,9 +247,6 @@
#[cfg(not(feature = "unique-runtime"))]
io.merge(AppPromotion::new(client.clone()).into_rpc())?;
-
- #[cfg(not(feature = "unique-runtime"))]
- io.merge(Rmrk::new(client.clone()).into_rpc())?;
#[cfg(feature = "pov-estimate")]
io.merge(
pallets/common/src/erc.rsdiffbeforeafterboth--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -33,7 +33,7 @@
};
use crate::{
- Pallet, CollectionHandle, Config, CollectionProperties, SelfWeightOf, eth, weights::WeightInfo,
+ Pallet, CollectionHandle, Config, CollectionProperties, eth, SelfWeightOf, weights::WeightInfo,
};
frontier_contract! {
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -109,15 +109,6 @@
TokenData,
TrySetProperty,
PropertyScope,
- // RMRK
- RmrkCollectionInfo,
- RmrkInstanceInfo,
- RmrkResourceInfo,
- RmrkPropertyInfo,
- RmrkBaseInfo,
- RmrkPartType,
- RmrkBoundedTheme,
- RmrkNftChild,
CollectionPermissions,
};
use up_pov_estimate_rpc::PovInfo;
@@ -898,15 +889,6 @@
PhantomType<(
TokenData<T::CrossAccountId>,
RpcCollection<T::AccountId>,
- // RMRK
- RmrkCollectionInfo<T::AccountId>,
- RmrkInstanceInfo<T::AccountId>,
- RmrkResourceInfo,
- RmrkPropertyInfo,
- RmrkBaseInfo<T::AccountId>,
- RmrkPartType,
- RmrkBoundedTheme,
- RmrkNftChild,
// PoV Estimate Info
PovInfo,
)>,
pallets/fungible/src/erc.rsdiffbeforeafterboth--- a/pallets/fungible/src/erc.rs
+++ b/pallets/fungible/src/erc.rs
@@ -38,8 +38,8 @@
use sp_core::{U256, Get};
use crate::{
- Allowance, Balance, Config, FungibleHandle, Pallet, SelfWeightOf, TotalSupply,
- weights::WeightInfo,
+ Allowance, Balance, Config, FungibleHandle, Pallet, TotalSupply,
+ SelfWeightOf, weights::WeightInfo,
};
frontier_contract! {
pallets/nonfungible/src/erc.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -47,7 +47,7 @@
use crate::{
AccountBalance, Config, CreateItemData, NonfungibleHandle, Pallet, TokenData, TokensMinted,
- SelfWeightOf, weights::WeightInfo, TokenProperties,
+ TokenProperties, SelfWeightOf, weights::WeightInfo,
};
frontier_contract! {
pallets/nonfungible/src/lib.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/lib.rs
+++ b/pallets/nonfungible/src/lib.rs
@@ -214,7 +214,7 @@
/// usual [`TokenProperties`] due to an unlimited number
/// and separately stored and written-to key-value pairs.
///
- /// Currently used to store RMRK data.
+ /// Currently unused.
#[pallet::storage]
#[pallet::getter(fn token_aux_property)]
pub type TokenAuxProperties<T: Config> = StorageNMap<
pallets/proxy-rmrk-core/CHANGELOG.mddiffbeforeafterboth--- a/pallets/proxy-rmrk-core/CHANGELOG.md
+++ /dev/null
@@ -1,17 +0,0 @@
-<!-- bureaucrate goes here -->
-## [v0.1.2] 2022-08-16
-
-### Other changes
-
-- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a
-
-- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8
-
-- refactor: Remove `#[transactional]` from extrinsics 7fd36cea2f6e00c02c67ccc1de9649ae404efd31
-
-Every extrinsic now runs in transaction implicitly, and
-`#[transactional]` on pallet dispatchable is now meaningless
-
-Upstream-Change: https://github.com/paritytech/substrate/issues/10806
-
-- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b
\ No newline at end of file
pallets/proxy-rmrk-core/Cargo.tomldiffbeforeafterboth--- a/pallets/proxy-rmrk-core/Cargo.toml
+++ /dev/null
@@ -1,41 +0,0 @@
-[package]
-edition = "2021"
-license = "GPLv3"
-name = "pallet-rmrk-core"
-version = "0.1.2"
-
-[dependencies]
-# Note: `package = "parity-scale-codec"` must be supplied since the `Encode` macro searches for it.
-codec = { workspace = true, package = "parity-scale-codec" }
-
-scale-info = { workspace = true }
-
-frame-benchmarking = { workspace = true, optional = true }
-frame-support = { workspace = true }
-frame-system = { workspace = true }
-pallet-common = { workspace = true }
-pallet-evm = { workspace = true }
-pallet-nonfungible = { workspace = true }
-pallet-structure = { workspace = true }
-rmrk-traits = { workspace = true }
-sp-runtime = { workspace = true }
-sp-std = { workspace = true }
-up-data-structs = { workspace = true }
-
-[features]
-default = ["std"]
-runtime-benchmarks = ['frame-benchmarking', 'frame-support/runtime-benchmarks', 'frame-system/runtime-benchmarks']
-std = [
- "frame-support/std",
- "frame-system/std",
- "pallet-common/std",
- "pallet-evm/std",
- "pallet-nonfungible/std",
- "pallet-structure/std",
- "rmrk-traits/std",
- "sp-runtime/std",
- "sp-std/std",
- "up-data-structs/std",
- 'frame-benchmarking/std',
-]
-try-runtime = ["frame-support/try-runtime"]
pallets/proxy-rmrk-core/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-core/src/benchmarking.rs
+++ /dev/null
@@ -1,544 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-use sp_std::vec;
-
-use frame_benchmarking::{benchmarks, account};
-use frame_system::RawOrigin;
-use frame_support::{
- traits::{Currency, Get},
- BoundedVec,
-};
-use sp_runtime::Permill;
-
-use up_data_structs::*;
-
-use super::*;
-
-const SEED: u32 = 1;
-
-fn create_data<S: Get<u32>>() -> BoundedVec<u8, S> {
- vec![b'A'; S::get() as usize].try_into().expect("size == S")
-}
-
-fn create_u32_array<S: Get<u32>>() -> BoundedVec<u32, S> {
- vec![0; S::get() as usize].try_into().expect("size == S")
-}
-
-fn create_basic_resource() -> RmrkBasicResource {
- RmrkBasicResource {
- src: Some(create_data()),
- metadata: Some(create_data()),
- license: Some(create_data()),
- thumb: Some(create_data()),
- }
-}
-
-fn create_composable_resource() -> RmrkComposableResource {
- RmrkComposableResource {
- parts: create_u32_array(),
- base: 100,
- src: Some(create_data()),
- metadata: Some(create_data()),
- license: Some(create_data()),
- thumb: Some(create_data()),
- }
-}
-
-fn create_slot_resource() -> RmrkSlotResource {
- RmrkSlotResource {
- base: 100,
- slot: 200,
- src: Some(create_data()),
- metadata: Some(create_data()),
- license: Some(create_data()),
- thumb: Some(create_data()),
- }
-}
-
-fn create_max_resource_types_array<S: Get<u32>>(num: usize) -> BoundedVec<RmrkResourceTypes, S> {
- vec![RmrkResourceTypes::Composable(create_composable_resource()); num]
- .try_into()
- .expect("num <= S")
-}
-
-fn create_max_collection<T: Config>(owner: &T::AccountId) -> DispatchResult {
- <T as pallet_common::Config>::Currency::deposit_creating(
- owner,
- T::CollectionCreationPrice::get(),
- );
-
- let metadata = create_data();
- let max = None;
- let symbol = create_data();
-
- <Pallet<T>>::create_collection(
- RawOrigin::Signed(owner.clone()).into(),
- metadata,
- max,
- symbol,
- )
-}
-
-fn create_nft<T: Config>(owner: &T::AccountId, collection_id: RmrkCollectionId) -> DispatchResult {
- let royalty_recipient = Some(owner.clone());
- let royalty_amount = Some(Permill::from_percent(25));
- let metadata = create_data();
- let transferable = true;
-
- <Pallet<T>>::mint_nft(
- RawOrigin::Signed(owner.clone()).into(),
- None,
- collection_id,
- royalty_recipient,
- royalty_amount,
- metadata,
- transferable,
- None,
- )
-}
-
-struct NftBuilder {
- collection_id: RmrkCollectionId,
- current_nft_id: RmrkNftId,
-}
-
-impl NftBuilder {
- fn new(collection_id: RmrkCollectionId) -> Self {
- Self {
- collection_id,
- current_nft_id: 0,
- }
- }
-
- fn build<T: Config>(&mut self, owner: &T::AccountId) -> Result<RmrkNftId, DispatchError> {
- create_nft::<T>(owner, self.collection_id)?;
- self.current_nft_id += 1;
-
- Ok(self.current_nft_id)
- }
-
- fn build_tower<T: Config>(
- &mut self,
- owner: &T::AccountId,
- height: u32,
- ) -> Result<(RmrkNftId, RmrkNftId), DispatchError> {
- self.build::<T>(owner)?;
-
- let root_nft_id = self.current_nft_id;
- let mut prev_nft_id = root_nft_id;
-
- for _ in 0..height {
- self.build::<T>(owner)?;
-
- let new_owner =
- <RmrkAccountIdOrCollectionNftTuple<T::AccountId>>::CollectionAndNftTuple(
- self.collection_id,
- prev_nft_id,
- );
-
- <Pallet<T>>::send(
- RawOrigin::Signed(owner.clone()).into(),
- self.collection_id,
- self.current_nft_id,
- new_owner,
- )?;
-
- prev_nft_id = self.current_nft_id;
- }
-
- let deepest_nft_id = self.current_nft_id;
-
- Ok((root_nft_id, deepest_nft_id))
- }
-
- fn build_wide_tree<T: Config>(
- &mut self,
- owner: &T::AccountId,
- width: u32,
- ) -> Result<RmrkNftId, DispatchError> {
- self.build::<T>(owner)?;
-
- let root_nft_id = self.current_nft_id;
-
- let root_owner = <RmrkAccountIdOrCollectionNftTuple<T::AccountId>>::CollectionAndNftTuple(
- self.collection_id,
- root_nft_id,
- );
-
- for _ in 0..width {
- self.build::<T>(owner)?;
-
- <Pallet<T>>::send(
- RawOrigin::Signed(owner.clone()).into(),
- self.collection_id,
- self.current_nft_id,
- root_owner.clone(),
- )?;
- }
-
- Ok(root_nft_id)
- }
-}
-
-benchmarks! {
- create_collection {
- let caller = account("caller", 0, SEED);
- <T as pallet_common::Config>::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get());
- let metadata = create_data();
- let max = None;
- let symbol = create_data();
- }: _(RawOrigin::Signed(caller), metadata, max, symbol)
-
- destroy_collection {
- let caller = account("caller", 0, SEED);
-
- create_max_collection::<T>(&caller)?;
- let collection_id = 0;
- }: _(RawOrigin::Signed(caller), collection_id)
-
- change_collection_issuer {
- let caller: T::AccountId = account("caller", 0, SEED);
-
- create_max_collection::<T>(&caller)?;
- let collection_id = 0;
-
- let new_owner: T::AccountId = account("new_owner", 0, SEED);
-
- let new_owner_source = T::Lookup::unlookup(new_owner);
- }: _(RawOrigin::Signed(caller), collection_id, new_owner_source)
-
- lock_collection {
- let caller: T::AccountId = account("caller", 0, SEED);
-
- create_max_collection::<T>(&caller)?;
- let collection_id = 0;
- }: _(RawOrigin::Signed(caller), collection_id)
-
- mint_nft {
- let b in 0..100;
-
- let caller: T::AccountId = account("caller", 0, SEED);
-
- create_max_collection::<T>(&caller)?;
- let collection_id = 0;
- let owner = caller.clone();
-
- let royalty_recipient = Some(caller.clone());
- let royalty_amount = Some(Permill::from_percent(25));
- let metadata = create_data();
- let transferable = true;
- }: _(
- RawOrigin::Signed(caller),
- None,
- collection_id,
- royalty_recipient,
- royalty_amount,
- metadata,
- transferable,
- Some(create_max_resource_types_array(b as usize))
- )
-
- burn_nft {
- let b in 0..200;
-
- let caller: T::AccountId = account("caller", 0, SEED);
- create_max_collection::<T>(&caller)?;
- let collection_id = 0;
-
- let mut nft_builder = NftBuilder::new(collection_id);
- let root_nft_id = nft_builder.build_wide_tree::<T>(&caller, b)?;
- let max_burns = b + 1;
- }: _(
- RawOrigin::Signed(caller),
- collection_id,
- root_nft_id,
- max_burns
- )
-
- send {
- let caller: T::AccountId = account("caller", 0, SEED);
- create_max_collection::<T>(&caller)?;
- let collection_id = 0;
-
- let mut nft_builder = NftBuilder::new(collection_id);
- let src_nft_id = nft_builder.build::<T>(&caller)?;
- let (_, target_nft_id) = nft_builder.build_tower::<T>(&caller, NESTING_BUDGET - 2)?;
- }: _(
- RawOrigin::Signed(caller),
- collection_id,
- src_nft_id,
- <RmrkAccountIdOrCollectionNftTuple<T::AccountId>>::CollectionAndNftTuple(collection_id, target_nft_id)
- )
-
- accept_nft {
- let caller: T::AccountId = account("caller", 0, SEED);
- let sender: T::AccountId = account("sender", 0, SEED);
-
- create_max_collection::<T>(&sender)?;
- let src_collection_id = 0;
-
- create_max_collection::<T>(&caller)?;
- let target_collection_id = 1;
-
- let mut src_nft_builder = NftBuilder::new(src_collection_id);
- let src_nft_id = src_nft_builder.build::<T>(&sender)?;
-
- let mut target_nft_builder = NftBuilder::new(target_collection_id);
- let fake_target_nft_id = target_nft_builder.build::<T>(&caller)?;
- let (_, target_nft_id) = target_nft_builder.build_tower::<T>(&caller, NESTING_BUDGET - 1)?;
-
- let new_owner = <RmrkAccountIdOrCollectionNftTuple<T::AccountId>>::CollectionAndNftTuple(
- target_collection_id,
- fake_target_nft_id
- );
-
- let actual_new_owner = <RmrkAccountIdOrCollectionNftTuple<T::AccountId>>::CollectionAndNftTuple(
- target_collection_id,
- target_nft_id
- );
-
- <Pallet<T>>::send(
- RawOrigin::Signed(sender.clone()).into(),
- src_collection_id,
- src_nft_id,
- new_owner,
- )?;
- }: _(
- RawOrigin::Signed(caller),
- src_collection_id,
- src_nft_id,
- actual_new_owner
- )
-
- reject_nft {
- let caller: T::AccountId = account("caller", 0, SEED);
- let sender: T::AccountId = account("sender", 0, SEED);
-
- create_max_collection::<T>(&sender)?;
- let src_collection_id = 0;
-
- create_max_collection::<T>(&caller)?;
- let target_collection_id = 1;
-
- let mut src_nft_builder = NftBuilder::new(src_collection_id);
- let (src_root_nft_id, _) = src_nft_builder.build_tower::<T>(&sender, NESTING_BUDGET - 1)?;
-
- let mut target_nft_builder = NftBuilder::new(target_collection_id);
- let target_nft_id = target_nft_builder.build::<T>(&caller)?;
-
- let new_owner = <RmrkAccountIdOrCollectionNftTuple<T::AccountId>>::CollectionAndNftTuple(
- target_collection_id,
- target_nft_id
- );
-
- <Pallet<T>>::send(
- RawOrigin::Signed(sender.clone()).into(),
- src_collection_id,
- src_root_nft_id,
- new_owner,
- )?;
- }: _(
- RawOrigin::Signed(caller),
- src_collection_id,
- src_root_nft_id
- )
-
- set_property {
- let caller: T::AccountId = account("caller", 0, SEED);
- create_max_collection::<T>(&caller)?;
- let collection_id = 0;
-
- let mut nft_builder = NftBuilder::new(collection_id);
- let (_, nft_id) = nft_builder.build_tower::<T>(&caller, NESTING_BUDGET - 1)?;
-
- let key = create_data();
- let value = create_data();
- }: _(
- RawOrigin::Signed(caller),
- collection_id,
- Some(nft_id),
- key,
- value
- )
-
- set_priority {
- let caller: T::AccountId = account("caller", 0, SEED);
- create_max_collection::<T>(&caller)?;
- let collection_id = 0;
-
- let mut nft_builder = NftBuilder::new(collection_id);
- let (_, nft_id) = nft_builder.build_tower::<T>(&caller, NESTING_BUDGET - 1)?;
- let priorities = create_u32_array();
- }: _(
- RawOrigin::Signed(caller),
- collection_id,
- nft_id,
- priorities
- )
-
- add_basic_resource {
- let caller: T::AccountId = account("caller", 0, SEED);
-
- create_max_collection::<T>(&caller)?;
- let collection_id = 0;
-
- let mut nft_builder = NftBuilder::new(collection_id);
- let (_, nft_id) = nft_builder.build_tower::<T>(&caller, NESTING_BUDGET - 1)?;
- let resource = create_basic_resource();
- }: _(
- RawOrigin::Signed(caller),
- collection_id,
- nft_id,
- resource
- )
-
- add_composable_resource {
- let caller: T::AccountId = account("caller", 0, SEED);
-
- create_max_collection::<T>(&caller)?;
- let collection_id = 0;
-
- let mut nft_builder = NftBuilder::new(collection_id);
- let (_, nft_id) = nft_builder.build_tower::<T>(&caller, NESTING_BUDGET - 1)?;
- let resource = create_composable_resource();
- }: _(
- RawOrigin::Signed(caller),
- collection_id,
- nft_id,
- resource
- )
-
- add_slot_resource {
- let caller: T::AccountId = account("caller", 0, SEED);
-
- create_max_collection::<T>(&caller)?;
- let collection_id = 0;
-
- let mut nft_builder = NftBuilder::new(collection_id);
- let (_, nft_id) = nft_builder.build_tower::<T>(&caller, NESTING_BUDGET - 1)?;
- let resource = create_slot_resource();
- }: _(
- RawOrigin::Signed(caller),
- collection_id,
- nft_id,
- resource
- )
-
- remove_resource {
- let caller: T::AccountId = account("caller", 0, SEED);
-
- create_max_collection::<T>(&caller)?;
- let collection_id = 0;
-
- let mut nft_builder = NftBuilder::new(collection_id);
- let (_, nft_id) = nft_builder.build_tower::<T>(&caller, NESTING_BUDGET - 1)?;
- let resource = create_basic_resource();
-
- <Pallet<T>>::add_basic_resource(
- RawOrigin::Signed(caller.clone()).into(),
- collection_id,
- nft_id,
- resource
- )?;
-
- let resource_id = 0;
- }: _(
- RawOrigin::Signed(caller),
- collection_id,
- nft_id,
- resource_id
- )
-
- accept_resource {
- let caller: T::AccountId = account("caller", 0, SEED);
- let admin: T::AccountId = account("admin", 0, SEED);
-
- create_max_collection::<T>(&admin)?;
- let collection_id = 0;
-
- let mut nft_builder = NftBuilder::new(collection_id);
- let root_nft_id = 1;
- let (_, nested_nft_id) = nft_builder.build_tower::<T>(&admin, NESTING_BUDGET - 1)?;
- let resource = create_basic_resource();
-
- let new_owner = <RmrkAccountIdOrCollectionNftTuple<T::AccountId>>::AccountId(caller.clone());
-
- <Pallet<T>>::send(
- RawOrigin::Signed(admin.clone()).into(),
- collection_id,
- root_nft_id,
- new_owner,
- )?;
-
- <Pallet<T>>::add_basic_resource(
- RawOrigin::Signed(admin.clone()).into(),
- collection_id,
- nested_nft_id,
- resource
- )?;
-
- let resource_id = 0;
- }: _(
- RawOrigin::Signed(caller),
- collection_id,
- nested_nft_id,
- resource_id
- )
-
- accept_resource_removal {
- let caller: T::AccountId = account("caller", 0, SEED);
- let admin: T::AccountId = account("admin", 0, SEED);
-
- create_max_collection::<T>(&admin)?;
- let collection_id = 0;
-
- let mut nft_builder = NftBuilder::new(collection_id);
- let root_nft_id = 1;
- let (_, nested_nft_id) = nft_builder.build_tower::<T>(&admin, NESTING_BUDGET - 1)?;
- let resource = create_basic_resource();
-
- <Pallet<T>>::add_basic_resource(
- RawOrigin::Signed(admin.clone()).into(),
- collection_id,
- nested_nft_id,
- resource
- )?;
-
- let resource_id = 0;
-
- let new_owner = <RmrkAccountIdOrCollectionNftTuple<T::AccountId>>::AccountId(caller.clone());
-
- <Pallet<T>>::send(
- RawOrigin::Signed(admin.clone()).into(),
- collection_id,
- root_nft_id,
- new_owner,
- )?;
-
- <Pallet<T>>::remove_resource(
- RawOrigin::Signed(admin).into(),
- collection_id,
- nested_nft_id,
- resource_id
- )?;
- }: _(
- RawOrigin::Signed(caller),
- collection_id,
- nested_nft_id,
- resource_id
- )
-}
pallets/proxy-rmrk-core/src/lib.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-core/src/lib.rs
+++ /dev/null
@@ -1,2119 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-//! # RMRK Core Proxy Pallet
-//!
-//! A pallet used as proxy for RMRK Core (<https://rmrk-team.github.io/rmrk-substrate/#/pallets/rmrk-core>).
-//!
-//! - [`Config`]
-//! - [`Call`]
-//! - [`Pallet`]
-//!
-//! ## Overview
-//!
-//! The RMRK Core Proxy pallet mirrors the functionality of RMRK Core,
-//! binding its externalities to Unique's own underlying structure.
-//! It is purposed to mimic RMRK Core exactly, allowing seamless integrations
-//! of solutions based on RMRK.
-//!
-//! RMRK Core itself contains essential functionality for RMRK's nested and
-//! multi-resourced NFTs.
-//!
-//! *Note*, that while RMRK itself is subject to active development and restructuring,
-//! the proxy may be caught temporarily out of date.
-//!
-//! ### What is RMRK?
-//!
-//! RMRK is a set of NFT standards which compose several "NFT 2.0 lego" primitives.
-//! Putting these legos together allows a user to create NFT systems of arbitrary complexity.
-//!
-//! Meaning, RMRK NFTs are dynamic, able to nest into each other and form a hierarchy,
-//! make use of specific changeable and partially shared metadata in the form of resources,
-//! and more.
-//!
-//! Visit RMRK documentation and repositories to learn more:
-//! - Docs: <https://docs.rmrk.app/getting-started/>
-//! - FAQ: <https://coda.io/@rmrk/faq>
-//! - Substrate code repository: <https://github.com/rmrk-team/rmrk-substrate>
-//! - RMRK specification repository: <https://github.com/rmrk-team/rmrk-spec>
-//!
-//! ## Terminology
-//!
-//! For more information on RMRK, see RMRK's own documentation.
-//!
-//! ### Intro to RMRK
-//!
-//! - **Resource:** Additional piece of metadata of an NFT usually serving to add
-//! a piece of media on top of the root metadata (NFT's own), be it a different wing
-//! on the root template bird or something entirely unrelated.
-//!
-//! - **Base:** A list of possible "components" - Parts, a combination of which can
-//! be appended/equipped to/on an NFT.
-//!
-//! - **Part:** Something that, together with other Parts, can constitute an NFT.
-//! Parts are defined in the Base to which they belong. Parts can be either
-//! of the `slot` type or `fixed` type. Slots are intended for equippables.
-//! Note that "part of something" and "Part of a Base" can be easily confused,
-//! and so in this documentation these words are distinguished by the capital letter.
-//!
-//! - **Theme:** Named objects of variable => value pairs which get interpolated into
-//! the Base's `themable` Parts. Themes can hold any value, but are often represented
-//! in RMRK's examples as colors applied to visible Parts.
-//!
-//! ### Peculiarities in Unique
-//!
-//! - **Scoped properties:** Properties that are normally obscured from users.
-//! Their purpose is to contain structured metadata that was not included in the Unique standard
-//! for collections and tokens, meant to be operated on by proxies and other outliers.
-//! Scoped property keys are prefixed with `some-scope:`, where `some-scope` is
-//! an arbitrary keyword, like "rmrk". `:` is considered an unacceptable symbol in user-defined
-//! properties, which, along with other safeguards, makes scoped ones impossible to tamper with.
-//!
-//! - **Auxiliary properties:** A slightly different structure of properties,
-//! trading universality of use for more convenient storage, writes and access.
-//! Meant to be inaccessible to end users.
-//!
-//! ## Proxy Implementation
-//!
-//! An external user is supposed to be able to utilize this proxy as they would
-//! utilize RMRK, and get exactly the same results. Normally, Unique transactions
-//! are off-limits to RMRK collections and tokens, and vice versa. However,
-//! the information stored on chain can be freely interpreted by storage reads and Unique RPCs.
-//!
-//! ### ID Mapping
-//!
-//! RMRK's collections' IDs are counted independently of Unique's and start at 0.
-//! Note that tokens' IDs still start at 1.
-//! The collections themselves, as well as tokens, are stored as Unique collections,
-//! and thus RMRK IDs are mapped to Unique IDs (but not vice versa).
-//!
-//! ### External/Internal Collection Insulation
-//!
-//! A Unique transaction cannot target collections purposed for RMRK,
-//! and they are flagged as `external` to specify that. On the other hand,
-//! due to the mapping, RMRK transactions and RPCs simply cannot reach Unique collections.
-//!
-//! ### Native Properties
-//!
-//! Many of RMRK's native parameters are stored as scoped properties of a collection
-//! or an NFT on the chain. Scoped properties are prefixed with `rmrk:`, where `:`
-//! is an unacceptable symbol in user-defined properties, which, along with other safeguards,
-//! makes them impossible to tamper with.
-//!
-//! ### Collection and NFT Types, or Base, Parts and Themes Handling
-//!
-//! RMRK introduces the concept of a Base, which is a catalogue of Parts,
-//! possible components of an NFT. Due to its similarity with the functionality
-//! of a token collection, a Base is stored and handled as one, and the Base's Parts and Themes
-//! are this collection's NFTs. See [`CollectionType`] and [`NftType`].
-//!
-//! ## Interface
-//!
-//! ### Dispatchables
-//!
-//! - `create_collection` - Create a new collection of NFTs.
-//! - `destroy_collection` - Destroy a collection.
-//! - `change_collection_issuer` - Change the issuer of a collection.
-//! Analogous to Unique's collection's [`owner`](up_data_structs::Collection).
-//! - `lock_collection` - "Lock" the collection and prevent new token creation. **Cannot be undone.**
-//! - `mint_nft` - Mint an NFT in a specified collection.
-//! - `burn_nft` - Burn an NFT, destroying it and its nested tokens.
-//! - `send` - Transfer an NFT from an account/NFT A to another account/NFT B.
-//! - `accept_nft` - Accept an NFT sent from another account to self or an owned NFT.
-//! - `reject_nft` - Reject an NFT sent from another account to self or owned NFT and **burn it**.
-//! - `accept_resource` - Accept the addition of a newly created pending resource to an existing NFT.
-//! - `accept_resource_removal` - Accept the removal of a removal-pending resource from an NFT.
-//! - `set_property` - Add or edit a custom user property of a token or a collection.
-//! - `set_priority` - Set a different order of resource priorities for an NFT.
-//! - `add_basic_resource` - Create and set/propose a basic resource for an NFT.
-//! - `add_composable_resource` - Create and set/propose a composable resource for an NFT.
-//! - `add_slot_resource` - Create and set/propose a slot resource for an NFT.
-//! - `remove_resource` - Remove and erase a resource from an NFT.
-
-#![cfg_attr(not(feature = "std"), no_std)]
-
-use frame_support::{pallet_prelude::*, BoundedVec, dispatch::DispatchResult};
-use frame_system::{pallet_prelude::*, ensure_signed};
-use sp_runtime::{DispatchError, Permill, traits::StaticLookup};
-use sp_std::{
- vec::Vec,
- collections::{btree_set::BTreeSet, btree_map::BTreeMap},
-};
-use up_data_structs::{*, mapping::TokenAddressMapping};
-use pallet_common::{
- Pallet as PalletCommon, Error as CommonError, CollectionHandle, CommonCollectionOperations,
-};
-use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle, TokenData};
-use pallet_structure::{Pallet as PalletStructure, Error as StructureError};
-use pallet_evm::account::CrossAccountId;
-use core::convert::AsRef;
-
-pub use pallet::*;
-
-#[cfg(feature = "runtime-benchmarks")]
-pub mod benchmarking;
-pub mod misc;
-pub mod property;
-pub mod rpc;
-pub mod weights;
-
-pub type SelfWeightOf<T> = <T as Config>::WeightInfo;
-
-use weights::WeightInfo;
-use misc::*;
-pub use property::*;
-
-use RmrkProperty::*;
-
-/// A maximum number of levels of depth in the token nesting tree.
-pub const NESTING_BUDGET: u32 = 5;
-
-type PendingTarget = (CollectionId, TokenId);
-type PendingChild = (RmrkCollectionId, RmrkNftId);
-type PendingChildrenSet = BTreeSet<PendingChild>;
-
-type BasesMap = BTreeMap<RmrkBaseId, u32>;
-
-#[frame_support::pallet]
-pub mod pallet {
- use super::*;
-
- #[pallet::config]
- pub trait Config:
- frame_system::Config
- + pallet_common::Config
- + pallet_nonfungible::Config
- + pallet_evm::Config
- {
- /// Overarching event type.
- type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
-
- /// The weight information of this pallet.
- type WeightInfo: WeightInfo;
- }
-
- /// Latest yet-unused collection ID.
- #[pallet::storage]
- #[pallet::getter(fn collection_index)]
- pub type CollectionIndex<T: Config> = StorageValue<_, RmrkCollectionId, ValueQuery>;
-
- /// Mapping from RMRK collection ID to Unique's.
- #[pallet::storage]
- pub type UniqueCollectionId<T: Config> =
- StorageMap<_, Twox64Concat, RmrkCollectionId, CollectionId, ValueQuery>;
-
- #[pallet::pallet]
- #[pallet::generate_store(pub(super) trait Store)]
- pub struct Pallet<T>(_);
-
- #[pallet::event]
- #[pallet::generate_deposit(pub(super) fn deposit_event)]
- pub enum Event<T: Config> {
- CollectionCreated {
- issuer: T::AccountId,
- collection_id: RmrkCollectionId,
- },
- CollectionDestroyed {
- issuer: T::AccountId,
- collection_id: RmrkCollectionId,
- },
- IssuerChanged {
- old_issuer: T::AccountId,
- new_issuer: T::AccountId,
- collection_id: RmrkCollectionId,
- },
- CollectionLocked {
- issuer: T::AccountId,
- collection_id: RmrkCollectionId,
- },
- NftMinted {
- owner: T::AccountId,
- collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
- },
- NFTBurned {
- owner: T::AccountId,
- nft_id: RmrkNftId,
- },
- NFTSent {
- sender: T::AccountId,
- recipient: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,
- collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
- approval_required: bool,
- },
- NFTAccepted {
- sender: T::AccountId,
- recipient: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,
- collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
- },
- NFTRejected {
- sender: T::AccountId,
- collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
- },
- PropertySet {
- collection_id: RmrkCollectionId,
- maybe_nft_id: Option<RmrkNftId>,
- key: RmrkKeyString,
- value: RmrkValueString,
- },
- ResourceAdded {
- nft_id: RmrkNftId,
- resource_id: RmrkResourceId,
- },
- ResourceRemoval {
- nft_id: RmrkNftId,
- resource_id: RmrkResourceId,
- },
- ResourceAccepted {
- nft_id: RmrkNftId,
- resource_id: RmrkResourceId,
- },
- ResourceRemovalAccepted {
- nft_id: RmrkNftId,
- resource_id: RmrkResourceId,
- },
- PrioritySet {
- collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
- },
- }
-
- #[pallet::error]
- pub enum Error<T> {
- /* Unique proxy-specific events */
- /// Property of the type of RMRK collection could not be read successfully.
- CorruptedCollectionType,
- // NftTypeEncodeError,
- /// Too many symbols supplied as the property key. The maximum is [256](up_data_structs::MAX_PROPERTY_KEY_LENGTH).
- RmrkPropertyKeyIsTooLong,
- /// Too many bytes supplied as the property value. The maximum is [32768](up_data_structs::MAX_PROPERTY_VALUE_LENGTH).
- RmrkPropertyValueIsTooLong,
- /// Could not find a property by the supplied key.
- RmrkPropertyIsNotFound,
- /// Something went wrong when decoding encoded data from the storage.
- /// Perhaps, there was a wrong key supplied for the type, or the data was improperly stored.
- UnableToDecodeRmrkData,
-
- /* RMRK compatible events */
- /// Only destroying collections without tokens is allowed.
- CollectionNotEmpty,
- /// Could not find an ID for a collection. It is likely there were too many collections created on the chain, causing an overflow.
- NoAvailableCollectionId,
- /// Token does not exist, or there is no suitable ID for it, likely too many tokens were created in a collection, causing an overflow.
- NoAvailableNftId,
- /// Collection does not exist, has a wrong type, or does not map to a Unique ID.
- CollectionUnknown,
- /// No permission to perform action.
- NoPermission,
- /// Token is marked as non-transferable, and thus cannot be transferred.
- NonTransferable,
- /// Too many tokens created in the collection, no new ones are allowed.
- CollectionFullOrLocked,
- /// No such resource found.
- ResourceDoesntExist,
- /// If an NFT is sent to a descendant, that would form a nesting loop, an ouroboros.
- /// Sending to self is redundant.
- CannotSendToDescendentOrSelf,
- /// Not the target owner of the sent NFT.
- CannotAcceptNonOwnedNft,
- /// Not the target owner of the sent NFT.
- CannotRejectNonOwnedNft,
- /// NFT was not sent and is not pending.
- CannotRejectNonPendingNft,
- /// Resource is not pending for the operation.
- ResourceNotPending,
- /// Could not find an ID for the resource. It is likely there were too many resources created on an NFT, causing an overflow.
- NoAvailableResourceId,
- }
-
- #[pallet::call]
- impl<T: Config> Pallet<T> {
- // todo :refactor replace every collection_id with rmrk_collection_id (and nft_id) in arguments for uniformity?
-
- /// Create a new collection of NFTs.
- ///
- /// # Permissions:
- /// * Anyone - will be assigned as the issuer of the collection.
- ///
- /// # Arguments:
- /// - `origin`: sender of the transaction
- /// - `metadata`: Metadata describing the collection, e.g. IPFS hash. Cannot be changed.
- /// - `max`: Optional maximum number of tokens.
- /// - `symbol`: UTF-8 string with token prefix, by which to represent the token in wallets and UIs.
- /// Analogous to Unique's [`token_prefix`](up_data_structs::Collection). Cannot be changed.
- #[pallet::call_index(0)]
- #[pallet::weight(<SelfWeightOf<T>>::create_collection())]
- pub fn create_collection(
- origin: OriginFor<T>,
- metadata: RmrkString,
- max: Option<u32>,
- symbol: RmrkCollectionSymbol,
- ) -> DispatchResult {
- let sender = ensure_signed(origin)?;
-
- let limits = CollectionLimits {
- owner_can_transfer: Some(false),
- token_limit: max,
- ..Default::default()
- };
-
- let data = CreateCollectionData {
- limits: Some(limits),
- token_prefix: symbol
- .into_inner()
- .try_into()
- .map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,
- permissions: Some(CollectionPermissions {
- nesting: Some(NestingPermissions {
- token_owner: true,
- collection_admin: false,
- restricted: None,
- #[cfg(feature = "runtime-benchmarks")]
- permissive: false,
- }),
- ..Default::default()
- }),
- ..Default::default()
- };
-
- let unique_collection_id = Self::init_collection(
- T::CrossAccountId::from_sub(sender.clone()),
- data,
- [
- Self::encode_rmrk_property(Metadata, &metadata)?,
- Self::encode_rmrk_property(CollectionType, &misc::CollectionType::Regular)?,
- ]
- .into_iter(),
- )?;
- let rmrk_collection_id = <CollectionIndex<T>>::get();
-
- <UniqueCollectionId<T>>::insert(rmrk_collection_id, unique_collection_id);
-
- <PalletCommon<T>>::set_scoped_collection_property(
- unique_collection_id,
- RMRK_SCOPE,
- Self::encode_rmrk_property(RmrkInternalCollectionId, &rmrk_collection_id)?,
- )?;
-
- <CollectionIndex<T>>::mutate(|n| *n += 1);
-
- Self::deposit_event(Event::CollectionCreated {
- issuer: sender,
- collection_id: rmrk_collection_id,
- });
-
- Ok(())
- }
-
- /// Destroy a collection.
- ///
- /// Only empty collections can be destroyed. If it has any tokens, they must be burned first.
- ///
- /// # Permissions:
- /// * Collection issuer
- ///
- /// # Arguments:
- /// - `origin`: sender of the transaction
- /// - `collection_id`: RMRK ID of the collection to destroy.
- #[pallet::call_index(1)]
- #[pallet::weight(<SelfWeightOf<T>>::destroy_collection())]
- pub fn destroy_collection(
- origin: OriginFor<T>,
- collection_id: RmrkCollectionId,
- ) -> DispatchResult {
- let sender = ensure_signed(origin)?;
- let cross_sender = T::CrossAccountId::from_sub(sender.clone());
-
- let collection = Self::get_typed_nft_collection(
- Self::unique_collection_id(collection_id)?,
- misc::CollectionType::Regular,
- )?;
- collection.check_is_external()?;
-
- <PalletNft<T>>::destroy_collection(collection, &cross_sender)
- .map_err(Self::map_unique_err_to_proxy)?;
-
- Self::deposit_event(Event::CollectionDestroyed {
- issuer: sender,
- collection_id,
- });
-
- Ok(())
- }
-
- /// Change the issuer of a collection. Analogous to Unique's collection's [`owner`](up_data_structs::Collection).
- ///
- /// # Permissions:
- /// * Collection issuer
- ///
- /// # Arguments:
- /// - `origin`: sender of the transaction
- /// - `collection_id`: RMRK collection ID to change the issuer of.
- /// - `new_issuer`: Collection's new issuer.
- #[pallet::call_index(2)]
- #[pallet::weight(<SelfWeightOf<T>>::change_collection_issuer())]
- pub fn change_collection_issuer(
- origin: OriginFor<T>,
- collection_id: RmrkCollectionId,
- new_issuer: <T::Lookup as StaticLookup>::Source,
- ) -> DispatchResult {
- let sender = ensure_signed(origin)?;
-
- let collection = Self::get_nft_collection(Self::unique_collection_id(collection_id)?)?;
- collection.check_is_external()?;
-
- let new_issuer = T::Lookup::lookup(new_issuer)?;
-
- Self::change_collection_owner(
- Self::unique_collection_id(collection_id)?,
- misc::CollectionType::Regular,
- sender.clone(),
- new_issuer.clone(),
- )?;
-
- Self::deposit_event(Event::IssuerChanged {
- old_issuer: sender,
- new_issuer,
- collection_id,
- });
-
- Ok(())
- }
-
- /// "Lock" the collection and prevent new token creation. Cannot be undone.
- ///
- /// # Permissions:
- /// * Collection issuer
- ///
- /// # Arguments:
- /// - `origin`: sender of the transaction
- /// - `collection_id`: RMRK ID of the collection to lock.
- #[pallet::call_index(3)]
- #[pallet::weight(<SelfWeightOf<T>>::lock_collection())]
- pub fn lock_collection(
- origin: OriginFor<T>,
- collection_id: RmrkCollectionId,
- ) -> DispatchResult {
- let sender = ensure_signed(origin)?;
- let cross_sender = T::CrossAccountId::from_sub(sender.clone());
-
- let collection = Self::get_typed_nft_collection(
- Self::unique_collection_id(collection_id)?,
- misc::CollectionType::Regular,
- )?;
- collection.check_is_external()?;
-
- Self::check_collection_owner(&collection, &cross_sender)?;
-
- let token_count = collection.total_supply();
-
- let mut collection = collection.into_inner();
- collection.limits.token_limit = Some(token_count);
- collection.save()?;
-
- Self::deposit_event(Event::CollectionLocked {
- issuer: sender,
- collection_id,
- });
-
- Ok(())
- }
-
- /// Mint an NFT in a specified collection.
- ///
- /// # Permissions:
- /// * Collection issuer
- ///
- /// # Arguments:
- /// - `origin`: sender of the transaction
- /// - `owner`: Owner account of the NFT. If set to None, defaults to the sender (collection issuer).
- /// - `collection_id`: RMRK collection ID for the NFT to be minted within. Cannot be changed.
- /// - `recipient`: Receiver account of the royalty. Has no effect if the `royalty_amount` is not set. Cannot be changed.
- /// - `royalty_amount`: Optional permillage reward from each trade for the `recipient`. Cannot be changed.
- /// - `metadata`: Arbitrary data about an NFT, e.g. IPFS hash. Cannot be changed.
- /// - `transferable`: Can this NFT be transferred? Cannot be changed.
- /// - `resources`: Resource data to be added to the NFT immediately after minting.
- #[pallet::call_index(4)]
- #[pallet::weight(<SelfWeightOf<T>>::mint_nft(resources.as_ref().map(|r| r.len() as u32).unwrap_or(0)))]
- pub fn mint_nft(
- origin: OriginFor<T>,
- owner: Option<T::AccountId>,
- collection_id: RmrkCollectionId,
- recipient: Option<T::AccountId>,
- royalty_amount: Option<Permill>,
- metadata: RmrkString,
- transferable: bool,
- resources: Option<BoundedVec<RmrkResourceTypes, MaxResourcesOnMint>>,
- ) -> DispatchResult {
- let sender = ensure_signed(origin)?;
- let cross_sender = T::CrossAccountId::from_sub(sender.clone());
-
- let owner = owner.unwrap_or(sender.clone());
- let cross_owner = T::CrossAccountId::from_sub(owner.clone());
-
- let collection = Self::get_typed_nft_collection(
- Self::unique_collection_id(collection_id)?,
- misc::CollectionType::Regular,
- )?;
- collection.check_is_external()?;
-
- let royalty_info = royalty_amount.map(|amount| rmrk_traits::RoyaltyInfo {
- recipient: recipient.unwrap_or_else(|| owner.clone()),
- amount,
- });
-
- let nft_id = Self::create_nft(
- &cross_sender,
- &cross_owner,
- &collection,
- [
- Self::encode_rmrk_property(TokenType, &NftType::Regular)?,
- Self::encode_rmrk_property(Transferable, &transferable)?,
- Self::encode_rmrk_property(PendingNftAccept, &None::<PendingTarget>)?,
- Self::encode_rmrk_property(RoyaltyInfo, &royalty_info)?,
- Self::encode_rmrk_property(Metadata, &metadata)?,
- Self::encode_rmrk_property(Equipped, &false)?,
- Self::encode_rmrk_property(ResourcePriorities, &<Vec<u8>>::new())?,
- Self::encode_rmrk_property(NextResourceId, &(0 as RmrkResourceId))?,
- Self::encode_rmrk_property(PendingChildren, &PendingChildrenSet::new())?,
- Self::encode_rmrk_property(AssociatedBases, &BasesMap::new())?,
- ]
- .into_iter(),
- )
- .map_err(|err| match err {
- DispatchError::Arithmetic(_) => <Error<T>>::NoAvailableNftId.into(),
- err => Self::map_unique_err_to_proxy(err),
- })?;
-
- if let Some(resources) = resources {
- for resource in resources {
- Self::resource_add(sender.clone(), collection.id, nft_id, resource)?;
- }
- }
-
- Self::deposit_event(Event::NftMinted {
- owner,
- collection_id,
- nft_id: nft_id.0,
- });
-
- Ok(())
- }
-
- /// Burn an NFT, destroying it and its nested tokens up to the specified limit.
- /// If the burning budget is exceeded, the transaction is reverted.
- ///
- /// This is the way to burn a nested token as well.
- ///
- /// For more information, see [`burn_recursively`](pallet_nonfungible::pallet::Pallet::burn_recursively).
- ///
- /// # Permissions:
- /// * Token owner
- ///
- /// # Arguments:
- /// - `origin`: sender of the transaction
- /// - `collection_id`: RMRK ID of the collection in which the NFT to burn belongs to.
- /// - `nft_id`: ID of the NFT to be destroyed.
- /// - `max_burns`: Maximum number of tokens to burn, assuming nesting. The transaction
- /// is reverted if there are more tokens to burn in the nesting tree than this number.
- /// This is primarily a mechanism of transaction weight control.
- #[pallet::call_index(5)]
- #[pallet::weight(<SelfWeightOf<T>>::burn_nft(*max_burns))]
- pub fn burn_nft(
- origin: OriginFor<T>,
- collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
- max_burns: u32,
- ) -> DispatchResult {
- let sender = ensure_signed(origin)?;
- let cross_sender = T::CrossAccountId::from_sub(sender.clone());
-
- let collection = Self::get_typed_nft_collection(
- Self::unique_collection_id(collection_id)?,
- misc::CollectionType::Regular,
- )?;
- collection.check_is_external()?;
-
- Self::destroy_nft(
- cross_sender,
- Self::unique_collection_id(collection_id)?,
- nft_id.into(),
- max_burns,
- <Error<T>>::NoPermission,
- )
- .map_err(|err| Self::map_unique_err_to_proxy(err.error))?;
-
- Self::deposit_event(Event::NFTBurned {
- owner: sender,
- nft_id,
- });
-
- Ok(())
- }
-
- /// Transfer an NFT from an account/NFT A to another account/NFT B.
- /// The token must be transferable. Nesting cannot occur deeper than the [`NESTING_BUDGET`].
- ///
- /// If the target owner is an NFT owned by another account, then the NFT will enter
- /// the pending state and will have to be accepted by the other account.
- ///
- /// # Permissions:
- /// - Token owner
- ///
- /// # Arguments:
- /// - `origin`: sender of the transaction
- /// - `rmrk_collection_id`: RMRK ID of the collection of the NFT to be transferred.
- /// - `rmrk_nft_id`: ID of the NFT to be transferred.
- /// - `new_owner`: New owner of the nft which can be either an account or a NFT.
- #[pallet::call_index(6)]
- #[pallet::weight(<SelfWeightOf<T>>::send())]
- pub fn send(
- origin: OriginFor<T>,
- rmrk_collection_id: RmrkCollectionId,
- rmrk_nft_id: RmrkNftId,
- new_owner: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,
- ) -> DispatchResult {
- let sender = ensure_signed(origin.clone())?;
- let cross_sender = T::CrossAccountId::from_sub(sender.clone());
-
- let collection_id = Self::unique_collection_id(rmrk_collection_id)?;
- let nft_id = rmrk_nft_id.into();
-
- let collection =
- Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;
- collection.check_is_external()?;
-
- let token_data =
- <TokenData<T>>::get((collection_id, nft_id)).ok_or(<Error<T>>::NoAvailableNftId)?;
-
- let from = token_data.owner;
-
- ensure!(
- Self::get_nft_property_decoded(collection_id, nft_id, RmrkProperty::Transferable)?,
- <Error<T>>::NonTransferable
- );
-
- ensure!(
- Self::get_nft_property_decoded::<Option<PendingTarget>>(
- collection_id,
- nft_id,
- RmrkProperty::PendingNftAccept
- )?
- .is_none(),
- <Error<T>>::NoPermission
- );
-
- let target_owner;
- let approval_required;
-
- match new_owner {
- RmrkAccountIdOrCollectionNftTuple::AccountId(ref account_id) => {
- target_owner = T::CrossAccountId::from_sub(account_id.clone());
- approval_required = false;
- }
- RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(
- target_collection_id,
- target_nft_id,
- ) => {
- let target_collection_id = Self::unique_collection_id(target_collection_id)?;
-
- let target_nft_budget = budget::Value::new(NESTING_BUDGET);
-
- let target_nft_owner = <PalletStructure<T>>::get_checked_topmost_owner(
- target_collection_id,
- target_nft_id.into(),
- Some((collection_id, nft_id)),
- &target_nft_budget,
- )
- .map_err(Self::map_unique_err_to_proxy)?
- .ok_or::<DispatchError>(<Error<T>>::NoPermission.into())?;
-
- approval_required = cross_sender != target_nft_owner;
-
- if approval_required {
- target_owner = target_nft_owner;
-
- <PalletNft<T>>::set_scoped_token_property(
- collection.id,
- nft_id,
- RMRK_SCOPE,
- Self::encode_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(
- target_collection_id,
- target_nft_id.into(),
- );
- }
- }
- }
-
- let src_nft_budget = budget::Value::new(NESTING_BUDGET);
-
- <PalletNft<T>>::transfer_from(
- &collection,
- &cross_sender,
- &from,
- &target_owner,
- nft_id,
- &src_nft_budget,
- )
- .map_err(Self::map_unique_err_to_proxy)?;
-
- Self::deposit_event(Event::NFTSent {
- sender,
- recipient: new_owner,
- collection_id: rmrk_collection_id,
- nft_id: rmrk_nft_id,
- approval_required,
- });
-
- Ok(())
- }
-
- /// Accept an NFT sent from another account to self or an owned NFT.
- ///
- /// The NFT in question must be pending, and, thus, be [sent](`Pallet::send`) first.
- ///
- /// # Permissions:
- /// - Token-owner-to-be
- ///
- /// # Arguments:
- /// - `origin`: sender of the transaction
- /// - `rmrk_collection_id`: RMRK collection ID of the NFT to be accepted.
- /// - `rmrk_nft_id`: ID of the NFT to be accepted.
- /// - `new_owner`: Either the sender's account ID or a sender-owned NFT,
- /// whichever the accepted NFT was sent to.
- #[pallet::call_index(7)]
- #[pallet::weight(<SelfWeightOf<T>>::accept_nft())]
- pub fn accept_nft(
- origin: OriginFor<T>,
- rmrk_collection_id: RmrkCollectionId,
- rmrk_nft_id: RmrkNftId,
- new_owner: RmrkAccountIdOrCollectionNftTuple<T::AccountId>,
- ) -> DispatchResult {
- let sender = ensure_signed(origin.clone())?;
- let cross_sender = T::CrossAccountId::from_sub(sender.clone());
-
- let collection_id = Self::unique_collection_id(rmrk_collection_id)?;
- let nft_id = rmrk_nft_id.into();
-
- let collection =
- Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;
- collection.check_is_external()?;
-
- let new_cross_owner = match new_owner {
- RmrkAccountIdOrCollectionNftTuple::AccountId(ref account_id) => {
- T::CrossAccountId::from_sub(account_id.clone())
- }
- RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(
- target_collection_id,
- target_nft_id,
- ) => {
- let target_collection_id = Self::unique_collection_id(target_collection_id)?;
-
- T::CrossTokenAddressMapping::token_to_address(
- target_collection_id,
- TokenId(target_nft_id),
- )
- }
- };
-
- let budget = budget::Value::new(NESTING_BUDGET);
-
- <PalletNft<T>>::transfer(
- &collection,
- &cross_sender,
- &new_cross_owner,
- nft_id,
- &budget,
- )
- .map_err(|err| {
- if err == <CommonError<T>>::UserIsNotAllowedToNest.into() {
- <Error<T>>::CannotAcceptNonOwnedNft.into()
- } else {
- Self::map_unique_err_to_proxy(err)
- }
- })?;
-
- let pending_target = Self::get_nft_property_decoded::<Option<PendingTarget>>(
- collection_id,
- nft_id,
- 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,
- RMRK_SCOPE,
- Self::encode_rmrk_property(PendingNftAccept, &None::<PendingTarget>)?,
- )?;
- }
-
- Self::deposit_event(Event::NFTAccepted {
- sender,
- recipient: new_owner,
- collection_id: rmrk_collection_id,
- nft_id: rmrk_nft_id,
- });
-
- Ok(())
- }
-
- /// Reject an NFT sent from another account to self or owned NFT.
- /// The NFT in question will not be sent back and burnt instead.
- ///
- /// The NFT in question must be pending, and, thus, be [sent](`Pallet::send`) first.
- ///
- /// # Permissions:
- /// - Token-owner-to-be-not
- ///
- /// # Arguments:
- /// - `origin`: sender of the transaction
- /// - `rmrk_collection_id`: RMRK ID of the NFT to be rejected.
- /// - `rmrk_nft_id`: ID of the NFT to be rejected.
- #[pallet::call_index(8)]
- #[pallet::weight(<SelfWeightOf<T>>::reject_nft())]
- pub fn reject_nft(
- origin: OriginFor<T>,
- rmrk_collection_id: RmrkCollectionId,
- rmrk_nft_id: RmrkNftId,
- ) -> DispatchResult {
- let sender = ensure_signed(origin)?;
- let cross_sender = T::CrossAccountId::from_sub(sender.clone());
-
- let collection_id = Self::unique_collection_id(rmrk_collection_id)?;
- let nft_id = rmrk_nft_id.into();
-
- let collection =
- Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;
- collection.check_is_external()?;
-
- ensure!(
- <TokenData<T>>::get((collection_id, nft_id)).is_some(),
- <Error<T>>::NoAvailableNftId
- );
-
- 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,
- nft_id,
- NESTING_BUDGET,
- <Error<T>>::CannotRejectNonOwnedNft,
- )
- .map_err(|err| Self::map_unique_err_to_proxy(err.error))?;
-
- Self::deposit_event(Event::NFTRejected {
- sender,
- collection_id: rmrk_collection_id,
- nft_id: rmrk_nft_id,
- });
-
- Ok(())
- }
-
- /// Accept the addition of a newly created pending resource to an existing NFT.
- ///
- /// This transaction is needed when a resource is created and assigned to an NFT
- /// by a non-owner, i.e. the collection issuer, with one of the
- /// [`add_...` transactions](Pallet::add_basic_resource).
- ///
- /// # Permissions:
- /// - Token owner
- ///
- /// # Arguments:
- /// - `origin`: sender of the transaction
- /// - `rmrk_collection_id`: RMRK collection ID of the NFT.
- /// - `rmrk_nft_id`: ID of the NFT with a pending resource to be accepted.
- /// - `resource_id`: ID of the newly created pending resource.
- /// accept the addition of a new resource to an existing NFT
- #[pallet::call_index(9)]
- #[pallet::weight(<SelfWeightOf<T>>::accept_resource())]
- pub fn accept_resource(
- origin: OriginFor<T>,
- rmrk_collection_id: RmrkCollectionId,
- rmrk_nft_id: RmrkNftId,
- 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(|_| <Error<T>>::ResourceDoesntExist)?;
- let collection =
- Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;
- collection.check_is_external()?;
-
- let nft_id = rmrk_nft_id.into();
-
- let budget = budget::Value::new(NESTING_BUDGET);
-
- let nft_owner =
- <PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)
- .map_err(|_| <Error<T>>::ResourceDoesntExist)?
- .ok_or::<DispatchError>(<Error<T>>::NoPermission.into())?;
-
- Self::try_mutate_resource_info(collection_id, nft_id, resource_id, |res| {
- ensure!(res.pending, <Error<T>>::ResourceNotPending);
- ensure!(cross_sender == nft_owner, <Error<T>>::NoPermission);
-
- res.pending = false;
-
- Ok(())
- })?;
-
- Self::deposit_event(Event::<T>::ResourceAccepted {
- nft_id: rmrk_nft_id,
- resource_id,
- });
-
- Ok(())
- }
-
- /// Accept the removal of a removal-pending resource from an NFT.
- ///
- /// This transaction is needed when a non-owner, i.e. the collection issuer,
- /// requests a [removal](`Pallet::remove_resource`) of a resource from an NFT.
- ///
- /// # Permissions:
- /// - Token owner
- ///
- /// # Arguments:
- /// - `origin`: sender of the transaction
- /// - `rmrk_collection_id`: RMRK collection ID of the NFT.
- /// - `rmrk_nft_id`: ID of the NFT with a resource to be removed.
- /// - `resource_id`: ID of the removal-pending resource.
- #[pallet::call_index(10)]
- #[pallet::weight(<SelfWeightOf<T>>::accept_resource_removal())]
- pub fn accept_resource_removal(
- origin: OriginFor<T>,
- rmrk_collection_id: RmrkCollectionId,
- rmrk_nft_id: RmrkNftId,
- 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(|_| <Error<T>>::ResourceDoesntExist)?;
- let collection =
- Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;
- collection.check_is_external()?;
-
- let nft_id = rmrk_nft_id.into();
-
- let budget = budget::Value::new(NESTING_BUDGET);
-
- let nft_owner =
- <PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)
- .map_err(|_| <Error<T>>::ResourceDoesntExist)?
- .ok_or::<DispatchError>(<Error<T>>::NoPermission.into())?;
-
- ensure!(cross_sender == nft_owner, <Error<T>>::NoPermission);
-
- let resource_id_key = Self::get_scoped_property_key(ResourceId(resource_id))?;
-
- let resource_info = <PalletNft<T>>::token_aux_property((
- collection_id,
- nft_id,
- RMRK_SCOPE,
- resource_id_key.clone(),
- ))
- .ok_or(<Error<T>>::ResourceDoesntExist)?;
-
- let resource_info: RmrkResourceInfo = Self::decode_property_value(&resource_info)?;
-
- ensure!(
- resource_info.pending_removal,
- <Error<T>>::ResourceNotPending
- );
-
- <PalletNft<T>>::remove_token_aux_property(
- collection_id,
- nft_id,
- RMRK_SCOPE,
- resource_id_key,
- );
-
- if let RmrkResourceTypes::Composable(resource) = resource_info.resource {
- let base_id = resource.base;
-
- Self::remove_associated_base_id(collection_id, nft_id, base_id)?;
- }
-
- Self::deposit_event(Event::<T>::ResourceRemovalAccepted {
- nft_id: rmrk_nft_id,
- resource_id,
- });
-
- Ok(())
- }
-
- /// Add or edit a custom user property, a key-value pair, describing the metadata
- /// of a token or a collection, on either one of these.
- ///
- /// Note that in this proxy implementation many details regarding RMRK are stored
- /// as scoped properties prefixed with "rmrk:", normally inaccessible
- /// to external transactions and RPCs.
- ///
- /// # Permissions:
- /// - Collection issuer - in case of collection property
- /// - Token owner - in case of NFT property
- ///
- /// # Arguments:
- /// - `origin`: sender of the transaction
- /// - `rmrk_collection_id`: RMRK collection ID.
- /// - `maybe_nft_id`: Optional ID of the NFT. If left empty, then the property is set for the collection.
- /// - `key`: Key of the custom property to be referenced by.
- /// - `value`: Value of the custom property to be stored.
- #[pallet::call_index(11)]
- #[pallet::weight(<SelfWeightOf<T>>::set_property())]
- pub fn set_property(
- origin: OriginFor<T>,
- #[pallet::compact] rmrk_collection_id: RmrkCollectionId,
- maybe_nft_id: Option<RmrkNftId>,
- key: RmrkKeyString,
- value: RmrkValueString,
- ) -> DispatchResult {
- let sender = ensure_signed(origin)?;
- let sender = T::CrossAccountId::from_sub(sender);
-
- let collection_id = Self::unique_collection_id(rmrk_collection_id)?;
- let collection =
- Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;
- collection.check_is_external()?;
-
- let budget = budget::Value::new(NESTING_BUDGET);
-
- match maybe_nft_id {
- Some(nft_id) => {
- let token_id: TokenId = nft_id.into();
-
- Self::ensure_nft_type(collection_id, token_id, NftType::Regular)?;
- Self::ensure_nft_owner(collection_id, token_id, &sender, &budget)?;
-
- <PalletNft<T>>::set_scoped_token_property(
- collection_id,
- token_id,
- RMRK_SCOPE,
- Self::encode_rmrk_property(UserProperty(key.as_slice()), &value)?,
- )?;
- }
- None => {
- let collection = Self::get_typed_nft_collection(
- collection_id,
- misc::CollectionType::Regular,
- )?;
-
- Self::check_collection_owner(&collection, &sender)?;
-
- <PalletCommon<T>>::set_scoped_collection_property(
- collection_id,
- RMRK_SCOPE,
- Self::encode_rmrk_property(UserProperty(key.as_slice()), &value)?,
- )?;
- }
- }
-
- Self::deposit_event(Event::PropertySet {
- collection_id: rmrk_collection_id,
- maybe_nft_id,
- key,
- value,
- });
-
- Ok(())
- }
-
- /// Set a different order of resource priorities for an NFT. Priorities can be used,
- /// for example, for order of rendering.
- ///
- /// Note that the priorities are not updated automatically, and are an empty vector
- /// by default. There is no pre-set definition for the order to be particular,
- /// it can be interpreted arbitrarily use-case by use-case.
- ///
- /// # Permissions:
- /// - Token owner
- ///
- /// # Arguments:
- /// - `origin`: sender of the transaction
- /// - `rmrk_collection_id`: RMRK collection ID of the NFT.
- /// - `rmrk_nft_id`: ID of the NFT to rearrange resource priorities for.
- /// - `priorities`: Ordered vector of resource IDs.
- #[pallet::call_index(12)]
- #[pallet::weight(<SelfWeightOf<T>>::set_priority())]
- pub fn set_priority(
- origin: OriginFor<T>,
- rmrk_collection_id: RmrkCollectionId,
- rmrk_nft_id: RmrkNftId,
- priorities: BoundedVec<RmrkResourceId, RmrkMaxPriorities>,
- ) -> DispatchResult {
- let sender = ensure_signed(origin)?;
- let sender = T::CrossAccountId::from_sub(sender);
-
- let collection_id = Self::unique_collection_id(rmrk_collection_id)?;
- let nft_id = rmrk_nft_id.into();
-
- let collection =
- Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;
- collection.check_is_external()?;
-
- let budget = budget::Value::new(NESTING_BUDGET);
-
- Self::ensure_nft_type(collection_id, nft_id, NftType::Regular)?;
- Self::ensure_nft_owner(collection_id, nft_id, &sender, &budget)?;
-
- <PalletNft<T>>::set_scoped_token_property(
- collection_id,
- nft_id,
- RMRK_SCOPE,
- Self::encode_rmrk_property(ResourcePriorities, &priorities.into_inner())?,
- )?;
-
- Self::deposit_event(Event::<T>::PrioritySet {
- collection_id: rmrk_collection_id,
- nft_id: rmrk_nft_id,
- });
-
- Ok(())
- }
-
- /// Create and set/propose a basic resource for an NFT.
- ///
- /// A basic resource is the simplest, lacking a Base and anything that comes with it.
- /// See RMRK docs for more information and examples.
- ///
- /// # Permissions:
- /// - Collection issuer - if not the token owner, adding the resource will warrant
- /// the owner's [acceptance](Pallet::accept_resource).
- ///
- /// # Arguments:
- /// - `origin`: sender of the transaction
- /// - `rmrk_collection_id`: RMRK collection ID of the NFT.
- /// - `nft_id`: ID of the NFT to assign a resource to.
- /// - `resource`: Data of the resource to be created.
- #[pallet::call_index(13)]
- #[pallet::weight(<SelfWeightOf<T>>::add_basic_resource())]
- pub fn add_basic_resource(
- origin: OriginFor<T>,
- rmrk_collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
- resource: RmrkBasicResource,
- ) -> DispatchResult {
- let sender = ensure_signed(origin.clone())?;
-
- let collection_id = Self::unique_collection_id(rmrk_collection_id)?;
- let collection =
- Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;
- collection.check_is_external()?;
-
- let resource_id = Self::resource_add(
- sender,
- collection_id,
- nft_id.into(),
- RmrkResourceTypes::Basic(resource),
- )?;
-
- Self::deposit_event(Event::ResourceAdded {
- nft_id,
- resource_id,
- });
- Ok(())
- }
-
- /// Create and set/propose a composable resource for an NFT.
- ///
- /// A composable resource links to a Base and has a subset of its Parts it is composed of.
- /// See RMRK docs for more information and examples.
- ///
- /// # Permissions:
- /// - Collection issuer - if not the token owner, adding the resource will warrant
- /// the owner's [acceptance](Pallet::accept_resource).
- ///
- /// # Arguments:
- /// - `origin`: sender of the transaction
- /// - `rmrk_collection_id`: RMRK collection ID of the NFT.
- /// - `nft_id`: ID of the NFT to assign a resource to.
- /// - `resource`: Data of the resource to be created.
- #[pallet::call_index(14)]
- #[pallet::weight(<SelfWeightOf<T>>::add_composable_resource())]
- pub fn add_composable_resource(
- origin: OriginFor<T>,
- rmrk_collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
- resource: RmrkComposableResource,
- ) -> DispatchResult {
- let sender = ensure_signed(origin.clone())?;
-
- let collection_id = Self::unique_collection_id(rmrk_collection_id)?;
- let collection =
- Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;
- collection.check_is_external()?;
-
- let base_id = resource.base;
-
- let resource_id = Self::resource_add(
- sender,
- collection_id,
- nft_id.into(),
- RmrkResourceTypes::Composable(resource),
- )?;
-
- <PalletNft<T>>::try_mutate_token_aux_property(
- collection_id,
- nft_id.into(),
- RMRK_SCOPE,
- Self::get_scoped_property_key(AssociatedBases)?,
- |value| -> DispatchResult {
- let mut bases: BasesMap = match value {
- Some(value) => Self::decode_property_value(value)?,
- None => BasesMap::new(),
- };
-
- *bases.entry(base_id).or_insert(0) += 1;
-
- *value = Some(Self::encode_property_value(&bases)?);
- Ok(())
- },
- )?;
-
- Self::deposit_event(Event::ResourceAdded {
- nft_id,
- resource_id,
- });
- Ok(())
- }
-
- /// Create and set/propose a slot resource for an NFT.
- ///
- /// A slot resource links to a Base and a slot ID in it which it can fit into.
- /// See RMRK docs for more information and examples.
- ///
- /// # Permissions:
- /// - Collection issuer - if not the token owner, adding the resource will warrant
- /// the owner's [acceptance](Pallet::accept_resource).
- ///
- /// # Arguments:
- /// - `origin`: sender of the transaction
- /// - `rmrk_collection_id`: RMRK collection ID of the NFT.
- /// - `nft_id`: ID of the NFT to assign a resource to.
- /// - `resource`: Data of the resource to be created.
- #[pallet::call_index(15)]
- #[pallet::weight(<SelfWeightOf<T>>::add_slot_resource())]
- pub fn add_slot_resource(
- origin: OriginFor<T>,
- rmrk_collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
- resource: RmrkSlotResource,
- ) -> DispatchResult {
- let sender = ensure_signed(origin.clone())?;
-
- let collection_id = Self::unique_collection_id(rmrk_collection_id)?;
- let collection =
- Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;
- collection.check_is_external()?;
-
- let resource_id = Self::resource_add(
- sender,
- collection_id,
- nft_id.into(),
- RmrkResourceTypes::Slot(resource),
- )?;
-
- Self::deposit_event(Event::ResourceAdded {
- nft_id,
- resource_id,
- });
- Ok(())
- }
-
- /// Remove and erase a resource from an NFT.
- ///
- /// If the sender does not own the NFT, then it will be pending confirmation,
- /// and will have to be [accepted](Pallet::accept_resource_removal) by the token owner.
- ///
- /// # Permissions
- /// - Collection issuer
- ///
- /// # Arguments
- /// - `origin`: sender of the transaction
- /// - `rmrk_collection_id`: RMRK ID of a collection to which the NFT making use of the resource belongs to.
- /// - `nft_id`: ID of the NFT with a resource to be removed.
- /// - `resource_id`: ID of the resource to be removed.
- #[pallet::call_index(16)]
- #[pallet::weight(<SelfWeightOf<T>>::remove_resource())]
- pub fn remove_resource(
- origin: OriginFor<T>,
- rmrk_collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
- resource_id: RmrkResourceId,
- ) -> DispatchResult {
- let sender = ensure_signed(origin.clone())?;
-
- let collection_id = Self::unique_collection_id(rmrk_collection_id)?;
- let collection =
- Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;
- collection.check_is_external()?;
-
- Self::resource_remove(sender, collection_id, nft_id.into(), resource_id)?;
-
- Self::deposit_event(Event::ResourceRemoval {
- nft_id,
- resource_id,
- });
- Ok(())
- }
- }
-}
-
-impl<T: Config> Pallet<T> {
- /// Transform one of possible RMRK keys into a byte key with a RMRK scope.
- pub fn get_scoped_property_key(rmrk_key: RmrkProperty) -> Result<PropertyKey, DispatchError> {
- let key = rmrk_key.to_key::<T>()?;
-
- let scoped_key = RMRK_SCOPE
- .apply(key)
- .map_err(|_| <Error<T>>::RmrkPropertyKeyIsTooLong)?;
-
- Ok(scoped_key)
- }
-
- /// Form a Unique property, transforming a RMRK key into bytes (without assigning the scope yet)
- /// and encoding the value from an arbitrary type into bytes.
- pub fn encode_rmrk_property<E: Encode>(
- rmrk_key: RmrkProperty,
- value: &E,
- ) -> Result<Property, DispatchError> {
- let key = rmrk_key.to_key::<T>()?;
-
- let value = Self::encode_property_value(value)?;
-
- let property = Property { key, value };
-
- Ok(property)
- }
-
- /// Encode property value from an arbitrary type into bytes for storage.
- pub fn encode_property_value<E: Encode, S: Get<u32>>(
- value: &E,
- ) -> Result<BoundedBytes<S>, DispatchError> {
- let value = value
- .encode()
- .try_into()
- .map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong)?;
-
- Ok(value)
- }
-
- /// Decode property value from bytes into an arbitrary type.
- pub fn decode_property_value<D: Decode, S: Get<u32>>(
- vec: &BoundedBytes<S>,
- ) -> Result<D, DispatchError> {
- vec.decode()
- .map_err(|_| <Error<T>>::UnableToDecodeRmrkData.into())
- }
-
- /// Change the limit of a property value byte vector.
- pub fn rebind<L, S>(vec: &BoundedVec<u8, L>) -> Result<BoundedVec<u8, S>, DispatchError>
- where
- BoundedVec<u8, S>: TryFrom<Vec<u8>>,
- {
- vec.rebind()
- .map_err(|_| <Error<T>>::RmrkPropertyValueIsTooLong.into())
- }
-
- /// Initialize a new NFT collection with certain RMRK-scoped properties.
- ///
- /// See [`init_collection`](pallet_nonfungible::pallet::Pallet::init_collection) for more details.
- fn init_collection(
- sender: T::CrossAccountId,
- data: CreateCollectionData<T::AccountId>,
- properties: impl Iterator<Item = Property>,
- ) -> Result<CollectionId, DispatchError> {
- let collection_id = <PalletNft<T>>::init_collection(
- sender.clone(),
- sender,
- data,
- up_data_structs::CollectionFlags {
- external: true,
- ..Default::default()
- },
- );
-
- if let Err(DispatchError::Arithmetic(_)) = &collection_id {
- return Err(<Error<T>>::NoAvailableCollectionId.into());
- }
-
- <PalletCommon<T>>::set_scoped_collection_properties(
- collection_id?,
- RMRK_SCOPE,
- properties,
- )?;
-
- collection_id
- }
-
- /// Mint a new NFT with certain RMRK-scoped properties. Sender must be the collection owner.
- ///
- /// See [`create_item`](pallet_nonfungible::pallet::Pallet::create_item) for more details.
- pub fn create_nft(
- sender: &T::CrossAccountId,
- owner: &T::CrossAccountId,
- collection: &NonfungibleHandle<T>,
- properties: impl Iterator<Item = Property>,
- ) -> Result<TokenId, DispatchError> {
- let data = CreateNftExData {
- properties: BoundedVec::default(),
- owner: owner.clone(),
- };
-
- let budget = budget::Value::new(NESTING_BUDGET);
-
- <PalletNft<T>>::create_item(collection, sender, data, &budget)?;
-
- let nft_id = <PalletNft<T>>::current_token_id(collection.id);
-
- <PalletNft<T>>::set_scoped_token_properties(collection.id, nft_id, RMRK_SCOPE, properties)?;
-
- Ok(nft_id)
- }
-
- /// Burn an NFT, along with its nested children, limited by `max_burns`. The sender must be the token owner.
- ///
- /// See [`burn_recursively`](pallet_nonfungible::pallet::Pallet::burn_recursively) for more details.
- fn destroy_nft(
- sender: T::CrossAccountId,
- collection_id: CollectionId,
- token_id: TokenId,
- max_burns: u32,
- error_if_not_owned: Error<T>,
- ) -> DispatchResultWithPostInfo {
- let collection =
- Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;
-
- let token_data =
- <TokenData<T>>::get((collection_id, token_id)).ok_or(<Error<T>>::NoAvailableNftId)?;
-
- let from = token_data.owner;
-
- let owner_check_budget = budget::Value::new(NESTING_BUDGET);
-
- ensure!(
- <PalletStructure<T>>::check_indirectly_owned(
- sender.clone(),
- collection_id,
- token_id,
- None,
- &owner_check_budget
- )?,
- error_if_not_owned,
- );
-
- let burns_budget = budget::Value::new(max_burns);
- let breadth_budget = budget::Value::new(max_burns);
-
- <PalletNft<T>>::burn_recursively(
- &collection,
- &from,
- token_id,
- &burns_budget,
- &breadth_budget,
- )
- }
-
- /// Add a sent token pending acceptance to the target owning token as a property.
- fn insert_pending_child(
- target: (CollectionId, TokenId),
- child: (RmrkCollectionId, RmrkNftId),
- ) -> DispatchResult {
- Self::mutate_pending_children(target, |pending_children| {
- pending_children.insert(child);
- })
- }
-
- /// Remove a sent token pending acceptance from the target token's properties.
- fn remove_pending_child(
- target: (CollectionId, TokenId),
- child: (RmrkCollectionId, RmrkNftId),
- ) -> DispatchResult {
- Self::mutate_pending_children(target, |pending_children| {
- pending_children.remove(&child);
- })
- }
-
- /// Apply a mutation to the property of a token containing sent tokens
- /// that are currently pending acceptance.
- fn mutate_pending_children(
- (target_collection_id, target_nft_id): (CollectionId, TokenId),
- f: impl FnOnce(&mut PendingChildrenSet),
- ) -> DispatchResult {
- <PalletNft<T>>::try_mutate_token_aux_property(
- target_collection_id,
- target_nft_id,
- RMRK_SCOPE,
- Self::get_scoped_property_key(PendingChildren)?,
- |pending_children| -> DispatchResult {
- let mut map = match pending_children {
- Some(map) => Self::decode_property_value(map)?,
- None => PendingChildrenSet::new(),
- };
-
- f(&mut map);
-
- *pending_children = Some(Self::encode_property_value(&map)?);
-
- Ok(())
- },
- )
- }
-
- /// Get an iterator from a token's property containing tokens sent to it
- /// that are currently pending acceptance.
- 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,
- RMRK_SCOPE,
- Self::get_scoped_property_key(PendingChildren)?,
- ));
-
- let pending_children = match property {
- Some(map) => Self::decode_property_value(&map)?,
- None => PendingChildrenSet::new(),
- };
-
- Ok(pending_children.into_iter())
- }
-
- /// Get incremented resource ID from within an NFT's properties and store the new latest ID.
- /// Thus, the returned resource ID should be used.
- ///
- /// Resource IDs are unique only across an NFT.
- fn acquire_next_resource_id(
- collection_id: CollectionId,
- nft_id: TokenId,
- ) -> Result<RmrkResourceId, DispatchError> {
- let resource_id: RmrkResourceId =
- Self::get_nft_property_decoded(collection_id, nft_id, NextResourceId)?;
-
- let next_id = resource_id
- .checked_add(1)
- .ok_or(<Error<T>>::NoAvailableResourceId)?;
-
- <PalletNft<T>>::set_scoped_token_property(
- collection_id,
- nft_id,
- RMRK_SCOPE,
- Self::encode_rmrk_property(NextResourceId, &next_id)?,
- )?;
-
- Ok(resource_id)
- }
-
- /// Create and add a resource for a regular NFT, mark it as pending if the sender
- /// is not the token owner. The sender must be the collection owner.
- fn resource_add(
- sender: T::AccountId,
- collection_id: CollectionId,
- nft_id: TokenId,
- resource: RmrkResourceTypes,
- ) -> Result<RmrkResourceId, DispatchError> {
- let collection =
- Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;
- ensure!(collection.owner == sender, Error::<T>::NoPermission);
-
- let sender = T::CrossAccountId::from_sub(sender);
- let budget = budget::Value::new(NESTING_BUDGET);
-
- let nft_owner = <PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)
- .map_err(Self::map_unique_err_to_proxy)?
- .ok_or::<DispatchError>(<Error<T>>::NoPermission.into())?;
-
- let pending = sender != nft_owner;
-
- let id = Self::acquire_next_resource_id(collection_id, nft_id)?;
-
- let resource_info = RmrkResourceInfo {
- id,
- resource,
- pending,
- pending_removal: false,
- };
-
- <PalletNft<T>>::try_mutate_token_aux_property(
- collection_id,
- nft_id,
- RMRK_SCOPE,
- Self::get_scoped_property_key(ResourceId(id))?,
- |value| -> DispatchResult {
- *value = Some(Self::encode_property_value(&resource_info)?);
-
- Ok(())
- },
- )?;
-
- Ok(id)
- }
-
- /// Designate a resource for erasure from an NFT, and remove it if the sender is the token owner.
- /// The sender must be the collection owner.
- fn resource_remove(
- sender: T::AccountId,
- collection_id: CollectionId,
- nft_id: TokenId,
- resource_id: RmrkResourceId,
- ) -> DispatchResult {
- let collection =
- Self::get_typed_nft_collection(collection_id, misc::CollectionType::Regular)?;
- ensure!(collection.owner == sender, Error::<T>::NoPermission);
-
- let resource_id_key = Self::get_scoped_property_key(ResourceId(resource_id))?;
-
- let resource = <PalletNft<T>>::token_aux_property((
- collection_id,
- nft_id,
- RMRK_SCOPE,
- resource_id_key.clone(),
- ))
- .ok_or(<Error<T>>::ResourceDoesntExist)?;
-
- let resource_info: RmrkResourceInfo = Self::decode_property_value(&resource)?;
-
- let budget = up_data_structs::budget::Value::new(NESTING_BUDGET);
- let topmost_owner =
- <PalletStructure<T>>::find_topmost_owner(collection_id, nft_id, &budget)?
- .ok_or::<DispatchError>(<Error<T>>::NoPermission.into())?;
-
- let sender = T::CrossAccountId::from_sub(sender);
- if topmost_owner == sender {
- <PalletNft<T>>::remove_token_aux_property(
- collection_id,
- nft_id,
- RMRK_SCOPE,
- Self::get_scoped_property_key(ResourceId(resource_id))?,
- );
-
- if let RmrkResourceTypes::Composable(resource) = resource_info.resource {
- let base_id = resource.base;
-
- Self::remove_associated_base_id(collection_id, nft_id, base_id)?;
- }
- } else {
- Self::try_mutate_resource_info(collection_id, nft_id, resource_id, |res| {
- res.pending_removal = true;
-
- Ok(())
- })?;
- }
-
- Ok(())
- }
-
- /// Remove a Base ID from an NFT if they are associated.
- /// The Base itself is deleted if the number of associated NFTs reaches 0.
- fn remove_associated_base_id(
- collection_id: CollectionId,
- nft_id: TokenId,
- base_id: RmrkBaseId,
- ) -> DispatchResult {
- <PalletNft<T>>::try_mutate_token_aux_property(
- collection_id,
- nft_id,
- RMRK_SCOPE,
- Self::get_scoped_property_key(AssociatedBases)?,
- |value| -> DispatchResult {
- let mut bases: BasesMap = match value {
- Some(value) => Self::decode_property_value(value)?,
- None => BasesMap::new(),
- };
-
- let remaining = bases.get(&base_id);
-
- if let Some(remaining) = remaining {
- if let Some(0) | None = remaining.checked_sub(1) {
- bases.remove(&base_id);
- }
- }
-
- *value = Some(Self::encode_property_value(&bases)?);
- Ok(())
- },
- )
- }
-
- /// Apply a mutation to a resource stored in the token properties of an NFT.
- fn try_mutate_resource_info(
- collection_id: CollectionId,
- nft_id: TokenId,
- resource_id: RmrkResourceId,
- f: impl FnOnce(&mut RmrkResourceInfo) -> DispatchResult,
- ) -> DispatchResult {
- <PalletNft<T>>::try_mutate_token_aux_property(
- collection_id,
- nft_id,
- RMRK_SCOPE,
- Self::get_scoped_property_key(ResourceId(resource_id))?,
- |value| match value {
- Some(value) => {
- let mut resource_info: RmrkResourceInfo = Self::decode_property_value(value)?;
-
- f(&mut resource_info)?;
-
- *value = Self::encode_property_value(&resource_info)?;
-
- Ok(())
- }
- None => Err(<Error<T>>::ResourceDoesntExist.into()),
- },
- )
- }
-
- /// Change the owner of an NFT collection, ensuring that the sender is the current owner.
- fn change_collection_owner(
- collection_id: CollectionId,
- collection_type: misc::CollectionType,
- sender: T::AccountId,
- new_owner: T::AccountId,
- ) -> DispatchResult {
- let collection = Self::get_typed_nft_collection(collection_id, collection_type)?;
- Self::check_collection_owner(&collection, &T::CrossAccountId::from_sub(sender))?;
-
- let mut collection = collection.into_inner();
-
- collection.owner = new_owner;
- collection.save()
- }
-
- /// Ensure that an account is the collection owner/issuer, return an error if not.
- pub fn check_collection_owner(
- collection: &NonfungibleHandle<T>,
- account: &T::CrossAccountId,
- ) -> DispatchResult {
- collection
- .check_is_owner(account)
- .map_err(Self::map_unique_err_to_proxy)
- }
-
- /// Get the latest yet-unused RMRK collection index from the storage.
- pub fn last_collection_idx() -> RmrkCollectionId {
- <CollectionIndex<T>>::get()
- }
-
- /// Get a mapping from a RMRK collection ID to its corresponding Unique collection ID.
- pub fn unique_collection_id(
- rmrk_collection_id: RmrkCollectionId,
- ) -> Result<CollectionId, DispatchError> {
- <UniqueCollectionId<T>>::try_get(rmrk_collection_id)
- .map_err(|_| <Error<T>>::CollectionUnknown.into())
- }
-
- /// Get a mapping from a Unique collection ID to its RMRK collection ID counterpart, if it exists.
- pub fn rmrk_collection_id(
- unique_collection_id: CollectionId,
- ) -> Result<RmrkCollectionId, DispatchError> {
- Self::get_collection_property_decoded(unique_collection_id, RmrkInternalCollectionId)
- }
-
- /// Fetch a Unique NFT collection.
- pub fn get_nft_collection(
- collection_id: CollectionId,
- ) -> Result<NonfungibleHandle<T>, DispatchError> {
- let collection = <CollectionHandle<T>>::try_get(collection_id)
- .map_err(|_| <Error<T>>::CollectionUnknown)?;
-
- match collection.mode {
- CollectionMode::NFT => Ok(NonfungibleHandle::cast(collection)),
- _ => Err(<Error<T>>::CollectionUnknown.into()),
- }
- }
-
- /// Check if an NFT collection with such an ID exists.
- pub fn collection_exists(collection_id: CollectionId) -> bool {
- <CollectionHandle<T>>::try_get(collection_id).is_ok()
- }
-
- /// Fetch and decode a RMRK-scoped collection property value in bytes.
- pub fn get_collection_property(
- collection_id: CollectionId,
- key: RmrkProperty,
- ) -> Result<PropertyValue, DispatchError> {
- let collection_property = <PalletCommon<T>>::collection_properties(collection_id)
- .get(&Self::get_scoped_property_key(key)?)
- .ok_or(<Error<T>>::CollectionUnknown)?
- .clone();
-
- Ok(collection_property)
- }
-
- /// Fetch a RMRK-scoped collection property and decode it from bytes into an appropriate type.
- pub fn get_collection_property_decoded<V: Decode>(
- collection_id: CollectionId,
- key: RmrkProperty,
- ) -> Result<V, DispatchError> {
- Self::decode_property_value(&Self::get_collection_property(collection_id, key)?)
- }
-
- /// Get the type of a collection stored as a scoped property.
- ///
- /// RMRK Core proxy differentiates between regular collections as well as RMRK Bases as collections.
- pub fn get_collection_type(
- collection_id: CollectionId,
- ) -> Result<misc::CollectionType, DispatchError> {
- Self::get_collection_property_decoded(collection_id, CollectionType).map_err(|err| {
- if err != <Error<T>>::CollectionUnknown.into() {
- <Error<T>>::CorruptedCollectionType.into()
- } else {
- err
- }
- })
- }
-
- /// Ensure that the type of the collection equals the provided type,
- /// otherwise return an error.
- pub fn ensure_collection_type(
- collection_id: CollectionId,
- collection_type: misc::CollectionType,
- ) -> DispatchResult {
- let actual_type = Self::get_collection_type(collection_id)?;
- ensure!(
- actual_type == collection_type,
- <CommonError<T>>::NoPermission
- );
-
- Ok(())
- }
-
- /// Fetch an NFT collection, but make sure it has the appropriate type.
- pub fn get_typed_nft_collection(
- collection_id: CollectionId,
- collection_type: misc::CollectionType,
- ) -> Result<NonfungibleHandle<T>, DispatchError> {
- Self::ensure_collection_type(collection_id, collection_type)?;
-
- Self::get_nft_collection(collection_id)
- }
-
- /// Same as [`get_typed_nft_collection`](crate::pallet::Pallet::get_typed_nft_collection),
- /// but also return the Unique collection ID.
- pub fn get_typed_nft_collection_mapped(
- rmrk_collection_id: RmrkCollectionId,
- collection_type: misc::CollectionType,
- ) -> Result<(NonfungibleHandle<T>, CollectionId), DispatchError> {
- let unique_collection_id = match collection_type {
- misc::CollectionType::Regular => Self::unique_collection_id(rmrk_collection_id)?,
- _ => rmrk_collection_id.into(),
- };
-
- let collection = Self::get_typed_nft_collection(unique_collection_id, collection_type)?;
-
- Ok((collection, unique_collection_id))
- }
-
- /// Fetch and decode a RMRK-scoped NFT property value in bytes.
- pub fn get_nft_property(
- collection_id: CollectionId,
- nft_id: TokenId,
- key: RmrkProperty,
- ) -> Result<PropertyValue, DispatchError> {
- let nft_property = <PalletNft<T>>::token_properties((collection_id, nft_id))
- .get(&Self::get_scoped_property_key(key)?)
- .ok_or(<Error<T>>::RmrkPropertyIsNotFound)?
- .clone();
-
- Ok(nft_property)
- }
-
- /// Fetch a RMRK-scoped NFT property and decode it from bytes into an appropriate type.
- pub fn get_nft_property_decoded<V: Decode>(
- collection_id: CollectionId,
- nft_id: TokenId,
- key: RmrkProperty,
- ) -> Result<V, DispatchError> {
- Self::decode_property_value(&Self::get_nft_property(collection_id, nft_id, key)?)
- }
-
- /// Check that an NFT exists.
- pub fn nft_exists(collection_id: CollectionId, nft_id: TokenId) -> bool {
- <TokenData<T>>::contains_key((collection_id, nft_id))
- }
-
- /// Get the type of an NFT stored as a scoped property.
- ///
- /// RMRK Core proxy differentiates between regular NFTs, and RMRK Parts and Themes.
- pub fn get_nft_type(
- collection_id: CollectionId,
- token_id: TokenId,
- ) -> Result<NftType, DispatchError> {
- Self::get_nft_property_decoded(collection_id, token_id, TokenType)
- .map_err(|_| <Error<T>>::NoAvailableNftId.into())
- }
-
- /// Ensure that the type of the NFT equals the provided type, otherwise return an error.
- pub fn ensure_nft_type(
- collection_id: CollectionId,
- token_id: TokenId,
- nft_type: NftType,
- ) -> DispatchResult {
- let actual_type = Self::get_nft_type(collection_id, token_id)?;
- ensure!(actual_type == nft_type, <Error<T>>::NoPermission);
-
- Ok(())
- }
-
- /// Ensure that an account is the owner of the token, either directly
- /// or at the top of the nesting hierarchy; return an error if it is not.
- pub fn ensure_nft_owner(
- collection_id: CollectionId,
- token_id: TokenId,
- possible_owner: &T::CrossAccountId,
- nesting_budget: &dyn budget::Budget,
- ) -> DispatchResult {
- let is_owned = <PalletStructure<T>>::check_indirectly_owned(
- possible_owner.clone(),
- collection_id,
- token_id,
- None,
- nesting_budget,
- )
- .map_err(Self::map_unique_err_to_proxy)?;
-
- ensure!(is_owned, <Error<T>>::NoPermission);
-
- Ok(())
- }
-
- /// Fetch non-scoped properties of a collection or a token that match the filter keys supplied,
- /// or, if None are provided, return all non-scoped properties.
- pub fn filter_user_properties<Key, Value, R, Mapper>(
- collection_id: CollectionId,
- token_id: Option<TokenId>,
- filter_keys: Option<Vec<RmrkPropertyKey>>,
- mapper: Mapper,
- ) -> Result<Vec<R>, DispatchError>
- where
- Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,
- Value: Decode + Default,
- Mapper: Fn(Key, Value) -> R,
- {
- filter_keys
- .map(|keys| {
- let properties = keys
- .into_iter()
- .filter_map(|key| {
- let key: Key = key.try_into().ok()?;
-
- let value = match token_id {
- Some(token_id) => Self::get_nft_property_decoded(
- collection_id,
- token_id,
- UserProperty(key.as_ref()),
- ),
- None => Self::get_collection_property_decoded(
- collection_id,
- UserProperty(key.as_ref()),
- ),
- }
- .ok()?;
-
- Some(mapper(key, value))
- })
- .collect();
-
- Ok(properties)
- })
- .unwrap_or_else(|| {
- let properties =
- Self::iterate_user_properties(collection_id, token_id, mapper)?.collect();
-
- Ok(properties)
- })
- }
-
- /// Get all non-scoped properties from a collection or a token, and apply some transformation,
- /// supplied by `mapper`, to each key-value pair.
- pub fn iterate_user_properties<Key, Value, R, Mapper>(
- collection_id: CollectionId,
- token_id: Option<TokenId>,
- mapper: Mapper,
- ) -> Result<impl Iterator<Item = R>, DispatchError>
- where
- Key: TryFrom<RmrkPropertyKey> + AsRef<[u8]>,
- Value: Decode + Default,
- Mapper: Fn(Key, Value) -> R,
- {
- 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 = strip_key_prefix(&key, USER_PROPERTY_PREFIX)?;
-
- let key: Key = key.to_vec().try_into().ok()?;
- let value: Value = value.decode().ok()?;
-
- Some(mapper(key, value))
- });
-
- Ok(properties)
- }
-
- /// Match Unique errors to RMRK's own and return the RMRK error if a match is successful.
- fn map_unique_err_to_proxy(err: DispatchError) -> DispatchError {
- map_unique_err_to_proxy! {
- match err {
- CommonError::NoPermission => NoPermission,
- CommonError::CollectionTokenLimitExceeded => CollectionFullOrLocked,
- CommonError::PublicMintingNotAllowed => NoPermission,
- CommonError::TokenNotFound => NoAvailableNftId,
- CommonError::ApprovedValueTooLow => NoPermission,
- CommonError::CantDestroyNotEmptyCollection => CollectionNotEmpty,
- StructureError::TokenNotFound => NoAvailableNftId,
- StructureError::OuroborosDetected => CannotSendToDescendentOrSelf,
- }
- }
- }
-}
pallets/proxy-rmrk-core/src/misc.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-core/src/misc.rs
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-//! Miscellaneous helpers and utilities used by the proxy pallet.
-
-use super::*;
-use codec::{Encode, Decode, Error};
-
-/// Match an error to a provided pattern matcher and get
-/// the corresponding error of another type if a match is successful.
-#[macro_export]
-macro_rules! map_unique_err_to_proxy {
- (match $err:ident { $($unique_err_ty:ident :: $unique_err:ident => $proxy_err:ident),+ $(,)? }) => {
- $(
- if $err == <$unique_err_ty<T>>::$unique_err.into() {
- return <Error<T>>::$proxy_err.into()
- } else
- )+ {
- $err
- }
- };
-}
-
-/// Interface to decode some serialized bytes into an arbitrary type `T`,
-/// preferably if these bytes were originally encoded from `T`.
-pub trait RmrkDecode<T: Decode, S> {
- /// Try to decode self into an arbitrary type `T`.
- fn decode(&self) -> Result<T, Error>;
-}
-
-impl<T: Decode, S> RmrkDecode<T, S> for BoundedVec<u8, S> {
- fn decode(&self) -> Result<T, Error> {
- let mut value = self.as_slice();
-
- T::decode(&mut value)
- }
-}
-
-/// Interface to "rebind" - change the limit of a bounded byte vector.
-pub trait RmrkRebind<T, S> {
- /// Try to change the limit of a bounded byte vector.
- fn rebind(&self) -> Result<BoundedVec<u8, S>, Error>;
-}
-
-impl<T, S> RmrkRebind<T, S> for BoundedVec<u8, T>
-where
- BoundedVec<u8, S>: TryFrom<Vec<u8>>,
-{
- fn rebind(&self) -> Result<BoundedVec<u8, S>, Error> {
- BoundedVec::<u8, S>::try_from(self.clone().into_inner())
- .map_err(|_| "BoundedVec exceeds its limit".into())
- }
-}
-
-/// RMRK Base shares functionality with a regular collection, and is thus
-/// stored as one, but they are used for different purposes and need to be differentiated.
-#[derive(Encode, Decode, PartialEq, Eq)]
-pub enum CollectionType {
- Regular,
- Base,
-}
-
-/// RMRK Base, being stored as a collection, can have different kinds of tokens,
-/// all except the `Regular` type, which is attributed to `Regular` collection.
-#[derive(Encode, Decode, PartialEq, Eq)]
-pub enum NftType {
- Regular,
- FixedPart,
- SlotPart,
- Theme,
-}
pallets/proxy-rmrk-core/src/property.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-core/src/property.rs
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-//! Details of storing and handling RMRK properties.
-
-use super::*;
-use up_data_structs::PropertyScope;
-use core::convert::AsRef;
-
-/// Property prefix for storing resources.
-pub const RESOURCE_ID_PREFIX: &str = "rsid-";
-/// Property prefix for storing custom user-defined properties.
-pub const USER_PROPERTY_PREFIX: &str = "userprop-";
-/// Property scope for RMRK, used to signify that this property
-/// was created and is used by RMRK.
-pub const RMRK_SCOPE: PropertyScope = PropertyScope::Rmrk;
-
-/// Predefined RMRK property keys for storage of RMRK data format on the Unique chain.
-pub enum RmrkProperty<'r> {
- Metadata,
- CollectionType,
- RmrkInternalCollectionId,
- TokenType,
- Transferable,
- RoyaltyInfo,
- Equipped,
- ResourcePriorities,
- NextResourceId,
- ResourceId(RmrkResourceId),
- PendingNftAccept,
- PendingChildren,
- AssociatedBases,
- Parts,
- Base,
- Src,
- EquippedNft,
- BaseType,
- ExternalPartId,
- EquippableList,
- ZIndex,
- ThemeName,
- ThemeInherit,
- UserProperty(&'r [u8]),
-}
-
-impl<'r> RmrkProperty<'r> {
- /// Convert a predefined RMRK property key enum into string bytes.
- pub fn to_key<T: Config>(self) -> Result<PropertyKey, Error<T>> {
- fn get_bytes<T: AsRef<[u8]>>(container: &T) -> &[u8] {
- container.as_ref()
- }
-
- macro_rules! key {
- ($($component:expr),+) => {
- PropertyKey::try_from([$(key!(@ &$component)),+].concat())
- .map_err(|_| <Error<T>>::RmrkPropertyKeyIsTooLong)
- };
-
- (@ $key:expr) => {
- get_bytes($key)
- };
- }
-
- match self {
- Self::Metadata => key!("metadata"),
- Self::CollectionType => key!("collection-type"),
- Self::RmrkInternalCollectionId => key!("internal-id"),
- Self::TokenType => key!("token-type"),
- Self::Transferable => key!("transferable"),
- Self::RoyaltyInfo => key!("royalty-info"),
- Self::Equipped => key!("equipped"),
- Self::ResourcePriorities => key!("resource-priorities"),
- Self::NextResourceId => key!("next-resource-id"),
- Self::ResourceId(id) => key!(RESOURCE_ID_PREFIX, id.to_le_bytes()),
- Self::PendingNftAccept => key!("pending-nft-accept"),
- Self::PendingChildren => key!("pending-children"),
- Self::AssociatedBases => key!("assoc-bases"),
- Self::Parts => key!("parts"),
- Self::Base => key!("base"),
- Self::Src => key!("src"),
- Self::EquippedNft => key!("equipped-nft"),
- Self::BaseType => key!("base-type"),
- Self::ExternalPartId => key!("ext-part-id"),
- Self::EquippableList => key!("equippable-list"),
- Self::ZIndex => key!("z-index"),
- Self::ThemeName => key!("theme-name"),
- Self::ThemeInherit => key!("theme-inherit"),
- Self::UserProperty(name) => key!(USER_PROPERTY_PREFIX, name),
- }
- }
-}
-
-/// Strip a property key of its prefix and RMRK scope.
-pub fn strip_key_prefix(key: &PropertyKey, prefix: &str) -> Option<PropertyKey> {
- let key_prefix = PropertyKey::try_from(prefix.as_bytes().to_vec()).ok()?;
- let key_prefix = RMRK_SCOPE.apply(key_prefix).ok()?;
-
- key.as_slice()
- .strip_prefix(key_prefix.as_slice())?
- .to_vec()
- .try_into()
- .ok()
-}
-
-/// Check that the key has the prefix.
-pub fn is_valid_key_prefix(key: &PropertyKey, prefix: &str) -> bool {
- strip_key_prefix(key, prefix).is_some()
-}
pallets/proxy-rmrk-core/src/rpc.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-core/src/rpc.rs
+++ /dev/null
@@ -1,293 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-//! Realizations of RMRK RPCs (remote procedure calls) related to the Core pallet.
-
-use super::*;
-
-/// Get the latest created collection ID.
-pub fn last_collection_idx<T: Config>() -> Result<RmrkCollectionId, DispatchError> {
- Ok(<Pallet<T>>::last_collection_idx())
-}
-
-/// Get collection info by ID.
-pub fn collection_by_id<T: Config>(
- collection_id: RmrkCollectionId,
-) -> Result<Option<RmrkCollectionInfo<T::AccountId>>, DispatchError> {
- let (collection, collection_id) = match <Pallet<T>>::get_typed_nft_collection_mapped(
- collection_id,
- misc::CollectionType::Regular,
- ) {
- Ok(c) => c,
- Err(_) => return Ok(None),
- };
-
- let nfts_count = collection.total_supply();
-
- Ok(Some(RmrkCollectionInfo {
- issuer: collection.owner.clone(),
- metadata: <Pallet<T>>::get_collection_property_decoded(
- collection_id,
- RmrkProperty::Metadata,
- )?,
- max: collection.limits.token_limit,
- symbol: <Pallet<T>>::rebind(&collection.token_prefix)?,
- nfts_count,
- }))
-}
-
-/// Get NFT info by collection and NFT IDs.
-pub fn nft_by_id<T: Config>(
- collection_id: RmrkCollectionId,
- nft_by_id: RmrkNftId,
-) -> Result<Option<RmrkInstanceInfo<T::AccountId>>, DispatchError> {
- let (collection, collection_id) = match <Pallet<T>>::get_typed_nft_collection_mapped(
- collection_id,
- misc::CollectionType::Regular,
- ) {
- Ok(c) => c,
- Err(_) => return Ok(None),
- };
-
- let nft_id = TokenId(nft_by_id);
- if !<Pallet<T>>::nft_exists(collection_id, nft_id) {
- return Ok(None);
- }
-
- let owner = match collection.token_owner(nft_id) {
- Ok(owner) => match T::CrossTokenAddressMapping::address_to_token(&owner) {
- Some((col, tok)) => {
- let rmrk_collection = <Pallet<T>>::rmrk_collection_id(col)?;
-
- RmrkAccountIdOrCollectionNftTuple::CollectionAndNftTuple(rmrk_collection, tok.0)
- }
- None => RmrkAccountIdOrCollectionNftTuple::AccountId(owner.as_sub().clone()),
- },
- _ => return Ok(None),
- };
-
- Ok(Some(RmrkInstanceInfo {
- owner: owner,
- royalty: <Pallet<T>>::get_nft_property_decoded(
- collection_id,
- nft_id,
- RmrkProperty::RoyaltyInfo,
- )?,
- metadata: <Pallet<T>>::get_nft_property_decoded(
- collection_id,
- nft_id,
- RmrkProperty::Metadata,
- )?,
- equipped: <Pallet<T>>::get_nft_property_decoded(
- collection_id,
- nft_id,
- RmrkProperty::Equipped,
- )?,
- pending: <Pallet<T>>::get_nft_property_decoded(
- collection_id,
- nft_id,
- RmrkProperty::PendingNftAccept,
- )?,
- }))
-}
-
-/// Get tokens owned by an account in a collection.
-pub fn account_tokens<T: Config>(
- account_id: T::AccountId,
- collection_id: RmrkCollectionId,
-) -> Result<Vec<RmrkNftId>, DispatchError> {
- let cross_account_id = CrossAccountId::from_sub(account_id);
-
- let (collection, collection_id) = match <Pallet<T>>::get_typed_nft_collection_mapped(
- collection_id,
- misc::CollectionType::Regular,
- ) {
- Ok(c) => c,
- Err(_) => return Ok(Vec::new()),
- };
-
- let tokens = collection
- .account_tokens(cross_account_id)
- .into_iter()
- .filter(|token| {
- let is_pending = <Pallet<T>>::get_nft_property_decoded(
- collection_id,
- *token,
- RmrkProperty::PendingNftAccept,
- )
- .unwrap_or(true);
-
- !is_pending
- })
- .map(|token| token.0)
- .collect();
-
- Ok(tokens)
-}
-
-/// Get tokens nested in an NFT - its direct children (not the children's children).
-pub fn nft_children<T: Config>(
- collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
-) -> Result<Vec<RmrkNftChild>, DispatchError> {
- let collection_id = match <Pallet<T>>::unique_collection_id(collection_id) {
- Ok(id) => id,
- Err(_) => return Ok(Vec::new()),
- };
- let nft_id = TokenId(nft_id);
- if !<Pallet<T>>::nft_exists(collection_id, nft_id) {
- return Ok(Vec::new());
- }
-
- Ok(
- pallet_nonfungible::TokenChildren::<T>::iter_prefix((collection_id, nft_id))
- .filter_map(|((child_collection, child_token), _)| {
- let rmrk_child_collection =
- <Pallet<T>>::rmrk_collection_id(child_collection).ok()?;
-
- Some(RmrkNftChild {
- collection_id: rmrk_child_collection,
- 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(),
- )
-}
-
-/// Get collection properties, created by the user - not the proxy-specific properties.
-pub fn collection_properties<T: Config>(
- collection_id: RmrkCollectionId,
- filter_keys: Option<Vec<RmrkPropertyKey>>,
-) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
- let collection_id = match <Pallet<T>>::unique_collection_id(collection_id) {
- Ok(id) => id,
- Err(_) => return Ok(Vec::new()),
- };
- if <Pallet<T>>::ensure_collection_type(collection_id, misc::CollectionType::Regular).is_err() {
- return Ok(Vec::new());
- }
-
- let properties = <Pallet<T>>::filter_user_properties(
- collection_id,
- /* token_id = */ None,
- filter_keys,
- |key, value| RmrkPropertyInfo { key, value },
- )?;
-
- Ok(properties)
-}
-
-/// Get NFT properties, created by the user - not the proxy-specific properties.
-pub fn nft_properties<T: Config>(
- collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
- filter_keys: Option<Vec<RmrkPropertyKey>>,
-) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
- let collection_id = match <Pallet<T>>::unique_collection_id(collection_id) {
- Ok(id) => id,
- Err(_) => return Ok(Vec::new()),
- };
- let token_id = TokenId(nft_id);
-
- if <Pallet<T>>::ensure_nft_type(collection_id, token_id, NftType::Regular).is_err() {
- return Ok(Vec::new());
- }
-
- let properties = <Pallet<T>>::filter_user_properties(
- collection_id,
- Some(token_id),
- filter_keys,
- |key, value| RmrkPropertyInfo { key, value },
- )?;
-
- Ok(properties)
-}
-
-/// Get full information on each resource of an NFT, including pending.
-pub fn nft_resources<T: Config>(
- collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
-) -> Result<Vec<RmrkResourceInfo>, DispatchError> {
- let collection_id = match <Pallet<T>>::unique_collection_id(collection_id) {
- Ok(id) => id,
- Err(_) => return Ok(Vec::new()),
- };
- if <Pallet<T>>::ensure_collection_type(collection_id, misc::CollectionType::Regular).is_err() {
- return Ok(Vec::new());
- }
-
- let nft_id = TokenId(nft_id);
- if <Pallet<T>>::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() {
- return Ok(Vec::new());
- }
-
- let resources = <pallet_nonfungible::Pallet<T>>::iterate_token_aux_properties(
- collection_id,
- nft_id,
- PropertyScope::Rmrk,
- )
- .filter_map(|(key, value)| {
- if !is_valid_key_prefix(&key, RESOURCE_ID_PREFIX) {
- return None;
- }
-
- let resource_info: RmrkResourceInfo = <Pallet<T>>::decode_property_value(&value).ok()?;
-
- Some(resource_info)
- })
- .collect();
-
- Ok(resources)
-}
-
-/// Get the priority of a resource in an NFT.
-pub fn nft_resource_priority<T: Config>(
- collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
- resource_id: RmrkResourceId,
-) -> Result<Option<u32>, DispatchError> {
- let collection_id = match <Pallet<T>>::unique_collection_id(collection_id) {
- Ok(id) => id,
- Err(_) => return Ok(None),
- };
- if <Pallet<T>>::ensure_collection_type(collection_id, misc::CollectionType::Regular).is_err() {
- return Ok(None);
- }
-
- let nft_id = TokenId(nft_id);
- if <Pallet<T>>::ensure_nft_type(collection_id, nft_id, NftType::Regular).is_err() {
- return Ok(None);
- }
-
- let priorities: Vec<_> = <Pallet<T>>::get_nft_property_decoded(
- collection_id,
- nft_id,
- RmrkProperty::ResourcePriorities,
- )?;
- Ok(priorities
- .into_iter()
- .enumerate()
- .find(|(_, id)| *id == resource_id)
- .map(|(priority, _): (usize, RmrkResourceId)| priority as u32))
-}
pallets/proxy-rmrk-core/src/weights.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-core/src/weights.rs
+++ /dev/null
@@ -1,480 +0,0 @@
-// Template adopted from https://github.com/paritytech/substrate/blob/master/.maintain/frame-weight-template.hbs
-
-//! Autogenerated weights for pallet_proxy_rmrk_core
-//!
-//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-//! DATE: 2022-08-15, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`
-//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024
-
-// Executed Command:
-// target/release/unique-collator
-// benchmark
-// pallet
-// --pallet
-// pallet-proxy-rmrk-core
-// --wasm-execution
-// compiled
-// --extrinsic
-// *
-// --template
-// .maintain/frame-weight-template.hbs
-// --steps=50
-// --repeat=80
-// --heap-pages=4096
-// --output=./pallets/proxy-rmrk-core/src/weights.rs
-
-#![cfg_attr(rustfmt, rustfmt_skip)]
-#![allow(unused_parens)]
-#![allow(unused_imports)]
-#![allow(clippy::unnecessary_cast)]
-
-use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
-use sp_std::marker::PhantomData;
-
-/// Weight functions needed for pallet_proxy_rmrk_core.
-pub trait WeightInfo {
- fn create_collection() -> Weight;
- fn destroy_collection() -> Weight;
- fn change_collection_issuer() -> Weight;
- fn lock_collection() -> Weight;
- fn mint_nft(b: u32, ) -> Weight;
- fn burn_nft(b: u32, ) -> Weight;
- fn send() -> Weight;
- fn accept_nft() -> Weight;
- fn reject_nft() -> Weight;
- fn set_property() -> Weight;
- fn set_priority() -> Weight;
- fn add_basic_resource() -> Weight;
- fn add_composable_resource() -> Weight;
- fn add_slot_resource() -> Weight;
- fn remove_resource() -> Weight;
- fn accept_resource() -> Weight;
- fn accept_resource_removal() -> Weight;
-}
-
-/// Weights for pallet_proxy_rmrk_core using the Substrate node and recommended hardware.
-pub struct SubstrateWeight<T>(PhantomData<T>);
-impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
- // Storage: Common CreatedCollectionCount (r:1 w:1)
- // Storage: Common DestroyedCollectionCount (r:1 w:0)
- // Storage: System Account (r:2 w:2)
- // Storage: RmrkCore CollectionIndex (r:1 w:1)
- // Storage: Common CollectionPropertyPermissions (r:0 w:1)
- // Storage: Common CollectionProperties (r:0 w:1)
- // Storage: Common CollectionById (r:0 w:1)
- // Storage: RmrkCore UniqueCollectionId (r:0 w:1)
- fn create_collection() -> Weight {
- Weight::from_ref_time(49_754_000)
- .saturating_add(T::DbWeight::get().reads(5 as u64))
- .saturating_add(T::DbWeight::get().writes(8 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:1)
- // Storage: Common CollectionById (r:1 w:1)
- // Storage: Nonfungible TokenData (r:1 w:0)
- // Storage: Common DestroyedCollectionCount (r:1 w:1)
- // Storage: Nonfungible TokensMinted (r:0 w:1)
- // Storage: Nonfungible TokensBurnt (r:0 w:1)
- // Storage: Common AdminAmount (r:0 w:1)
- fn destroy_collection() -> Weight {
- Weight::from_ref_time(48_588_000)
- .saturating_add(T::DbWeight::get().reads(5 as u64))
- .saturating_add(T::DbWeight::get().writes(6 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:1)
- // Storage: Common CollectionProperties (r:1 w:0)
- fn change_collection_issuer() -> Weight {
- Weight::from_ref_time(25_054_000)
- .saturating_add(T::DbWeight::get().reads(3 as u64))
- .saturating_add(T::DbWeight::get().writes(1 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:1)
- // Storage: Nonfungible TokensMinted (r:1 w:0)
- // Storage: Nonfungible TokensBurnt (r:1 w:0)
- fn lock_collection() -> Weight {
- Weight::from_ref_time(26_483_000)
- .saturating_add(T::DbWeight::get().reads(5 as u64))
- .saturating_add(T::DbWeight::get().writes(1 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokensMinted (r:1 w:1)
- // Storage: Nonfungible AccountBalance (r:1 w:1)
- // Storage: Nonfungible TokenProperties (r:1 w:1)
- // Storage: Nonfungible TokenData (r:0 w:1)
- // Storage: Nonfungible Owned (r:0 w:1)
- // Storage: Nonfungible TokenAuxProperties (r:2 w:2)
- fn mint_nft(b: u32, ) -> Weight {
- Weight::from_ref_time(62_419_000)
- // Standard Error: 7_000
- .saturating_add(Weight::from_ref_time(12_325_000).saturating_mul(b as u64))
- .saturating_add(T::DbWeight::get().reads(6 as u64))
- .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(b as u64)))
- .saturating_add(T::DbWeight::get().writes(5 as u64))
- .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(b as u64)))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenData (r:1 w:1)
- // Storage: Nonfungible TokenChildren (r:1 w:0)
- // Storage: Nonfungible TokensBurnt (r:1 w:1)
- // Storage: Nonfungible AccountBalance (r:1 w:1)
- // Storage: Nonfungible Allowance (r:1 w:0)
- // Storage: Nonfungible Owned (r:0 w:1)
- // Storage: Nonfungible TokenProperties (r:0 w:1)
- fn burn_nft(b: u32, ) -> Weight {
- (Weight::from_ref_time(0))
- // Standard Error: 1_488_000
- .saturating_add(Weight::from_ref_time(298_367_000).saturating_mul(b as u64))
- .saturating_add(T::DbWeight::get().reads(9 as u64))
- .saturating_add(T::DbWeight::get().reads((4 as u64).saturating_mul(b as u64)))
- .saturating_add(T::DbWeight::get().writes(6 as u64))
- .saturating_add(T::DbWeight::get().writes((4 as u64).saturating_mul(b as u64)))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenData (r:5 w:1)
- // Storage: Nonfungible TokenProperties (r:1 w:0)
- // Storage: Nonfungible AccountBalance (r:2 w:2)
- // Storage: Nonfungible Allowance (r:1 w:0)
- // Storage: Nonfungible TokenChildren (r:0 w:1)
- // Storage: Nonfungible Owned (r:0 w:2)
- fn send() -> Weight {
- Weight::from_ref_time(81_942_000)
- .saturating_add(T::DbWeight::get().reads(12 as u64))
- .saturating_add(T::DbWeight::get().writes(6 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:2 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:2 w:0)
- // Storage: Nonfungible TokenData (r:6 w:1)
- // Storage: Nonfungible AccountBalance (r:2 w:2)
- // Storage: Nonfungible Allowance (r:1 w:0)
- // Storage: Nonfungible TokenProperties (r:1 w:1)
- // Storage: Nonfungible TokenAuxProperties (r:1 w:1)
- // Storage: Nonfungible TokenChildren (r:0 w:1)
- // Storage: Nonfungible Owned (r:0 w:2)
- fn accept_nft() -> Weight {
- Weight::from_ref_time(97_925_000)
- .saturating_add(T::DbWeight::get().reads(16 as u64))
- .saturating_add(T::DbWeight::get().writes(8 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenData (r:5 w:5)
- // Storage: Nonfungible TokenProperties (r:1 w:5)
- // Storage: Nonfungible TokenAuxProperties (r:1 w:1)
- // Storage: Nonfungible TokenChildren (r:9 w:4)
- // Storage: Nonfungible TokensBurnt (r:1 w:1)
- // Storage: Nonfungible AccountBalance (r:5 w:5)
- // Storage: Nonfungible Allowance (r:5 w:0)
- // Storage: Nonfungible Owned (r:0 w:5)
- fn reject_nft() -> Weight {
- Weight::from_ref_time(277_794_000)
- .saturating_add(T::DbWeight::get().reads(30 as u64))
- .saturating_add(T::DbWeight::get().writes(26 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenProperties (r:1 w:1)
- // Storage: Nonfungible TokenData (r:5 w:0)
- fn set_property() -> Weight {
- Weight::from_ref_time(54_657_000)
- .saturating_add(T::DbWeight::get().reads(9 as u64))
- .saturating_add(T::DbWeight::get().writes(1 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenProperties (r:1 w:1)
- // Storage: Nonfungible TokenData (r:5 w:0)
- fn set_priority() -> Weight {
- Weight::from_ref_time(55_056_000)
- .saturating_add(T::DbWeight::get().reads(9 as u64))
- .saturating_add(T::DbWeight::get().writes(1 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenData (r:5 w:0)
- // Storage: Nonfungible TokenProperties (r:1 w:1)
- // Storage: Nonfungible TokenAuxProperties (r:1 w:1)
- fn add_basic_resource() -> Weight {
- Weight::from_ref_time(61_673_000)
- .saturating_add(T::DbWeight::get().reads(10 as u64))
- .saturating_add(T::DbWeight::get().writes(2 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenData (r:5 w:0)
- // Storage: Nonfungible TokenProperties (r:1 w:1)
- // Storage: Nonfungible TokenAuxProperties (r:2 w:2)
- fn add_composable_resource() -> Weight {
- Weight::from_ref_time(67_125_000)
- .saturating_add(T::DbWeight::get().reads(11 as u64))
- .saturating_add(T::DbWeight::get().writes(3 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenData (r:5 w:0)
- // Storage: Nonfungible TokenProperties (r:1 w:1)
- // Storage: Nonfungible TokenAuxProperties (r:1 w:1)
- fn add_slot_resource() -> Weight {
- Weight::from_ref_time(69_058_000)
- .saturating_add(T::DbWeight::get().reads(10 as u64))
- .saturating_add(T::DbWeight::get().writes(2 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenAuxProperties (r:1 w:1)
- // Storage: Nonfungible TokenData (r:5 w:0)
- fn remove_resource() -> Weight {
- Weight::from_ref_time(53_427_000)
- .saturating_add(T::DbWeight::get().reads(9 as u64))
- .saturating_add(T::DbWeight::get().writes(1 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenData (r:5 w:0)
- // Storage: Nonfungible TokenAuxProperties (r:1 w:1)
- fn accept_resource() -> Weight {
- Weight::from_ref_time(50_623_000)
- .saturating_add(T::DbWeight::get().reads(9 as u64))
- .saturating_add(T::DbWeight::get().writes(1 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenData (r:5 w:0)
- // Storage: Nonfungible TokenAuxProperties (r:1 w:1)
- fn accept_resource_removal() -> Weight {
- Weight::from_ref_time(50_917_000)
- .saturating_add(T::DbWeight::get().reads(9 as u64))
- .saturating_add(T::DbWeight::get().writes(1 as u64))
- }
-}
-
-// For backwards compatibility and tests
-impl WeightInfo for () {
- // Storage: Common CreatedCollectionCount (r:1 w:1)
- // Storage: Common DestroyedCollectionCount (r:1 w:0)
- // Storage: System Account (r:2 w:2)
- // Storage: RmrkCore CollectionIndex (r:1 w:1)
- // Storage: Common CollectionPropertyPermissions (r:0 w:1)
- // Storage: Common CollectionProperties (r:0 w:1)
- // Storage: Common CollectionById (r:0 w:1)
- // Storage: RmrkCore UniqueCollectionId (r:0 w:1)
- fn create_collection() -> Weight {
- Weight::from_ref_time(49_754_000)
- .saturating_add(RocksDbWeight::get().reads(5 as u64))
- .saturating_add(RocksDbWeight::get().writes(8 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:1)
- // Storage: Common CollectionById (r:1 w:1)
- // Storage: Nonfungible TokenData (r:1 w:0)
- // Storage: Common DestroyedCollectionCount (r:1 w:1)
- // Storage: Nonfungible TokensMinted (r:0 w:1)
- // Storage: Nonfungible TokensBurnt (r:0 w:1)
- // Storage: Common AdminAmount (r:0 w:1)
- fn destroy_collection() -> Weight {
- Weight::from_ref_time(48_588_000)
- .saturating_add(RocksDbWeight::get().reads(5 as u64))
- .saturating_add(RocksDbWeight::get().writes(6 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:1)
- // Storage: Common CollectionProperties (r:1 w:0)
- fn change_collection_issuer() -> Weight {
- Weight::from_ref_time(25_054_000)
- .saturating_add(RocksDbWeight::get().reads(3 as u64))
- .saturating_add(RocksDbWeight::get().writes(1 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:1)
- // Storage: Nonfungible TokensMinted (r:1 w:0)
- // Storage: Nonfungible TokensBurnt (r:1 w:0)
- fn lock_collection() -> Weight {
- Weight::from_ref_time(26_483_000)
- .saturating_add(RocksDbWeight::get().reads(5 as u64))
- .saturating_add(RocksDbWeight::get().writes(1 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokensMinted (r:1 w:1)
- // Storage: Nonfungible AccountBalance (r:1 w:1)
- // Storage: Nonfungible TokenProperties (r:1 w:1)
- // Storage: Nonfungible TokenData (r:0 w:1)
- // Storage: Nonfungible Owned (r:0 w:1)
- // Storage: Nonfungible TokenAuxProperties (r:2 w:2)
- fn mint_nft(b: u32, ) -> Weight {
- Weight::from_ref_time(62_419_000)
- // Standard Error: 7_000
- .saturating_add(Weight::from_ref_time(12_325_000).saturating_mul(b as u64))
- .saturating_add(RocksDbWeight::get().reads(6 as u64))
- .saturating_add(RocksDbWeight::get().reads((1 as u64).saturating_mul(b as u64)))
- .saturating_add(RocksDbWeight::get().writes(5 as u64))
- .saturating_add(RocksDbWeight::get().writes((1 as u64).saturating_mul(b as u64)))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenData (r:1 w:1)
- // Storage: Nonfungible TokenChildren (r:1 w:0)
- // Storage: Nonfungible TokensBurnt (r:1 w:1)
- // Storage: Nonfungible AccountBalance (r:1 w:1)
- // Storage: Nonfungible Allowance (r:1 w:0)
- // Storage: Nonfungible Owned (r:0 w:1)
- // Storage: Nonfungible TokenProperties (r:0 w:1)
- fn burn_nft(b: u32, ) -> Weight {
- (Weight::from_ref_time(0))
- // Standard Error: 1_488_000
- .saturating_add(Weight::from_ref_time(298_367_000).saturating_mul(b as u64))
- .saturating_add(RocksDbWeight::get().reads(9 as u64))
- .saturating_add(RocksDbWeight::get().reads((4 as u64).saturating_mul(b as u64)))
- .saturating_add(RocksDbWeight::get().writes(6 as u64))
- .saturating_add(RocksDbWeight::get().writes((4 as u64).saturating_mul(b as u64)))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenData (r:5 w:1)
- // Storage: Nonfungible TokenProperties (r:1 w:0)
- // Storage: Nonfungible AccountBalance (r:2 w:2)
- // Storage: Nonfungible Allowance (r:1 w:0)
- // Storage: Nonfungible TokenChildren (r:0 w:1)
- // Storage: Nonfungible Owned (r:0 w:2)
- fn send() -> Weight {
- Weight::from_ref_time(81_942_000)
- .saturating_add(RocksDbWeight::get().reads(12 as u64))
- .saturating_add(RocksDbWeight::get().writes(6 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:2 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:2 w:0)
- // Storage: Nonfungible TokenData (r:6 w:1)
- // Storage: Nonfungible AccountBalance (r:2 w:2)
- // Storage: Nonfungible Allowance (r:1 w:0)
- // Storage: Nonfungible TokenProperties (r:1 w:1)
- // Storage: Nonfungible TokenAuxProperties (r:1 w:1)
- // Storage: Nonfungible TokenChildren (r:0 w:1)
- // Storage: Nonfungible Owned (r:0 w:2)
- fn accept_nft() -> Weight {
- Weight::from_ref_time(97_925_000)
- .saturating_add(RocksDbWeight::get().reads(16 as u64))
- .saturating_add(RocksDbWeight::get().writes(8 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenData (r:5 w:5)
- // Storage: Nonfungible TokenProperties (r:1 w:5)
- // Storage: Nonfungible TokenAuxProperties (r:1 w:1)
- // Storage: Nonfungible TokenChildren (r:9 w:4)
- // Storage: Nonfungible TokensBurnt (r:1 w:1)
- // Storage: Nonfungible AccountBalance (r:5 w:5)
- // Storage: Nonfungible Allowance (r:5 w:0)
- // Storage: Nonfungible Owned (r:0 w:5)
- fn reject_nft() -> Weight {
- Weight::from_ref_time(277_794_000)
- .saturating_add(RocksDbWeight::get().reads(30 as u64))
- .saturating_add(RocksDbWeight::get().writes(26 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenProperties (r:1 w:1)
- // Storage: Nonfungible TokenData (r:5 w:0)
- fn set_property() -> Weight {
- Weight::from_ref_time(54_657_000)
- .saturating_add(RocksDbWeight::get().reads(9 as u64))
- .saturating_add(RocksDbWeight::get().writes(1 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenProperties (r:1 w:1)
- // Storage: Nonfungible TokenData (r:5 w:0)
- fn set_priority() -> Weight {
- Weight::from_ref_time(55_056_000)
- .saturating_add(RocksDbWeight::get().reads(9 as u64))
- .saturating_add(RocksDbWeight::get().writes(1 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenData (r:5 w:0)
- // Storage: Nonfungible TokenProperties (r:1 w:1)
- // Storage: Nonfungible TokenAuxProperties (r:1 w:1)
- fn add_basic_resource() -> Weight {
- Weight::from_ref_time(61_673_000)
- .saturating_add(RocksDbWeight::get().reads(10 as u64))
- .saturating_add(RocksDbWeight::get().writes(2 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenData (r:5 w:0)
- // Storage: Nonfungible TokenProperties (r:1 w:1)
- // Storage: Nonfungible TokenAuxProperties (r:2 w:2)
- fn add_composable_resource() -> Weight {
- Weight::from_ref_time(67_125_000)
- .saturating_add(RocksDbWeight::get().reads(11 as u64))
- .saturating_add(RocksDbWeight::get().writes(3 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenData (r:5 w:0)
- // Storage: Nonfungible TokenProperties (r:1 w:1)
- // Storage: Nonfungible TokenAuxProperties (r:1 w:1)
- fn add_slot_resource() -> Weight {
- Weight::from_ref_time(69_058_000)
- .saturating_add(RocksDbWeight::get().reads(10 as u64))
- .saturating_add(RocksDbWeight::get().writes(2 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenAuxProperties (r:1 w:1)
- // Storage: Nonfungible TokenData (r:5 w:0)
- fn remove_resource() -> Weight {
- Weight::from_ref_time(53_427_000)
- .saturating_add(RocksDbWeight::get().reads(9 as u64))
- .saturating_add(RocksDbWeight::get().writes(1 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenData (r:5 w:0)
- // Storage: Nonfungible TokenAuxProperties (r:1 w:1)
- fn accept_resource() -> Weight {
- Weight::from_ref_time(50_623_000)
- .saturating_add(RocksDbWeight::get().reads(9 as u64))
- .saturating_add(RocksDbWeight::get().writes(1 as u64))
- }
- // Storage: RmrkCore UniqueCollectionId (r:1 w:0)
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: Nonfungible TokenData (r:5 w:0)
- // Storage: Nonfungible TokenAuxProperties (r:1 w:1)
- fn accept_resource_removal() -> Weight {
- Weight::from_ref_time(50_917_000)
- .saturating_add(RocksDbWeight::get().reads(9 as u64))
- .saturating_add(RocksDbWeight::get().writes(1 as u64))
- }
-}
pallets/proxy-rmrk-equip/CHANGELOG.mddiffbeforeafterboth--- a/pallets/proxy-rmrk-equip/CHANGELOG.md
+++ /dev/null
@@ -1,17 +0,0 @@
-<!-- bureaucrate goes here -->
-## [v0.1.2] 2022-08-16
-
-### Other changes
-
-- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a
-
-- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8
-
-- refactor: Remove `#[transactional]` from extrinsics 7fd36cea2f6e00c02c67ccc1de9649ae404efd31
-
-Every extrinsic now runs in transaction implicitly, and
-`#[transactional]` on pallet dispatchable is now meaningless
-
-Upstream-Change: https://github.com/paritytech/substrate/issues/10806
-
-- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b
\ No newline at end of file
pallets/proxy-rmrk-equip/Cargo.tomldiffbeforeafterboth--- a/pallets/proxy-rmrk-equip/Cargo.toml
+++ /dev/null
@@ -1,39 +0,0 @@
-[package]
-edition = "2021"
-license = "GPLv3"
-name = "pallet-rmrk-equip"
-version = "0.1.2"
-
-[dependencies]
-# Note: `package = "parity-scale-codec"` must be supplied since the `Encode` macro searches for it.
-codec = { workspace = true, package = "parity-scale-codec" }
-
-scale-info = { workspace = true }
-
-frame-benchmarking = {workspace = true, optional = true }
-frame-support = { workspace = true }
-frame-system = { workspace = true }
-pallet-common = { workspace = true }
-pallet-evm = { workspace = true }
-pallet-nonfungible = { workspace = true }
-pallet-proxy-rmrk-core = { workspace = true }
-sp-runtime = { workspace = true }
-sp-std = { workspace = true }
-up-data-structs = { workspace = true }
-
-[features]
-default = ["std"]
-runtime-benchmarks = ['frame-benchmarking', 'frame-support/runtime-benchmarks', 'frame-system/runtime-benchmarks']
-std = [
- "frame-support/std",
- "frame-system/std",
- "pallet-common/std",
- "pallet-evm/std",
- "pallet-nonfungible/std",
- "pallet-proxy-rmrk-core/std",
- "sp-runtime/std",
- "sp-std/std",
- "up-data-structs/std",
- 'frame-benchmarking/std',
-]
-try-runtime = ["frame-support/try-runtime"]
pallets/proxy-rmrk-equip/src/benchmarking.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-equip/src/benchmarking.rs
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-use sp_std::vec;
-
-use frame_benchmarking::{benchmarks, account};
-use frame_system::RawOrigin;
-use frame_support::{
- traits::{Currency, Get},
- BoundedVec,
-};
-
-use up_data_structs::*;
-
-use super::*;
-
-const SEED: u32 = 1;
-
-fn create_data<S: Get<u32>>() -> BoundedVec<u8, S> {
- vec![b'A'; S::get() as usize].try_into().expect("size == S")
-}
-
-fn create_u32_array<S: Get<u32>>() -> BoundedVec<u32, S> {
- vec![0; S::get() as usize].try_into().expect("size == S")
-}
-
-fn create_max_part(id: RmrkSlotId) -> RmrkPartType {
- RmrkPartType::SlotPart(RmrkSlotPart {
- id,
- equippable: RmrkEquippableList::Custom(create_u32_array()),
- src: create_data(),
- z: 1,
- })
-}
-
-fn create_parts_array<S: Get<u32>>(num: u32) -> BoundedVec<RmrkPartType, S> {
- let mut parts: BoundedVec<RmrkPartType, S> = vec![].try_into().expect("0 <= S");
-
- for i in 0..num {
- parts.try_push(create_max_part(i)).expect("num <= S");
- }
-
- parts
-}
-
-fn create_max_theme_property() -> RmrkThemeProperty {
- RmrkThemeProperty {
- key: create_data(),
- value: create_data(),
- }
-}
-
-fn create_theme_properties_array<S: Get<u32>>(num: u32) -> BoundedVec<RmrkThemeProperty, S> {
- vec![create_max_theme_property(); num as usize]
- .try_into()
- .expect("num <= S")
-}
-
-fn create_max_theme(name: RmrkString, props_num: u32) -> RmrkBoundedTheme {
- RmrkBoundedTheme {
- name,
- properties: create_theme_properties_array(props_num),
- inherit: false,
- }
-}
-
-benchmarks! {
- create_base {
- let b in 0..RmrkPartsLimit::get();
-
- let caller = account("caller", 0, SEED);
- <T as pallet_common::Config>::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get());
-
- let base_type = create_data();
- let symbol = create_data();
- let parts = create_parts_array(b);
- }: _(RawOrigin::Signed(caller), base_type, symbol, parts)
-
- theme_add {
- let b in 0..MaxPropertiesPerTheme::get();
-
- let caller = account("caller", 0, SEED);
- <T as pallet_common::Config>::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get());
-
- let base_type = create_data();
- let symbol = create_data();
- let parts = create_parts_array(0);
-
- <Pallet<T>>::create_base(RawOrigin::Signed(caller.clone()).into(), base_type, symbol, parts)?;
- let base_id = 1;
-
-
- let default_theme_name = b"default".to_vec().try_into().expect("default is a valid name; qed");
- let default_theme = create_max_theme(default_theme_name, 0);
-
- <Pallet<T>>::theme_add(RawOrigin::Signed(caller.clone()).into(), base_id, default_theme)?;
-
- let theme = create_max_theme(create_data(), b);
- }: _(RawOrigin::Signed(caller), base_id, theme)
-
- equippable {
- let caller = account("caller", 0, SEED);
- <T as pallet_common::Config>::Currency::deposit_creating(&caller, T::CollectionCreationPrice::get());
-
- let base_id = 1;
- let slot_id = 42;
-
- let base_type = create_data();
- let symbol = create_data();
- let parts = vec! {
- RmrkPartType::SlotPart(RmrkSlotPart {
- id: slot_id,
- equippable: RmrkEquippableList::All,
- src: create_data(),
- z: 1,
- })
- }.try_into().expect("1 <= RmrkPartsLimit");
-
- <Pallet<T>>::create_base(RawOrigin::Signed(caller.clone()).into(), base_type, symbol, parts)?;
-
- let equippables = RmrkEquippableList::Custom(create_u32_array());
- }: _(RawOrigin::Signed(caller), base_id, slot_id, equippables)
-}
pallets/proxy-rmrk-equip/src/lib.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-equip/src/lib.rs
+++ /dev/null
@@ -1,508 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-//! # RMRK Core Proxy Pallet
-//!
-//! A pallet used as proxy for RMRK Core (<https://rmrk-team.github.io/rmrk-substrate/#/pallets/rmrk-core>).
-//!
-//! - [`Config`]
-//! - [`Call`]
-//! - [`Pallet`]
-//!
-//! ## Overview
-//!
-//! The RMRK Equip Proxy pallet mirrors the functionality of RMRK Equip,
-//! binding its externalities to Unique's own underlying structure.
-//! It is purposed to mimic RMRK Equip exactly, allowing seamless integrations
-//! of solutions based on RMRK.
-//!
-//! RMRK Equip itself contains functionality to equip NFTs, and work with Bases,
-//! Parts, and Themes. See [Proxy Implementation](#proxy-implementation) for details.
-//!
-//! Equip Proxy is responsible for a more specific area of RMRK, and heavily relies on the Core.
-//! For a more foundational description of proxy implementation, please refer to [`pallet_rmrk_core`].
-//!
-//! *Note*, that while RMRK itself is subject to active development and restructuring,
-//! the proxy may be caught temporarily out of date.
-//!
-//! ### What is RMRK?
-//!
-//! RMRK is a set of NFT standards which compose several "NFT 2.0 lego" primitives.
-//! Putting these legos together allows a user to create NFT systems of arbitrary complexity.
-//!
-//! Meaning, RMRK NFTs are dynamic, able to nest into each other and form a hierarchy,
-//! make use of specific changeable and partially shared metadata in the form of resources,
-//! and more.
-//!
-//! Visit RMRK documentation and repositories to learn more:
-//! - Docs: <https://docs.rmrk.app/getting-started/>
-//! - FAQ: <https://coda.io/@rmrk/faq>
-//! - Substrate code repository: <https://github.com/rmrk-team/rmrk-substrate>
-//! - RMRK spec repository: <https://github.com/rmrk-team/rmrk-spec>
-//!
-//! ## Terminology
-//!
-//! For more information on RMRK, see RMRK's own documentation.
-//!
-//! ### Intro to RMRK
-//!
-//! - **Resource:** Additional piece of metadata of an NFT usually serving to add
-//! a piece of media on top of the root metadata (NFT's own), be it a different wing
-//! on the root template bird or something entirely unrelated.
-//!
-//! - **Base:** A list of possible "components" - Parts, a combination of which can
-//! be appended/equipped to/on an NFT.
-//!
-//! - **Part:** Something that, together with other Parts, can constitute an NFT.
-//! Parts are defined in the Base to which they belong. Parts can be either
-//! of the `slot` type or `fixed` type. Slots are intended for equippables.
-//! Note that "part of something" and "Part of a Base" can be easily confused,
-//! and so in this documentation these words are distinguished by the capital letter.
-//!
-//! - **Theme:** Named objects of variable => value pairs which get interpolated into
-//! the Base's `themable` Parts. Themes can hold any value, but are often represented
-//! in RMRK's examples as colors applied to visible Parts.
-//!
-//! ### Peculiarities in Unique
-//!
-//! - **Scoped properties:** Properties that are normally obscured from users.
-//! Their purpose is to contain structured metadata that was not included in the Unique standard
-//! for collections and tokens, meant to be operated on by proxies and other outliers.
-//! Scoped property keys are prefixed with `some-scope:`, where `some-scope` is
-//! an arbitrary keyword, like "rmrk". `:` is considered an unacceptable symbol in user-defined
-//! properties, which, along with other safeguards, makes scoped ones impossible to tamper with.
-//!
-//! - **Auxiliary properties:** A slightly different structure of properties,
-//! trading universality of use for more convenient storage, writes and access.
-//! Meant to be inaccessible to end users.
-//!
-//! ## Proxy Implementation
-//!
-//! An external user is supposed to be able to utilize this proxy as they would
-//! utilize RMRK, and get exactly the same results. Normally, Unique transactions
-//! are off-limits to RMRK collections and tokens, and vice versa. However,
-//! the information stored on chain can be freely interpreted by storage reads and Unique RPCs.
-//!
-//! ### ID Mapping
-//!
-//! RMRK's collections' IDs are counted independently of Unique's and start at 0.
-//! Note that tokens' IDs still start at 1.
-//! The collections themselves, as well as tokens, are stored as Unique collections,
-//! and thus RMRK IDs are mapped to Unique IDs (but not vice versa).
-//!
-//! ### External/Internal Collection Insulation
-//!
-//! A Unique transaction cannot target collections purposed for RMRK,
-//! and they are flagged as `external` to specify that. On the other hand,
-//! due to the mapping, RMRK transactions and RPCs simply cannot reach Unique collections.
-//!
-//! ### Native Properties
-//!
-//! Many of RMRK's native parameters are stored as scoped properties of a collection
-//! or an NFT on the chain. Scoped properties are prefixed with `rmrk:`, where `:`
-//! is an unacceptable symbol in user-defined properties, which, along with other safeguards,
-//! makes them impossible to tamper with.
-//!
-//! ### Collection and NFT Types, or Base, Parts and Themes Handling
-//!
-//! RMRK introduces the concept of a Base, which is a catalogue of Parts,
-//! possible components of an NFT. Due to its similarity with the functionality
-//! of a token collection, a Base is stored and handled as one, and the Base's Parts and Themes
-//! are this collection's NFTs. See [`CollectionType`] and [`NftType`].
-//!
-//! ## Interface
-//!
-//! ### Dispatchables
-//!
-//! - `create_base` - Create a new Base.
-//! - `theme_add` - Add a Theme to a Base.
-//! - `equippable` - Update the array of Collections allowed to be equipped to a Base's specified Slot Part.
-
-#![cfg_attr(not(feature = "std"), no_std)]
-
-use frame_support::{pallet_prelude::*, BoundedVec, dispatch::DispatchResult};
-use frame_system::{pallet_prelude::*, ensure_signed};
-use sp_runtime::DispatchError;
-use up_data_structs::*;
-use pallet_common::{Pallet as PalletCommon, Error as CommonError};
-use pallet_proxy_rmrk_core::{
- Pallet as PalletCore, Error as CoreError,
- misc::{self, *},
- property::RmrkProperty::*,
-};
-use pallet_nonfungible::{Pallet as PalletNft, NonfungibleHandle};
-use pallet_evm::account::CrossAccountId;
-use weights::WeightInfo;
-
-pub use pallet::*;
-
-#[cfg(feature = "runtime-benchmarks")]
-pub mod benchmarking;
-pub mod rpc;
-pub mod weights;
-
-pub type SelfWeightOf<T> = <T as Config>::WeightInfo;
-
-#[frame_support::pallet]
-pub mod pallet {
- use super::*;
-
- #[pallet::config]
- pub trait Config: frame_system::Config + pallet_proxy_rmrk_core::Config {
- /// Overarching event type.
- type RuntimeEvent: From<Event<Self>> + IsType<<Self as frame_system::Config>::RuntimeEvent>;
-
- /// The weight information of this pallet.
- type WeightInfo: WeightInfo;
- }
-
- /// Map of a Base ID and a Part ID to an NFT in the Base collection serving as the Part.
- #[pallet::storage]
- #[pallet::getter(fn internal_part_id)]
- pub type InernalPartId<T: Config> =
- StorageDoubleMap<_, Twox64Concat, CollectionId, Twox64Concat, RmrkPartId, TokenId>;
-
- /// Checkmark that a Base has a Theme NFT named "default".
- #[pallet::storage]
- #[pallet::getter(fn base_has_default_theme)]
- pub type BaseHasDefaultTheme<T: Config> =
- StorageMap<_, Twox64Concat, CollectionId, bool, ValueQuery>;
-
- #[pallet::pallet]
- #[pallet::generate_store(pub(super) trait Store)]
- pub struct Pallet<T>(_);
-
- #[pallet::event]
- #[pallet::generate_deposit(pub(super) fn deposit_event)]
- pub enum Event<T: Config> {
- BaseCreated {
- issuer: T::AccountId,
- base_id: RmrkBaseId,
- },
- EquippablesUpdated {
- base_id: RmrkBaseId,
- slot_id: RmrkSlotId,
- },
- }
-
- #[pallet::error]
- pub enum Error<T> {
- /// No permission to perform action.
- PermissionError,
- /// Could not find an ID for a Base collection. It is likely there were too many collections created on the chain, causing an overflow.
- NoAvailableBaseId,
- /// Could not find a suitable ID for a Part, likely too many Part tokens were created in the Base, causing an overflow
- NoAvailablePartId,
- /// Base collection linked to this ID does not exist.
- BaseDoesntExist,
- /// No Theme named "default" is associated with the Base.
- NeedsDefaultThemeFirst,
- /// Part linked to this ID does not exist.
- PartDoesntExist,
- /// Cannot assign equippables to a fixed Part.
- NoEquippableOnFixedPart,
- }
-
- #[pallet::call]
- impl<T: Config> Pallet<T> {
- /// Create a new Base.
- ///
- /// Modeled after the [Base interaction](https://github.com/rmrk-team/rmrk-spec/blob/master/standards/rmrk2.0.0/interactions/base.md)
- ///
- /// # Permissions
- /// - Anyone - will be assigned as the issuer of the Base.
- ///
- /// # Arguments:
- /// - `origin`: Caller, will be assigned as the issuer of the Base
- /// - `base_type`: Arbitrary media type, e.g. "svg".
- /// - `symbol`: Arbitrary client-chosen symbol.
- /// - `parts`: Array of Fixed and Slot Parts composing the Base,
- /// confined in length by [`RmrkPartsLimit`](up_data_structs::RmrkPartsLimit).
- #[pallet::call_index(0)]
- #[pallet::weight(<SelfWeightOf<T>>::create_base(parts.len() as u32))]
- pub fn create_base(
- origin: OriginFor<T>,
- base_type: RmrkString,
- symbol: RmrkBaseSymbol,
- parts: BoundedVec<RmrkPartType, RmrkPartsLimit>,
- ) -> DispatchResult {
- let sender = ensure_signed(origin)?;
- let cross_sender = T::CrossAccountId::from_sub(sender.clone());
-
- let data = CreateCollectionData {
- limits: None,
- token_prefix: symbol
- .into_inner()
- .try_into()
- .map_err(|_| <CommonError<T>>::CollectionTokenPrefixLimitExceeded)?,
- ..Default::default()
- };
-
- let collection_id_res = <PalletNft<T>>::init_collection(
- cross_sender.clone(),
- cross_sender.clone(),
- data,
- up_data_structs::CollectionFlags {
- external: true,
- ..Default::default()
- },
- );
-
- if let Err(DispatchError::Arithmetic(_)) = &collection_id_res {
- return Err(<Error<T>>::NoAvailableBaseId.into());
- }
-
- let collection_id = collection_id_res?;
-
- <PalletCommon<T>>::set_scoped_collection_properties(
- collection_id,
- PropertyScope::Rmrk,
- [
- <PalletCore<T>>::encode_rmrk_property(
- CollectionType,
- &misc::CollectionType::Base,
- )?,
- <PalletCore<T>>::encode_rmrk_property(BaseType, &base_type)?,
- ]
- .into_iter(),
- )?;
-
- let collection = <PalletCore<T>>::get_nft_collection(collection_id)?;
-
- for part in parts {
- Self::create_part(&cross_sender, &collection, part)?;
- }
-
- Self::deposit_event(Event::BaseCreated {
- issuer: sender,
- base_id: collection_id.0,
- });
-
- Ok(())
- }
-
- /// Add a Theme to a Base.
- /// A Theme named "default" is required prior to adding other Themes.
- ///
- /// Modeled after [Themeadd interaction](https://github.com/rmrk-team/rmrk-spec/blob/master/standards/rmrk2.0.0/interactions/themeadd.md).
- ///
- /// # Permissions:
- /// - Base issuer
- ///
- /// # Arguments:
- /// - `origin`: sender of the transaction
- /// - `base_id`: Base ID containing the Theme to be updated.
- /// - `theme`: Theme to add to the Base. A Theme has a name and properties, which are an
- /// array of [key, value, inherit].
- /// - `key`: Arbitrary BoundedString, defined by client.
- /// - `value`: Arbitrary BoundedString, defined by client.
- /// - `inherit`: Optional bool.
- #[pallet::call_index(1)]
- #[pallet::weight(<SelfWeightOf<T>>::theme_add(theme.properties.len() as u32))]
- pub fn theme_add(
- origin: OriginFor<T>,
- base_id: RmrkBaseId,
- theme: RmrkBoundedTheme,
- ) -> DispatchResult {
- let sender = ensure_signed(origin)?;
-
- let sender = T::CrossAccountId::from_sub(sender);
- let owner = &sender;
-
- let collection_id: CollectionId = base_id.into();
-
- let collection = Self::get_base(collection_id)?;
-
- if theme.name.as_slice() == b"default" {
- <BaseHasDefaultTheme<T>>::insert(collection_id, true);
- } else if !Self::base_has_default_theme(collection_id) {
- return Err(<Error<T>>::NeedsDefaultThemeFirst.into());
- }
-
- let token_id = <PalletCore<T>>::create_nft(
- &sender,
- owner,
- &collection,
- [
- <PalletCore<T>>::encode_rmrk_property(TokenType, &NftType::Theme)?,
- <PalletCore<T>>::encode_rmrk_property(ThemeName, &theme.name)?,
- <PalletCore<T>>::encode_rmrk_property(ThemeInherit, &theme.inherit)?,
- ]
- .into_iter(),
- )
- .map_err(|_| <Error<T>>::PermissionError)?;
-
- for property in theme.properties {
- <PalletNft<T>>::set_scoped_token_property(
- collection_id,
- token_id,
- PropertyScope::Rmrk,
- <PalletCore<T>>::encode_rmrk_property(
- UserProperty(property.key.as_slice()),
- &property.value,
- )?,
- )?;
- }
-
- Ok(())
- }
-
- /// Update the array of Collections allowed to be equipped to a Base's specified Slot Part.
- ///
- /// Modeled after [equippable interaction](https://github.com/rmrk-team/rmrk-spec/blob/master/standards/rmrk2.0.0/interactions/equippable.md).
- ///
- /// # Permissions:
- /// - Base issuer
- ///
- /// # Arguments:
- /// - `origin`: sender of the transaction
- /// - `base_id`: Base containing the Slot Part to be updated.
- /// - `slot_id`: Slot Part whose Equippable List is being updated .
- /// - `equippables`: List of equippables that will override the current Equippables list.
- #[pallet::call_index(2)]
- #[pallet::weight(<SelfWeightOf<T>>::equippable())]
- pub fn equippable(
- origin: OriginFor<T>,
- base_id: RmrkBaseId,
- slot_id: RmrkSlotId,
- equippables: RmrkEquippableList,
- ) -> DispatchResult {
- let sender = ensure_signed(origin)?;
-
- let base_collection_id = base_id.into();
- let collection = Self::get_base(base_collection_id)?;
-
- <PalletCore<T>>::check_collection_owner(
- &collection,
- &T::CrossAccountId::from_sub(sender),
- )
- .map_err(|err| {
- if err == <CoreError<T>>::NoPermission.into() {
- <Error<T>>::PermissionError.into()
- } else {
- err
- }
- })?;
-
- let part_id = Self::internal_part_id(base_collection_id, slot_id)
- .ok_or(<Error<T>>::PartDoesntExist)?;
-
- let nft_type = <PalletCore<T>>::get_nft_type(base_collection_id, part_id)
- .map_err(|_| <Error<T>>::PartDoesntExist)?;
-
- match nft_type {
- NftType::Regular | NftType::Theme => return Err(<Error<T>>::PermissionError.into()),
- NftType::FixedPart => return Err(<Error<T>>::NoEquippableOnFixedPart.into()),
- NftType::SlotPart => {
- <PalletNft<T>>::set_scoped_token_property(
- base_collection_id,
- part_id,
- PropertyScope::Rmrk,
- <PalletCore<T>>::encode_rmrk_property(EquippableList, &equippables)?,
- )?;
- }
- }
-
- Self::deposit_event(Event::EquippablesUpdated { base_id, slot_id });
-
- Ok(())
- }
- }
-}
-
-impl<T: Config> Pallet<T> {
- /// Create (or overwrite) a Part in a Base.
- /// The Part and the Base are represented as an NFT and a Collection.
- fn create_part(
- sender: &T::CrossAccountId,
- collection: &NonfungibleHandle<T>,
- part: RmrkPartType,
- ) -> DispatchResult {
- let owner = sender;
-
- let part_id = part.id();
- let src = part.src();
- let z_index = part.z_index();
-
- let nft_type = match part {
- RmrkPartType::FixedPart(_) => NftType::FixedPart,
- RmrkPartType::SlotPart(_) => NftType::SlotPart,
- };
-
- let token_id = match Self::internal_part_id(collection.id, part_id) {
- Some(token_id) => token_id,
- None => {
- let token_id =
- <PalletCore<T>>::create_nft(sender, owner, collection, [].into_iter())
- .map_err(|err| match err {
- DispatchError::Arithmetic(_) => <Error<T>>::NoAvailablePartId.into(),
- err => err,
- })?;
-
- <InernalPartId<T>>::insert(collection.id, part_id, token_id);
-
- <PalletNft<T>>::set_scoped_token_property(
- collection.id,
- token_id,
- PropertyScope::Rmrk,
- <PalletCore<T>>::encode_rmrk_property(ExternalPartId, &part_id)?,
- )?;
-
- token_id
- }
- };
-
- <PalletNft<T>>::set_scoped_token_properties(
- collection.id,
- token_id,
- PropertyScope::Rmrk,
- [
- <PalletCore<T>>::encode_rmrk_property(TokenType, &nft_type)?,
- <PalletCore<T>>::encode_rmrk_property(Src, &src)?,
- <PalletCore<T>>::encode_rmrk_property(ZIndex, &z_index)?,
- ]
- .into_iter(),
- )?;
-
- if let RmrkPartType::SlotPart(part) = part {
- <PalletNft<T>>::set_scoped_token_property(
- collection.id,
- token_id,
- PropertyScope::Rmrk,
- <PalletCore<T>>::encode_rmrk_property(EquippableList, &part.equippable)?,
- )?;
- }
-
- Ok(())
- }
-
- /// Ensure that the collection under the Base ID is a Base collection,
- /// and fetch it.
- fn get_base(base_id: CollectionId) -> Result<NonfungibleHandle<T>, DispatchError> {
- let collection =
- <PalletCore<T>>::get_typed_nft_collection(base_id, misc::CollectionType::Base)
- .map_err(|err| {
- if err == <CoreError<T>>::CollectionUnknown.into() {
- <Error<T>>::BaseDoesntExist.into()
- } else {
- err
- }
- })?;
- collection.check_is_external()?;
-
- Ok(collection)
- }
-}
pallets/proxy-rmrk-equip/src/rpc.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-equip/src/rpc.rs
+++ /dev/null
@@ -1,208 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-//! Realizations of RMRK RPCs (remote procedure calls) related to the Equip pallet.
-
-use super::*;
-use pallet_proxy_rmrk_core::{misc, property::*};
-use sp_std::vec::Vec;
-
-/// Get base info by its ID.
-pub fn base<T: Config>(
- base_id: RmrkBaseId,
-) -> Result<Option<RmrkBaseInfo<T::AccountId>>, DispatchError> {
- let (collection, collection_id) =
- match <PalletCore<T>>::get_typed_nft_collection_mapped(base_id, misc::CollectionType::Base)
- {
- Ok(c) => c,
- Err(_) => return Ok(None),
- };
-
- Ok(Some(RmrkBaseInfo {
- issuer: collection.owner.clone(),
- base_type: <PalletCore<T>>::get_collection_property_decoded(
- collection_id,
- RmrkProperty::BaseType,
- )?,
- symbol: <PalletCore<T>>::rebind(&collection.token_prefix)?,
- }))
-}
-
-/// Get all parts of a base.
-pub fn base_parts<T: Config>(base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {
- use pallet_common::CommonCollectionOperations;
-
- let (collection, collection_id) =
- match <PalletCore<T>>::get_typed_nft_collection_mapped(base_id, misc::CollectionType::Base)
- {
- Ok(c) => c,
- Err(_) => return Ok(Vec::new()),
- };
-
- let parts = collection
- .collection_tokens()
- .into_iter()
- .filter_map(|token_id| {
- let nft_type = <PalletCore<T>>::get_nft_type(collection_id, token_id).ok()?;
-
- match nft_type {
- NftType::FixedPart => Some(RmrkPartType::FixedPart(RmrkFixedPart {
- id: <PalletCore<T>>::get_nft_property_decoded(
- collection_id,
- token_id,
- RmrkProperty::ExternalPartId,
- )
- .ok()?,
- src: <PalletCore<T>>::get_nft_property_decoded(
- collection_id,
- token_id,
- RmrkProperty::Src,
- )
- .ok()?,
- z: <PalletCore<T>>::get_nft_property_decoded(
- collection_id,
- token_id,
- RmrkProperty::ZIndex,
- )
- .ok()?,
- })),
- NftType::SlotPart => Some(RmrkPartType::SlotPart(RmrkSlotPart {
- id: <PalletCore<T>>::get_nft_property_decoded(
- collection_id,
- token_id,
- RmrkProperty::ExternalPartId,
- )
- .ok()?,
- src: <PalletCore<T>>::get_nft_property_decoded(
- collection_id,
- token_id,
- RmrkProperty::Src,
- )
- .ok()?,
- z: <PalletCore<T>>::get_nft_property_decoded(
- collection_id,
- token_id,
- RmrkProperty::ZIndex,
- )
- .ok()?,
- equippable: <PalletCore<T>>::get_nft_property_decoded(
- collection_id,
- token_id,
- RmrkProperty::EquippableList,
- )
- .ok()?,
- })),
- _ => None,
- }
- })
- .collect();
-
- Ok(parts)
-}
-
-/// Get the theme names belonging to a base.
-pub fn theme_names<T: Config>(base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {
- use pallet_common::CommonCollectionOperations;
-
- let (collection, collection_id) =
- match <PalletCore<T>>::get_typed_nft_collection_mapped(base_id, misc::CollectionType::Base)
- {
- Ok(c) => c,
- Err(_) => return Ok(Vec::new()),
- };
-
- let theme_names = collection
- .collection_tokens()
- .iter()
- .filter_map(|token_id| {
- let nft_type = <PalletCore<T>>::get_nft_type(collection_id, *token_id).ok()?;
-
- match nft_type {
- NftType::Theme => <PalletCore<T>>::get_nft_property_decoded(
- collection_id,
- *token_id,
- RmrkProperty::ThemeName,
- )
- .ok(),
- _ => None,
- }
- })
- .collect();
-
- Ok(theme_names)
-}
-
-/// Get theme info, including properties, optionally limited to the provided keys.
-pub fn theme<T: Config>(
- base_id: RmrkBaseId,
- theme_name: RmrkThemeName,
- filter_keys: Option<Vec<RmrkPropertyKey>>,
-) -> Result<Option<RmrkTheme>, DispatchError> {
- use pallet_common::CommonCollectionOperations;
-
- let (collection, collection_id) =
- match <PalletCore<T>>::get_typed_nft_collection_mapped(base_id, misc::CollectionType::Base)
- {
- Ok(c) => c,
- Err(_) => return Ok(None),
- };
-
- let theme_info = collection
- .collection_tokens()
- .into_iter()
- .find_map(|token_id| {
- <PalletCore<T>>::ensure_nft_type(collection_id, token_id, NftType::Theme).ok()?;
-
- let name: RmrkString = <PalletCore<T>>::get_nft_property_decoded(
- collection_id,
- token_id,
- RmrkProperty::ThemeName,
- )
- .ok()?;
-
- if name == theme_name {
- Some((name, token_id))
- } else {
- None
- }
- });
-
- let (name, theme_id) = match theme_info {
- Some((name, theme_id)) => (name, theme_id),
- None => return Ok(None),
- };
-
- let properties = <PalletCore<T>>::filter_user_properties(
- collection_id,
- Some(theme_id),
- filter_keys,
- |key, value| RmrkThemeProperty { key, value },
- )?;
-
- let inherit = <PalletCore<T>>::get_nft_property_decoded(
- collection_id,
- theme_id,
- RmrkProperty::ThemeInherit,
- )?;
-
- let theme = RmrkTheme {
- name,
- properties,
- inherit,
- };
-
- Ok(Some(theme))
-}
pallets/proxy-rmrk-equip/src/weights.rsdiffbeforeafterboth--- a/pallets/proxy-rmrk-equip/src/weights.rs
+++ /dev/null
@@ -1,138 +0,0 @@
-// Template adopted from https://github.com/paritytech/substrate/blob/master/.maintain/frame-weight-template.hbs
-
-//! Autogenerated weights for pallet_proxy_rmrk_equip
-//!
-//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev
-//! DATE: 2022-08-15, STEPS: `50`, REPEAT: 80, LOW RANGE: `[]`, HIGH RANGE: `[]`
-//! EXECUTION: None, WASM-EXECUTION: Compiled, CHAIN: None, DB CACHE: 1024
-
-// Executed Command:
-// target/release/unique-collator
-// benchmark
-// pallet
-// --pallet
-// pallet-proxy-rmrk-equip
-// --wasm-execution
-// compiled
-// --extrinsic
-// *
-// --template
-// .maintain/frame-weight-template.hbs
-// --steps=50
-// --repeat=80
-// --heap-pages=4096
-// --output=./pallets/proxy-rmrk-equip/src/weights.rs
-
-#![cfg_attr(rustfmt, rustfmt_skip)]
-#![allow(unused_parens)]
-#![allow(unused_imports)]
-#![allow(clippy::unnecessary_cast)]
-
-use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}};
-use sp_std::marker::PhantomData;
-
-/// Weight functions needed for pallet_proxy_rmrk_equip.
-pub trait WeightInfo {
- fn create_base(b: u32, ) -> Weight;
- fn theme_add(b: u32, ) -> Weight;
- fn equippable() -> Weight;
-}
-
-/// Weights for pallet_proxy_rmrk_equip using the Substrate node and recommended hardware.
-pub struct SubstrateWeight<T>(PhantomData<T>);
-impl<T: frame_system::Config> WeightInfo for SubstrateWeight<T> {
- // Storage: Common CreatedCollectionCount (r:1 w:1)
- // Storage: Common DestroyedCollectionCount (r:1 w:0)
- // Storage: System Account (r:2 w:2)
- // Storage: Common CollectionPropertyPermissions (r:0 w:1)
- // Storage: Common CollectionProperties (r:0 w:1)
- // Storage: Common CollectionById (r:0 w:1)
- // Storage: RmrkEquip InernalPartId (r:1 w:1)
- // Storage: Nonfungible TokensMinted (r:1 w:1)
- // Storage: Nonfungible AccountBalance (r:1 w:1)
- // Storage: Nonfungible TokenProperties (r:1 w:1)
- // Storage: Nonfungible TokenData (r:0 w:1)
- // Storage: Nonfungible Owned (r:0 w:1)
- fn create_base(b: u32, ) -> Weight {
- Weight::from_ref_time(58_417_000)
- // Standard Error: 27_000
- .saturating_add(Weight::from_ref_time(20_439_000).saturating_mul(b as u64))
- .saturating_add(T::DbWeight::get().reads(6 as u64))
- .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(b as u64)))
- .saturating_add(T::DbWeight::get().writes(8 as u64))
- .saturating_add(T::DbWeight::get().writes((4 as u64).saturating_mul(b as u64)))
- }
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: RmrkEquip BaseHasDefaultTheme (r:1 w:0)
- // Storage: Nonfungible TokensMinted (r:1 w:1)
- // Storage: Nonfungible AccountBalance (r:1 w:1)
- // Storage: Nonfungible TokenProperties (r:1 w:1)
- // Storage: Nonfungible TokenData (r:0 w:1)
- // Storage: Nonfungible Owned (r:0 w:1)
- fn theme_add(b: u32, ) -> Weight {
- Weight::from_ref_time(46_005_000)
- // Standard Error: 42_000
- .saturating_add(Weight::from_ref_time(2_922_000).saturating_mul(b as u64))
- .saturating_add(T::DbWeight::get().reads(6 as u64))
- .saturating_add(T::DbWeight::get().writes(5 as u64))
- }
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: RmrkEquip InernalPartId (r:1 w:0)
- // Storage: Nonfungible TokenProperties (r:1 w:1)
- fn equippable() -> Weight {
- Weight::from_ref_time(32_526_000)
- .saturating_add(T::DbWeight::get().reads(4 as u64))
- .saturating_add(T::DbWeight::get().writes(1 as u64))
- }
-}
-
-// For backwards compatibility and tests
-impl WeightInfo for () {
- // Storage: Common CreatedCollectionCount (r:1 w:1)
- // Storage: Common DestroyedCollectionCount (r:1 w:0)
- // Storage: System Account (r:2 w:2)
- // Storage: Common CollectionPropertyPermissions (r:0 w:1)
- // Storage: Common CollectionProperties (r:0 w:1)
- // Storage: Common CollectionById (r:0 w:1)
- // Storage: RmrkEquip InernalPartId (r:1 w:1)
- // Storage: Nonfungible TokensMinted (r:1 w:1)
- // Storage: Nonfungible AccountBalance (r:1 w:1)
- // Storage: Nonfungible TokenProperties (r:1 w:1)
- // Storage: Nonfungible TokenData (r:0 w:1)
- // Storage: Nonfungible Owned (r:0 w:1)
- fn create_base(b: u32, ) -> Weight {
- Weight::from_ref_time(58_417_000)
- // Standard Error: 27_000
- .saturating_add(Weight::from_ref_time(20_439_000).saturating_mul(b as u64))
- .saturating_add(RocksDbWeight::get().reads(6 as u64))
- .saturating_add(RocksDbWeight::get().reads((2 as u64).saturating_mul(b as u64)))
- .saturating_add(RocksDbWeight::get().writes(8 as u64))
- .saturating_add(RocksDbWeight::get().writes((4 as u64).saturating_mul(b as u64)))
- }
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: RmrkEquip BaseHasDefaultTheme (r:1 w:0)
- // Storage: Nonfungible TokensMinted (r:1 w:1)
- // Storage: Nonfungible AccountBalance (r:1 w:1)
- // Storage: Nonfungible TokenProperties (r:1 w:1)
- // Storage: Nonfungible TokenData (r:0 w:1)
- // Storage: Nonfungible Owned (r:0 w:1)
- fn theme_add(b: u32, ) -> Weight {
- Weight::from_ref_time(46_005_000)
- // Standard Error: 42_000
- .saturating_add(Weight::from_ref_time(2_922_000).saturating_mul(b as u64))
- .saturating_add(RocksDbWeight::get().reads(6 as u64))
- .saturating_add(RocksDbWeight::get().writes(5 as u64))
- }
- // Storage: Common CollectionProperties (r:1 w:0)
- // Storage: Common CollectionById (r:1 w:0)
- // Storage: RmrkEquip InernalPartId (r:1 w:0)
- // Storage: Nonfungible TokenProperties (r:1 w:1)
- fn equippable() -> Weight {
- Weight::from_ref_time(32_526_000)
- .saturating_add(RocksDbWeight::get().reads(4 as u64))
- .saturating_add(RocksDbWeight::get().writes(1 as u64))
- }
-}
pallets/refungible/src/erc.rsdiffbeforeafterboth--- a/pallets/refungible/src/erc.rs
+++ b/pallets/refungible/src/erc.rs
@@ -48,8 +48,8 @@
};
use crate::{
- AccountBalance, Balance, Config, CreateItemData, Pallet, RefungibleHandle, SelfWeightOf,
- TokenProperties, TokensMinted, TotalSupply, weights::WeightInfo,
+ AccountBalance, Balance, Config, CreateItemData, Pallet, RefungibleHandle,
+ TokenProperties, TokensMinted, TotalSupply, SelfWeightOf, weights::WeightInfo,
};
frontier_contract! {
pallets/refungible/src/erc_token.rsdiffbeforeafterboth--- a/pallets/refungible/src/erc_token.rs
+++ b/pallets/refungible/src/erc_token.rs
@@ -28,6 +28,7 @@
use pallet_common::{
erc::{CommonEvmHandler, PrecompileResult},
eth::{collection_id_to_address, CrossAddress},
+ CommonWeightInfo,
};
use pallet_evm::{account::CrossAccountId, PrecompileHandle};
use pallet_evm_coder_substrate::{
@@ -39,7 +40,7 @@
use sp_core::U256;
use up_data_structs::TokenId;
-use crate::{Allowance, Balance, Config, Pallet, RefungibleHandle, TotalSupply};
+use crate::{Allowance, Balance, Config, Pallet, RefungibleHandle, TotalSupply, common::CommonWeights, SelfWeightOf, weights::WeightInfo};
/// Refungible token handle contains information about token's collection and id
///
primitives/data-structs/Cargo.tomldiffbeforeafterboth--- a/primitives/data-structs/Cargo.toml
+++ b/primitives/data-structs/Cargo.toml
@@ -15,7 +15,6 @@
derivative = { workspace = true }
frame-support = { workspace = true }
pallet-evm = { workspace = true }
-rmrk-traits = { workspace = true }
scale-info = { workspace = true }
serde = { workspace = true, optional = true }
sp-core = { workspace = true }
@@ -33,7 +32,6 @@
"codec/std",
"frame-support/std",
"pallet-evm/std",
- "rmrk-traits/std",
"serde/std",
"serde1",
"sp-core/std",
primitives/data-structs/src/lib.rsdiffbeforeafterboth1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! # Primitives crate.18//!19//! This crate contains types, traits and constants.2021#![cfg_attr(not(feature = "std"), no_std)]2223use core::{24 convert::{TryFrom, TryInto},25 fmt,26};27use frame_support::{28 storage::{bounded_btree_map::BoundedBTreeMap, bounded_btree_set::BoundedBTreeSet},29 traits::Get,30 parameter_types,31};3233#[cfg(feature = "serde")]34use serde::{Serialize, Deserialize};3536use sp_core::U256;37use sp_runtime::{ArithmeticError, sp_std::prelude::Vec, Permill};38use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};39use bondrewd::Bitfields;40use frame_support::{BoundedVec, traits::ConstU32};41use derivative::Derivative;42use scale_info::TypeInfo;4344// RMRK45use rmrk_traits::{46 CollectionInfo, NftInfo, ResourceInfo, PropertyInfo, BaseInfo, PartType, Theme, ThemeProperty,47 ResourceTypes, BasicResource, ComposableResource, SlotResource, EquippableList,48};49pub use rmrk_traits::{50 primitives::{51 CollectionId as RmrkCollectionId, NftId as RmrkNftId, BaseId as RmrkBaseId,52 SlotId as RmrkSlotId, PartId as RmrkPartId, ResourceId as RmrkResourceId,53 },54 NftChild as RmrkNftChild, AccountIdOrCollectionNftTuple as RmrkAccountIdOrCollectionNftTuple,55 FixedPart as RmrkFixedPart, SlotPart as RmrkSlotPart,56};5758mod bondrewd_codec;59mod bounded;60pub mod budget;61pub mod mapping;62mod migration;6364/// Maximum of decimal points.65pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;6667/// Maximum pieces for refungible token.68pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;69pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;7071/// Maximum tokens for user.72pub const MAX_TOKEN_OWNERSHIP: u32 = if cfg!(not(feature = "limit-testing")) {73 100_00074} else {75 1076};7778/// Maximum for collections can be created.79pub const COLLECTION_NUMBER_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {80 100_00081} else {82 1083};8485/// Maximum for various custom data of token.86pub const CUSTOM_DATA_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {87 204888} else {89 1090};9192/// Maximum admins per collection.93pub const COLLECTION_ADMINS_LIMIT: u32 = 5;9495/// Maximum tokens per collection.96pub const COLLECTION_TOKEN_LIMIT: u32 = u32::MAX;9798/// Maximum tokens per account.99pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {100 1_000_000101} else {102 10103};104105/// Default timeout for transfer sponsoring NFT item.106pub const NFT_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;107/// Default timeout for transfer sponsoring fungible item.108pub const FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;109/// Default timeout for transfer sponsoring refungible item.110pub const REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;111112/// Default timeout for sponsored approving.113pub const SPONSOR_APPROVE_TIMEOUT: u32 = 5;114115// Schema limits116pub const OFFCHAIN_SCHEMA_LIMIT: u32 = 8192;117pub const VARIABLE_ON_CHAIN_SCHEMA_LIMIT: u32 = 8192;118pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 32768;119120// TODO: not used. Delete?121pub const COLLECTION_FIELD_LIMIT: u32 = CONST_ON_CHAIN_SCHEMA_LIMIT;122123/// Maximal length of a collection name.124pub const MAX_COLLECTION_NAME_LENGTH: u32 = 64;125126/// Maximal length of a collection description.127pub const MAX_COLLECTION_DESCRIPTION_LENGTH: u32 = 256;128129/// Maximal length of a token prefix.130pub const MAX_TOKEN_PREFIX_LENGTH: u32 = 16;131132/// Maximal length of a property key.133pub const MAX_PROPERTY_KEY_LENGTH: u32 = 256;134135/// Maximal length of a property value.136pub const MAX_PROPERTY_VALUE_LENGTH: u32 = 32768;137138/// A maximum number of token properties.139pub const MAX_PROPERTIES_PER_ITEM: u32 = 64;140141/// Maximal lenght of extended property value.142pub const MAX_AUX_PROPERTY_VALUE_LENGTH: u32 = 2048;143144/// Maximum size for all collection properties.145pub const MAX_COLLECTION_PROPERTIES_SIZE: u32 = 40960;146147/// Maximum size of all token properties.148pub const MAX_TOKEN_PROPERTIES_SIZE: u32 = 32768;149150/// How much items can be created per single151/// create_many call.152pub const MAX_ITEMS_PER_BATCH: u32 = 200;153154/// Used for limit bounded types of token custom data.155pub type CustomDataLimit = ConstU32<CUSTOM_DATA_LIMIT>;156157/// Collection id.158#[derive(159 Encode,160 Decode,161 PartialEq,162 Eq,163 PartialOrd,164 Ord,165 Clone,166 Copy,167 Debug,168 Default,169 TypeInfo,170 MaxEncodedLen,171)]172#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]173pub struct CollectionId(pub u32);174impl EncodeLike<u32> for CollectionId {}175impl EncodeLike<CollectionId> for u32 {}176177/// Token id.178#[derive(179 Encode,180 Decode,181 PartialEq,182 Eq,183 PartialOrd,184 Ord,185 Clone,186 Copy,187 Debug,188 Default,189 TypeInfo,190 MaxEncodedLen,191)]192#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]193pub struct TokenId(pub u32);194impl EncodeLike<u32> for TokenId {}195impl EncodeLike<TokenId> for u32 {}196197impl TokenId {198 /// Try to get next token id.199 ///200 /// If next id cause overflow, then [`ArithmeticError::Overflow`] returned.201 pub fn try_next(self) -> Result<TokenId, ArithmeticError> {202 self.0203 .checked_add(1)204 .ok_or(ArithmeticError::Overflow)205 .map(Self)206 }207}208209impl From<TokenId> for U256 {210 fn from(t: TokenId) -> Self {211 t.0.into()212 }213}214215impl TryFrom<U256> for TokenId {216 type Error = &'static str;217218 fn try_from(value: U256) -> Result<Self, Self::Error> {219 Ok(TokenId(value.try_into().map_err(|_| "too large token id")?))220 }221}222223/// Token data.224#[struct_versioning::versioned(version = 2, upper)]225#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]226#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]227pub struct TokenData<CrossAccountId> {228 /// Properties of token.229 pub properties: Vec<Property>,230231 /// Token owner.232 pub owner: Option<CrossAccountId>,233234 /// Token pieces.235 #[version(2.., upper(0))]236 pub pieces: u128,237}238239// TODO: unused type240pub struct OverflowError;241impl From<OverflowError> for &'static str {242 fn from(_: OverflowError) -> Self {243 "overflow occured"244 }245}246247/// Alias for decimal points type.248pub type DecimalPoints = u8;249250/// Collection mode.251///252/// Collection can represent various types of tokens.253/// Each collection can contain only one type of tokens at a time.254/// This type helps to understand which tokens the collection contains.255#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]256#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]257pub enum CollectionMode {258 /// Non fungible tokens.259 NFT,260 /// Fungible tokens.261 Fungible(DecimalPoints),262 /// Refungible tokens.263 ReFungible,264}265266impl CollectionMode {267 /// Get collection mod as number.268 pub fn id(&self) -> u8 {269 match self {270 CollectionMode::NFT => 1,271 CollectionMode::Fungible(_) => 2,272 CollectionMode::ReFungible => 3,273 }274 }275}276277// TODO: unused trait278pub trait SponsoringResolve<AccountId, Call> {279 fn resolve(who: &AccountId, call: &Call) -> Option<AccountId>;280}281282/// Access mode for some token operations.283#[derive(Encode, Decode, Eq, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]284#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]285pub enum AccessMode {286 /// Access grant for owner and admins. Used as default.287 Normal,288 /// Like a [`Normal`](AccessMode::Normal) but also users in allow list.289 AllowList,290}291impl Default for AccessMode {292 fn default() -> Self {293 Self::Normal294 }295}296297// TODO: remove in future.298#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]299#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]300pub enum SchemaVersion {301 ImageURL,302 Unique,303}304impl Default for SchemaVersion {305 fn default() -> Self {306 Self::ImageURL307 }308}309310// TODO: unused type311#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, TypeInfo)]312#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]313pub struct Ownership<AccountId> {314 pub owner: AccountId,315 pub fraction: u128,316}317318/// The state of collection sponsorship.319#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]320#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]321pub enum SponsorshipState<AccountId> {322 /// The fees are applied to the transaction sender.323 Disabled,324 /// The sponsor is under consideration. Until the sponsor gives his consent,325 /// the fee will still be charged to sender.326 Unconfirmed(AccountId),327 /// Transactions are sponsored by specified account.328 Confirmed(AccountId),329}330331impl<AccountId> SponsorshipState<AccountId> {332 /// Get a sponsor of the collection who has confirmed his status.333 pub fn sponsor(&self) -> Option<&AccountId> {334 match self {335 Self::Confirmed(sponsor) => Some(sponsor),336 _ => None,337 }338 }339340 /// Get a sponsor of the collection who has pending or confirmed status.341 pub fn pending_sponsor(&self) -> Option<&AccountId> {342 match self {343 Self::Unconfirmed(sponsor) | Self::Confirmed(sponsor) => Some(sponsor),344 _ => None,345 }346 }347348 /// Whether the sponsorship is confirmed.349 pub fn confirmed(&self) -> bool {350 matches!(self, Self::Confirmed(_))351 }352}353354impl<T> Default for SponsorshipState<T> {355 fn default() -> Self {356 Self::Disabled357 }358}359360pub type CollectionName = BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>;361pub type CollectionDescription = BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>;362pub type CollectionTokenPrefix = BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>;363364#[derive(Bitfields, Clone, Copy, PartialEq, Eq, Debug, Default)]365#[bondrewd(enforce_bytes = 1)]366pub struct CollectionFlags {367 /// Tokens in foreign collections can be transferred, but not burnt368 #[bondrewd(bits = "0..1")]369 pub foreign: bool,370 /// Supports ERC721Metadata371 #[bondrewd(bits = "1..2")]372 pub erc721metadata: bool,373 /// External collections can't be managed using `unique` api374 #[bondrewd(bits = "7..8")]375 pub external: bool,376377 #[bondrewd(reserve, bits = "2..7")]378 pub reserved: u8,379}380bondrewd_codec!(CollectionFlags);381382/// Base structure for represent collection.383///384/// Used to provide basic functionality for all types of collections.385///386/// #### Note387/// Collection parameters, used in storage (see [`RpcCollection`] for the RPC version).388#[struct_versioning::versioned(version = 2, upper)]389#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen)]390pub struct Collection<AccountId> {391 /// Collection owner account.392 pub owner: AccountId,393394 /// Collection mode.395 pub mode: CollectionMode,396397 /// Access mode.398 #[version(..2)]399 pub access: AccessMode,400401 /// Collection name.402 pub name: CollectionName,403404 /// Collection description.405 pub description: CollectionDescription,406407 /// Token prefix.408 pub token_prefix: CollectionTokenPrefix,409410 #[version(..2)]411 pub mint_mode: bool,412413 #[version(..2)]414 pub offchain_schema: BoundedVec<u8, ConstU32<OFFCHAIN_SCHEMA_LIMIT>>,415416 #[version(..2)]417 pub schema_version: SchemaVersion,418419 /// The state of sponsorship of the collection.420 pub sponsorship: SponsorshipState<AccountId>,421422 /// Collection limits.423 pub limits: CollectionLimits,424425 /// Collection permissions.426 #[version(2.., upper(Default::default()))]427 pub permissions: CollectionPermissions,428429 #[version(2.., upper(Default::default()))]430 pub flags: CollectionFlags,431432 #[version(..2)]433 pub variable_on_chain_schema: BoundedVec<u8, ConstU32<VARIABLE_ON_CHAIN_SCHEMA_LIMIT>>,434435 #[version(..2)]436 pub const_on_chain_schema: BoundedVec<u8, ConstU32<CONST_ON_CHAIN_SCHEMA_LIMIT>>,437438 #[version(..2)]439 pub meta_update_permission: MetaUpdatePermission,440}441442#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]443#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]444pub struct RpcCollectionFlags {445 /// Is collection is foreign.446 pub foreign: bool,447 /// Collection supports ERC721Metadata.448 pub erc721metadata: bool,449}450451/// Collection parameters, used in RPC calls (see [`Collection`] for the storage version).452#[struct_versioning::versioned(version = 2, upper)]453#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]454#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]455pub struct RpcCollection<AccountId> {456 /// Collection owner account.457 pub owner: AccountId,458459 /// Collection mode.460 pub mode: CollectionMode,461462 /// Collection name.463 pub name: Vec<u16>,464465 /// Collection description.466 pub description: Vec<u16>,467468 /// Token prefix.469 pub token_prefix: Vec<u8>,470471 /// The state of sponsorship of the collection.472 pub sponsorship: SponsorshipState<AccountId>,473474 /// Collection limits.475 pub limits: CollectionLimits,476477 /// Collection permissions.478 pub permissions: CollectionPermissions,479480 /// Token property permissions.481 pub token_property_permissions: Vec<PropertyKeyPermission>,482483 /// Collection properties.484 pub properties: Vec<Property>,485486 /// Is collection read only.487 pub read_only: bool,488489 /// Extra collection flags490 #[version(2.., upper(RpcCollectionFlags {foreign: false, erc721metadata: false}))]491 pub flags: RpcCollectionFlags,492}493494/// Data used for create collection.495///496/// All fields are wrapped in [`Option`], where `None` means chain default.497#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, Derivative, MaxEncodedLen)]498#[derivative(Debug, Default(bound = ""))]499pub struct CreateCollectionData<AccountId> {500 /// Collection mode.501 #[derivative(Default(value = "CollectionMode::NFT"))]502 pub mode: CollectionMode,503504 /// Access mode.505 pub access: Option<AccessMode>,506507 /// Collection name.508 pub name: CollectionName,509510 /// Collection description.511 pub description: CollectionDescription,512513 /// Token prefix.514 pub token_prefix: CollectionTokenPrefix,515516 /// Pending collection sponsor.517 pub pending_sponsor: Option<AccountId>,518519 /// Collection limits.520 pub limits: Option<CollectionLimits>,521522 /// Collection permissions.523 pub permissions: Option<CollectionPermissions>,524525 /// Token property permissions.526 pub token_property_permissions: CollectionPropertiesPermissionsVec,527528 /// Collection properties.529 pub properties: CollectionPropertiesVec,530}531532/// Bounded vector of properties permissions. Max length is [`MAX_PROPERTIES_PER_ITEM`].533// TODO: maybe rename to PropertiesPermissionsVec534pub type CollectionPropertiesPermissionsVec =535 BoundedVec<PropertyKeyPermission, ConstU32<MAX_PROPERTIES_PER_ITEM>>;536537/// Bounded vector of properties. Max length is [`MAX_PROPERTIES_PER_ITEM`].538pub type CollectionPropertiesVec = BoundedVec<Property, ConstU32<MAX_PROPERTIES_PER_ITEM>>;539540/// Limits and restrictions of a collection.541///542/// All fields are wrapped in [`Option`], where `None` means chain default.543///544/// Update with `pallet_common::Pallet::clamp_limits`.545// IMPORTANT: When adding/removing fields from this struct - don't forget to also546#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]547#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]548// When adding/removing fields from this struct - don't forget to also update with `pallet_common::Pallet::clamp_limits`.549// TODO: move `pallet_common::Pallet::clamp_limits` into `impl CollectionLimits`.550// TODO: may be remove [`Option`] and **pub** from fields and create struct with default values.551pub struct CollectionLimits {552 /// How many tokens can a user have on one account.553 /// * Default - [`ACCOUNT_TOKEN_OWNERSHIP_LIMIT`].554 /// * Limit - [`MAX_TOKEN_OWNERSHIP`].555 pub account_token_ownership_limit: Option<u32>,556557 /// How many bytes of data are available for sponsorship.558 /// * Default - [`CUSTOM_DATA_LIMIT`].559 /// * Limit - [`CUSTOM_DATA_LIMIT`].560 pub sponsored_data_size: Option<u32>,561562 // FIXME should we delete this or repurpose it?563 /// Times in how many blocks we sponsor data.564 ///565 /// If is `Some(v)` then **setVariableMetadata** is sponsored if there is `v` block between transactions.566 ///567 /// * Default - [`SponsoringDisabled`](SponsoringRateLimit::SponsoringDisabled).568 /// * Limit - [`MAX_SPONSOR_TIMEOUT`].569 ///570 /// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]571 pub sponsored_data_rate_limit: Option<SponsoringRateLimit>,572 /// Maximum amount of tokens inside the collection. Chain default: [`COLLECTION_TOKEN_LIMIT`]573574 /// How many tokens can be mined into this collection.575 ///576 /// * Default - [`COLLECTION_TOKEN_LIMIT`].577 /// * Limit - [`COLLECTION_TOKEN_LIMIT`].578 pub token_limit: Option<u32>,579580 /// Timeouts for transfer sponsoring.581 ///582 /// * Default583 /// - **Fungible** - [`FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT`]584 /// - **NFT** - [`NFT_SPONSOR_TRANSFER_TIMEOUT`]585 /// - **Refungible** - [`REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT`]586 /// * Limit - [`MAX_SPONSOR_TIMEOUT`].587 pub sponsor_transfer_timeout: Option<u32>,588589 /// Timeout for sponsoring an approval in passed blocks.590 ///591 /// * Default - [`SPONSOR_APPROVE_TIMEOUT`].592 /// * Limit - [`MAX_SPONSOR_TIMEOUT`].593 pub sponsor_approve_timeout: Option<u32>,594595 /// Whether the collection owner of the collection can send tokens (which belong to other users).596 ///597 /// * Default - **false**.598 pub owner_can_transfer: Option<bool>,599600 /// Can the collection owner burn other people's tokens.601 ///602 /// * Default - **true**.603 pub owner_can_destroy: Option<bool>,604605 /// Is it possible to send tokens from this collection between users.606 ///607 /// * Default - **true**.608 pub transfers_enabled: Option<bool>,609}610611impl CollectionLimits {612 pub fn with_default_limits(collection_type: CollectionMode) -> Self {613 CollectionLimits {614 account_token_ownership_limit: Some(ACCOUNT_TOKEN_OWNERSHIP_LIMIT),615 sponsored_data_size: Some(CUSTOM_DATA_LIMIT),616 sponsored_data_rate_limit: Some(SponsoringRateLimit::SponsoringDisabled),617 token_limit: Some(COLLECTION_TOKEN_LIMIT),618 sponsor_transfer_timeout: match collection_type {619 CollectionMode::NFT => Some(NFT_SPONSOR_TRANSFER_TIMEOUT),620 CollectionMode::ReFungible => Some(REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT),621 CollectionMode::Fungible(_) => Some(FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT),622 },623 sponsor_approve_timeout: Some(SPONSOR_APPROVE_TIMEOUT),624 owner_can_transfer: Some(false),625 owner_can_destroy: Some(true),626 transfers_enabled: Some(true),627 }628 }629630 /// Get effective value for [`account_token_ownership_limit`](self.account_token_ownership_limit).631 pub fn account_token_ownership_limit(&self) -> u32 {632 self.account_token_ownership_limit633 .unwrap_or(ACCOUNT_TOKEN_OWNERSHIP_LIMIT)634 .min(MAX_TOKEN_OWNERSHIP)635 }636637 /// Get effective value for [`sponsored_data_size`](self.sponsored_data_size).638 pub fn sponsored_data_size(&self) -> u32 {639 self.sponsored_data_size640 .unwrap_or(CUSTOM_DATA_LIMIT)641 .min(CUSTOM_DATA_LIMIT)642 }643644 /// Get effective value for [`token_limit`](self.token_limit).645 pub fn token_limit(&self) -> u32 {646 self.token_limit647 .unwrap_or(COLLECTION_TOKEN_LIMIT)648 .min(COLLECTION_TOKEN_LIMIT)649 }650651 // TODO: may be replace u32 to mode?652 /// Get effective value for [`sponsor_transfer_timeout`](self.sponsor_transfer_timeout).653 pub fn sponsor_transfer_timeout(&self, default: u32) -> u32 {654 self.sponsor_transfer_timeout655 .unwrap_or(default)656 .min(MAX_SPONSOR_TIMEOUT)657 }658659 /// Get effective value for [`sponsor_approve_timeout`](self.sponsor_approve_timeout).660 pub fn sponsor_approve_timeout(&self) -> u32 {661 self.sponsor_approve_timeout662 .unwrap_or(SPONSOR_APPROVE_TIMEOUT)663 .min(MAX_SPONSOR_TIMEOUT)664 }665666 /// Get effective value for [`owner_can_transfer`](self.owner_can_transfer).667 pub fn owner_can_transfer(&self) -> bool {668 self.owner_can_transfer.unwrap_or(false)669 }670671 /// Get effective value for [`owner_can_transfer_instaled`](self.owner_can_transfer_instaled).672 pub fn owner_can_transfer_instaled(&self) -> bool {673 self.owner_can_transfer.is_some()674 }675676 /// Get effective value for [`owner_can_destroy`](self.owner_can_destroy).677 pub fn owner_can_destroy(&self) -> bool {678 self.owner_can_destroy.unwrap_or(true)679 }680681 /// Get effective value for [`transfers_enabled`](self.transfers_enabled).682 pub fn transfers_enabled(&self) -> bool {683 self.transfers_enabled.unwrap_or(true)684 }685686 /// Get effective value for [`sponsored_data_rate_limit`](self.sponsored_data_rate_limit).687 pub fn sponsored_data_rate_limit(&self) -> Option<u32> {688 match self689 .sponsored_data_rate_limit690 .unwrap_or(SponsoringRateLimit::SponsoringDisabled)691 {692 SponsoringRateLimit::SponsoringDisabled => None,693 SponsoringRateLimit::Blocks(v) => Some(v.min(MAX_SPONSOR_TIMEOUT)),694 }695 }696}697698/// Permissions on certain operations within a collection.699///700/// Some fields are wrapped in [`Option`], where `None` means chain default.701///702/// Update with `pallet_common::Pallet::clamp_permissions`.703#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]704#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]705// When adding/removing fields from this struct - don't forget to also update `pallet_common::Pallet::clamp_permissions`.706// TODO: move `pallet_common::Pallet::clamp_permissions` into `impl CollectionPermissions`.707pub struct CollectionPermissions {708 /// Access mode.709 ///710 /// * Default - [`AccessMode::Normal`].711 pub access: Option<AccessMode>,712713 /// Minting allowance.714 ///715 /// * Default - **false**.716 pub mint_mode: Option<bool>,717718 /// Permissions for nesting.719 ///720 /// * Default721 /// - `token_owner` - **false**722 /// - `collection_admin` - **false**723 /// - `restricted` - **None**724 pub nesting: Option<NestingPermissions>,725}726727impl CollectionPermissions {728 /// Get effective value for [`access`](self.access).729 pub fn access(&self) -> AccessMode {730 self.access.unwrap_or(AccessMode::Normal)731 }732733 /// Get effective value for [`mint_mode`](self.mint_mode).734 pub fn mint_mode(&self) -> bool {735 self.mint_mode.unwrap_or(false)736 }737738 /// Get effective value for [`nesting`](self.nesting).739 pub fn nesting(&self) -> &NestingPermissions {740 static DEFAULT: NestingPermissions = NestingPermissions {741 token_owner: false,742 collection_admin: false,743 restricted: None,744 #[cfg(feature = "runtime-benchmarks")]745 permissive: false,746 };747 self.nesting.as_ref().unwrap_or(&DEFAULT)748 }749}750751/// Inner set for collections allowed to nest.752type OwnerRestrictedSetInner = BoundedBTreeSet<CollectionId, ConstU32<16>>;753754/// Wraper for collections set allowing nest.755#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]756#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]757#[derivative(Debug)]758pub struct OwnerRestrictedSet(759 #[cfg_attr(feature = "serde1", serde(with = "bounded::set_serde"))]760 #[derivative(Debug(format_with = "bounded::set_debug"))]761 pub OwnerRestrictedSetInner,762);763764impl OwnerRestrictedSet {765 /// Create new set.766 pub fn new() -> Self {767 Self(Default::default())768 }769}770impl core::ops::Deref for OwnerRestrictedSet {771 type Target = OwnerRestrictedSetInner;772 fn deref(&self) -> &Self::Target {773 &self.0774 }775}776impl core::ops::DerefMut for OwnerRestrictedSet {777 fn deref_mut(&mut self) -> &mut Self::Target {778 &mut self.0779 }780}781782/// Part of collection permissions, if set, defines who is able to nest tokens into other tokens.783#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]784#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]785#[derivative(Debug)]786pub struct NestingPermissions {787 /// Owner of token can nest tokens under it.788 pub token_owner: bool,789 /// Admin of token collection can nest tokens under token.790 pub collection_admin: bool,791 /// If set - only tokens from specified collections can be nested.792 pub restricted: Option<OwnerRestrictedSet>,793794 #[cfg(feature = "runtime-benchmarks")]795 /// Anyone can nest tokens, mutually exclusive with `token_owner`, `admin`.796 pub permissive: bool,797}798799/// Enum denominating how often can sponsoring occur if it is enabled.800///801/// Used for [`collection limits`](CollectionLimits).802#[derive(Encode, Decode, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]803#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]804pub enum SponsoringRateLimit {805 /// Sponsoring is disabled, and the collection sponsor will not pay for transactions806 SponsoringDisabled,807 /// Once per how many blocks can sponsorship of a transaction type occur808 Blocks(u32),809}810811/// Data used to describe an NFT at creation.812#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]813#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]814#[derivative(Debug)]815pub struct CreateNftData {816 /// Key-value pairs used to describe the token as metadata817 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]818 #[derivative(Debug(format_with = "bounded::vec_debug"))]819 /// Properties that wil be assignet to created item.820 pub properties: CollectionPropertiesVec,821}822823/// Data used to describe a Fungible token at creation.824#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq, TypeInfo)]825#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]826pub struct CreateFungibleData {827 /// Number of fungible coins minted828 pub value: u128,829}830831/// Data used to describe a Refungible token at creation.832#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]833#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]834#[derivative(Debug)]835pub struct CreateReFungibleData {836 /// Number of pieces the RFT is split into837 pub pieces: u128,838839 /// Key-value pairs used to describe the token as metadata840 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]841 #[derivative(Debug(format_with = "bounded::vec_debug"))]842 pub properties: CollectionPropertiesVec,843}844845// TODO: remove this.846#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]847#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]848pub enum MetaUpdatePermission {849 ItemOwner,850 Admin,851 None,852}853854/// Enum holding data used for creation of all three item types.855/// Unified data for create item.856#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]857#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]858pub enum CreateItemData {859 /// Data for create NFT.860 NFT(CreateNftData),861 /// Data for create Fungible item.862 Fungible(CreateFungibleData),863 /// Data for create ReFungible item.864 ReFungible(CreateReFungibleData),865}866867/// Extended data for create NFT.868#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]869#[derivative(Debug)]870pub struct CreateNftExData<CrossAccountId> {871 /// Properties that wil be assignet to created item.872 #[derivative(Debug(format_with = "bounded::vec_debug"))]873 pub properties: CollectionPropertiesVec,874875 /// Owner of creating item.876 pub owner: CrossAccountId,877}878879/// Extended data for create ReFungible item.880#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]881#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]882pub struct CreateRefungibleExMultipleOwners<CrossAccountId> {883 #[derivative(Debug(format_with = "bounded::map_debug"))]884 pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,885 #[derivative(Debug(format_with = "bounded::vec_debug"))]886 pub properties: CollectionPropertiesVec,887}888889/// Extended data for create ReFungible item.890#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]891#[derivative(Debug(bound = "CrossAccountId: fmt::Debug"))]892pub struct CreateRefungibleExSingleOwner<CrossAccountId> {893 pub user: CrossAccountId,894 pub pieces: u128,895 #[derivative(Debug(format_with = "bounded::vec_debug"))]896 pub properties: CollectionPropertiesVec,897}898899/// Unified extended data for creating item.900#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]901#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]902pub enum CreateItemExData<CrossAccountId> {903 /// Extended data for create NFT.904 NFT(905 #[derivative(Debug(format_with = "bounded::vec_debug"))]906 BoundedVec<CreateNftExData<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,907 ),908909 /// Extended data for create Fungible item.910 Fungible(911 #[derivative(Debug(format_with = "bounded::map_debug"))]912 BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,913 ),914915 /// Extended data for create ReFungible item in case of916 /// many tokens, each may have only one owner917 RefungibleMultipleItems(918 #[derivative(Debug(format_with = "bounded::vec_debug"))]919 BoundedVec<CreateRefungibleExSingleOwner<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,920 ),921922 /// Extended data for create ReFungible item in case of923 /// single token, which may have many owners924 RefungibleMultipleOwners(CreateRefungibleExMultipleOwners<CrossAccountId>),925}926927impl From<CreateNftData> for CreateItemData {928 fn from(item: CreateNftData) -> Self {929 CreateItemData::NFT(item)930 }931}932933impl From<CreateReFungibleData> for CreateItemData {934 fn from(item: CreateReFungibleData) -> Self {935 CreateItemData::ReFungible(item)936 }937}938939impl From<CreateFungibleData> for CreateItemData {940 fn from(item: CreateFungibleData) -> Self {941 CreateItemData::Fungible(item)942 }943}944945/// Token's address, dictated by its collection and token IDs.946#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]947#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]948// todo possibly rename to be used generally as an address pair949pub struct TokenChild {950 /// Token id.951 pub token: TokenId,952953 /// Collection id.954 pub collection: CollectionId,955}956957/// Collection statistics.958#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]959#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]960pub struct CollectionStats {961 /// Number of created items.962 pub created: u32,963964 /// Number of burned items.965 pub destroyed: u32,966967 /// Number of current items.968 pub alive: u32,969}970971/// This type works like [`PhantomData`] but supports generating _scale-info_ descriptions to generate node metadata.972#[derive(Encode, Decode, Clone, Debug)]973#[cfg_attr(feature = "std", derive(PartialEq))]974pub struct PhantomType<T>(core::marker::PhantomData<T>);975976impl<T: TypeInfo + 'static> TypeInfo for PhantomType<T> {977 type Identity = PhantomType<T>;978979 fn type_info() -> scale_info::Type {980 use scale_info::{981 Type, Path,982 build::{FieldsBuilder, UnnamedFields},983 form::MetaForm,984 type_params,985 };986 Type::builder()987 .path(Path::new("up_data_structs", "PhantomType"))988 .type_params(type_params!(T))989 .composite(990 <FieldsBuilder<MetaForm, UnnamedFields>>::default().field(|b| b.ty::<[T; 0]>()),991 )992 }993}994impl<T> MaxEncodedLen for PhantomType<T> {995 fn max_encoded_len() -> usize {996 0997 }998}9991000/// Bounded vector of bytes.1001pub type BoundedBytes<S> = BoundedVec<u8, S>;10021003/// Extra properties for external collections.1004pub type AuxPropertyValue = BoundedBytes<ConstU32<MAX_AUX_PROPERTY_VALUE_LENGTH>>;10051006/// Property key.1007pub type PropertyKey = BoundedBytes<ConstU32<MAX_PROPERTY_KEY_LENGTH>>;10081009/// Property value.1010pub type PropertyValue = BoundedBytes<ConstU32<MAX_PROPERTY_VALUE_LENGTH>>;10111012/// Property permission.1013#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone, Default)]1014#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1015pub struct PropertyPermission {1016 /// Permission to change the property and property permission.1017 ///1018 /// If it **false** then you can not change corresponding property even if [`collection_admin`] and [`token_owner`] are **true**.1019 pub mutable: bool,10201021 /// Change permission for the collection administrator.1022 pub collection_admin: bool,10231024 /// Permission to change the property for the owner of the token.1025 pub token_owner: bool,1026}10271028impl PropertyPermission {1029 /// Creates mutable property permission but changes restricted for collection admin and token owner.1030 pub fn none() -> Self {1031 Self {1032 mutable: true,1033 collection_admin: false,1034 token_owner: false,1035 }1036 }1037}10381039/// Property is simpl key-value record.1040#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, MaxEncodedLen)]1041#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1042pub struct Property {1043 /// Property key.1044 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1045 pub key: PropertyKey,10461047 /// Property value.1048 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1049 pub value: PropertyValue,1050}10511052impl Into<(PropertyKey, PropertyValue)> for Property {1053 fn into(self) -> (PropertyKey, PropertyValue) {1054 (self.key, self.value)1055 }1056}10571058/// Record for proprty key permission.1059#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone)]1060#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1061pub struct PropertyKeyPermission {1062 /// Key.1063 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1064 pub key: PropertyKey,10651066 /// Permission.1067 pub permission: PropertyPermission,1068}10691070impl Into<(PropertyKey, PropertyPermission)> for PropertyKeyPermission {1071 fn into(self) -> (PropertyKey, PropertyPermission) {1072 (self.key, self.permission)1073 }1074}10751076/// Errors for properties actions.1077#[derive(Debug)]1078pub enum PropertiesError {1079 /// The space allocated for properties has run out.1080 ///1081 /// * Limit for colection - [`MAX_COLLECTION_PROPERTIES_SIZE`].1082 /// * Limit for token - [`MAX_TOKEN_PROPERTIES_SIZE`].1083 NoSpaceForProperty,10841085 /// The property limit has been reached.1086 ///1087 /// * Limit - [`MAX_PROPERTIES_PER_ITEM`].1088 PropertyLimitReached,10891090 /// Property key contains not allowed character.1091 InvalidCharacterInPropertyKey,10921093 /// Property key length is too long.1094 ///1095 /// * Limit - [`MAX_PROPERTY_KEY_LENGTH`].1096 PropertyKeyIsTooLong,10971098 /// Property key is empty.1099 EmptyPropertyKey,1100}11011102/// Token owner error: it could be either `NotFound` ot `MultipleOwners`.1103#[derive(Debug)]1104pub enum TokenOwnerError {1105 NotFound,1106 MultipleOwners,1107}11081109/// Marker for scope of property.1110///1111/// Scoped property can't be changed by user. Used for external collections.1112#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Clone, Copy)]1113pub enum PropertyScope {1114 None,1115 Rmrk,1116}11171118impl PropertyScope {1119 /// Apply scope to property key.1120 pub fn apply(self, key: PropertyKey) -> Result<PropertyKey, PropertiesError> {1121 let scope_str: &[u8] = match self {1122 Self::None => return Ok(key),1123 Self::Rmrk => b"rmrk",1124 };11251126 [scope_str, b":", key.as_slice()]1127 .concat()1128 .try_into()1129 .map_err(|_| PropertiesError::PropertyKeyIsTooLong)1130 }1131}11321133/// Trait for operate with properties.1134pub trait TrySetProperty: Sized {1135 type Value;11361137 /// Try to set property with scope.1138 fn try_scoped_set(1139 &mut self,1140 scope: PropertyScope,1141 key: PropertyKey,1142 value: Self::Value,1143 ) -> Result<Option<Self::Value>, PropertiesError>;11441145 /// Try to set property with scope from iterator.1146 fn try_scoped_set_from_iter<I, KV>(1147 &mut self,1148 scope: PropertyScope,1149 iter: I,1150 ) -> Result<(), PropertiesError>1151 where1152 I: Iterator<Item = KV>,1153 KV: Into<(PropertyKey, Self::Value)>,1154 {1155 for kv in iter {1156 let (key, value) = kv.into();1157 self.try_scoped_set(scope, key, value)?;1158 }11591160 Ok(())1161 }11621163 /// Try to set property.1164 fn try_set(1165 &mut self,1166 key: PropertyKey,1167 value: Self::Value,1168 ) -> Result<Option<Self::Value>, PropertiesError> {1169 self.try_scoped_set(PropertyScope::None, key, value)1170 }11711172 /// Try to set property from iterator.1173 fn try_set_from_iter<I, KV>(&mut self, iter: I) -> Result<(), PropertiesError>1174 where1175 I: Iterator<Item = KV>,1176 KV: Into<(PropertyKey, Self::Value)>,1177 {1178 self.try_scoped_set_from_iter(PropertyScope::None, iter)1179 }1180}11811182/// Wrapped map for storing properties.1183#[derive(Encode, Decode, TypeInfo, Derivative, Clone, PartialEq, MaxEncodedLen)]1184#[derivative(Default(bound = ""))]1185pub struct PropertiesMap<Value>(1186 BoundedBTreeMap<PropertyKey, Value, ConstU32<MAX_PROPERTIES_PER_ITEM>>,1187);11881189impl<Value> PropertiesMap<Value> {1190 /// Create new property map.1191 pub fn new() -> Self {1192 Self(BoundedBTreeMap::new())1193 }11941195 /// Remove property from map.1196 pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<Value>, PropertiesError> {1197 Self::check_property_key(key)?;11981199 Ok(self.0.remove(key))1200 }12011202 /// Get property with appropriate key from map.1203 pub fn get(&self, key: &PropertyKey) -> Option<&Value> {1204 self.0.get(key)1205 }12061207 /// Check if map contains key.1208 pub fn contains_key(&self, key: &PropertyKey) -> bool {1209 self.0.contains_key(key)1210 }12111212 /// Check if map contains key with key validation.1213 fn check_property_key(key: &PropertyKey) -> Result<(), PropertiesError> {1214 if key.is_empty() {1215 return Err(PropertiesError::EmptyPropertyKey);1216 }12171218 for byte in key.as_slice().iter() {1219 let byte = *byte;12201221 if !byte.is_ascii_alphanumeric() && byte != b'_' && byte != b'-' && byte != b'.' {1222 return Err(PropertiesError::InvalidCharacterInPropertyKey);1223 }1224 }12251226 Ok(())1227 }12281229 pub fn values(&self) -> impl Iterator<Item = &Value> {1230 self.0.values()1231 }1232}12331234impl<Value> IntoIterator for PropertiesMap<Value> {1235 type Item = (PropertyKey, Value);1236 type IntoIter = <1237 BoundedBTreeMap<1238 PropertyKey,1239 Value,1240 ConstU32<MAX_PROPERTIES_PER_ITEM>1241 > as IntoIterator1242 >::IntoIter;12431244 fn into_iter(self) -> Self::IntoIter {1245 self.0.into_iter()1246 }1247}12481249impl<Value> TrySetProperty for PropertiesMap<Value> {1250 type Value = Value;12511252 fn try_scoped_set(1253 &mut self,1254 scope: PropertyScope,1255 key: PropertyKey,1256 value: Self::Value,1257 ) -> Result<Option<Self::Value>, PropertiesError> {1258 Self::check_property_key(&key)?;12591260 let key = scope.apply(key)?;1261 self.01262 .try_insert(key, value)1263 .map_err(|_| PropertiesError::PropertyLimitReached)1264 }1265}12661267/// Alias for property permissions map.1268pub type PropertiesPermissionMap = PropertiesMap<PropertyPermission>;12691270/// Wrapper for properties map with consumed space control.1271#[derive(Encode, Decode, TypeInfo, Clone, PartialEq, MaxEncodedLen)]1272pub struct Properties {1273 map: PropertiesMap<PropertyValue>,1274 consumed_space: u32,1275 space_limit: u32,1276}12771278impl Properties {1279 /// Create new properies container.1280 pub fn new(space_limit: u32) -> Self {1281 Self {1282 map: PropertiesMap::new(),1283 consumed_space: 0,1284 space_limit,1285 }1286 }12871288 /// Remove propery with appropiate key.1289 pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<PropertyValue>, PropertiesError> {1290 let value = self.map.remove(key)?;12911292 if let Some(ref value) = value {1293 let value_len = value.len() as u32;1294 self.consumed_space -= value_len;1295 }12961297 Ok(value)1298 }12991300 /// Get property with appropriate key.1301 pub fn get(&self, key: &PropertyKey) -> Option<&PropertyValue> {1302 self.map.get(key)1303 }13041305 /// Recomputes the consumed space for the current properties state.1306 /// Needed to repair a token due to a bug fixed in the [PR #733](https://github.com/UniqueNetwork/unique-chain/pull/773).1307 pub fn recompute_consumed_space(&mut self) {1308 self.consumed_space = self.map.values().map(|value| value.len() as u32).sum();1309 }1310}13111312impl IntoIterator for Properties {1313 type Item = (PropertyKey, PropertyValue);1314 type IntoIter = <PropertiesMap<PropertyValue> as IntoIterator>::IntoIter;13151316 fn into_iter(self) -> Self::IntoIter {1317 self.map.into_iter()1318 }1319}13201321impl TrySetProperty for Properties {1322 type Value = PropertyValue;13231324 fn try_scoped_set(1325 &mut self,1326 scope: PropertyScope,1327 key: PropertyKey,1328 value: Self::Value,1329 ) -> Result<Option<Self::Value>, PropertiesError> {1330 let value_len = value.len();13311332 if self.consumed_space as usize + value_len > self.space_limit as usize1333 && !cfg!(feature = "runtime-benchmarks")1334 {1335 return Err(PropertiesError::NoSpaceForProperty);1336 }13371338 let value_len = value_len as u32;1339 let old_value = self.map.try_scoped_set(scope, key, value)?;13401341 let old_value_len = old_value.as_ref().map(|v| v.len() as u32).unwrap_or(0);13421343 if value_len > old_value_len {1344 self.consumed_space += value_len - old_value_len;1345 } else {1346 self.consumed_space -= old_value_len - value_len;1347 }13481349 Ok(old_value)1350 }1351}13521353/// Utility struct for using in `StorageMap`.1354pub struct CollectionProperties;13551356impl Get<Properties> for CollectionProperties {1357 fn get() -> Properties {1358 Properties::new(MAX_COLLECTION_PROPERTIES_SIZE)1359 }1360}13611362/// Utility struct for using in `StorageMap`.1363pub struct TokenProperties;13641365impl Get<Properties> for TokenProperties {1366 fn get() -> Properties {1367 Properties::new(MAX_TOKEN_PROPERTIES_SIZE)1368 }1369}13701371// RMRK1372// todo document?1373parameter_types! {1374 #[derive(PartialEq, TypeInfo)]1375 pub const RmrkStringLimit: u32 = 128;1376 #[derive(PartialEq)]1377 pub const RmrkCollectionSymbolLimit: u32 = MAX_TOKEN_PREFIX_LENGTH;1378 #[derive(PartialEq)]1379 pub const RmrkResourceSymbolLimit: u32 = 10;1380 #[derive(PartialEq)]1381 pub const RmrkBaseSymbolLimit: u32 = MAX_TOKEN_PREFIX_LENGTH;1382 #[derive(PartialEq)]1383 pub const RmrkKeyLimit: u32 = 32;1384 #[derive(PartialEq)]1385 pub const RmrkValueLimit: u32 = 256;1386 #[derive(PartialEq)]1387 pub const RmrkMaxCollectionsEquippablePerPart: u32 = 100;1388 #[derive(PartialEq)]1389 pub const MaxPropertiesPerTheme: u32 = 5;1390 #[derive(PartialEq)]1391 pub const RmrkPartsLimit: u32 = 25;1392 #[derive(PartialEq)]1393 pub const RmrkMaxPriorities: u32 = 25;1394 #[derive(PartialEq)]1395 pub const MaxResourcesOnMint: u32 = 100;1396}13971398impl From<RmrkCollectionId> for CollectionId {1399 fn from(id: RmrkCollectionId) -> Self {1400 Self(id)1401 }1402}14031404impl From<RmrkNftId> for TokenId {1405 fn from(id: RmrkNftId) -> Self {1406 Self(id)1407 }1408}14091410pub type RmrkCollectionInfo<AccountId> =1411 CollectionInfo<RmrkString, RmrkCollectionSymbol, AccountId>;1412pub type RmrkInstanceInfo<AccountId> = NftInfo<AccountId, Permill, RmrkString>;1413pub type RmrkResourceInfo = ResourceInfo<RmrkString, RmrkBoundedParts>;1414pub type RmrkPropertyInfo = PropertyInfo<RmrkKeyString, RmrkValueString>;1415pub type RmrkBaseInfo<AccountId> = BaseInfo<AccountId, RmrkString>;1416pub type BoundedEquippableCollectionIds =1417 BoundedVec<RmrkCollectionId, RmrkMaxCollectionsEquippablePerPart>;1418pub type RmrkPartType = PartType<RmrkString, BoundedEquippableCollectionIds>;1419pub type RmrkEquippableList = EquippableList<BoundedEquippableCollectionIds>;1420pub type RmrkThemeProperty = ThemeProperty<RmrkString>;1421pub type RmrkTheme = Theme<RmrkString, Vec<RmrkThemeProperty>>;1422pub type RmrkBoundedTheme = Theme<RmrkString, BoundedVec<RmrkThemeProperty, MaxPropertiesPerTheme>>;1423pub type RmrkResourceTypes = ResourceTypes<RmrkString, RmrkBoundedParts>;14241425pub type RmrkBasicResource = BasicResource<RmrkString>;1426pub type RmrkComposableResource = ComposableResource<RmrkString, RmrkBoundedParts>;1427pub type RmrkSlotResource = SlotResource<RmrkString>;14281429pub type RmrkString = BoundedVec<u8, RmrkStringLimit>;1430pub type RmrkCollectionSymbol = BoundedVec<u8, RmrkCollectionSymbolLimit>;1431pub type RmrkBaseSymbol = BoundedVec<u8, RmrkBaseSymbolLimit>;1432pub type RmrkKeyString = BoundedVec<u8, RmrkKeyLimit>;1433pub type RmrkValueString = BoundedVec<u8, RmrkValueLimit>;1434pub type RmrkBoundedResource = BoundedVec<u8, RmrkResourceSymbolLimit>;1435pub type RmrkBoundedParts = BoundedVec<RmrkPartId, RmrkPartsLimit>; // todo make sure it is needed14361437pub type RmrkRpcString = Vec<u8>;1438pub type RmrkThemeName = RmrkRpcString;1439pub type RmrkPropertyKey = RmrkRpcString;1// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.2// This file is part of Unique Network.34// Unique Network is free software: you can redistribute it and/or modify5// it under the terms of the GNU General Public License as published by6// the Free Software Foundation, either version 3 of the License, or7// (at your option) any later version.89// Unique Network is distributed in the hope that it will be useful,10// but WITHOUT ANY WARRANTY; without even the implied warranty of11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the12// GNU General Public License for more details.1314// You should have received a copy of the GNU General Public License15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.1617//! # Primitives crate.18//!19//! This crate contains types, traits and constants.2021#![cfg_attr(not(feature = "std"), no_std)]2223use core::{24 convert::{TryFrom, TryInto},25 fmt,26};27use frame_support::{28 storage::{bounded_btree_map::BoundedBTreeMap, bounded_btree_set::BoundedBTreeSet},29 traits::Get,30};3132#[cfg(feature = "serde")]33use serde::{Serialize, Deserialize};3435use sp_core::U256;36use sp_runtime::{ArithmeticError, sp_std::prelude::Vec};37use codec::{Decode, Encode, EncodeLike, MaxEncodedLen};38use bondrewd::Bitfields;39use frame_support::{BoundedVec, traits::ConstU32};40use derivative::Derivative;41use scale_info::TypeInfo;4243mod bondrewd_codec;44mod bounded;45pub mod budget;46pub mod mapping;47mod migration;4849/// Maximum of decimal points.50pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;5152/// Maximum pieces for refungible token.53pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;54pub const MAX_SPONSOR_TIMEOUT: u32 = 10_368_000;5556/// Maximum tokens for user.57pub const MAX_TOKEN_OWNERSHIP: u32 = if cfg!(not(feature = "limit-testing")) {58 100_00059} else {60 1061};6263/// Maximum for collections can be created.64pub const COLLECTION_NUMBER_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {65 100_00066} else {67 1068};6970/// Maximum for various custom data of token.71pub const CUSTOM_DATA_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {72 204873} else {74 1075};7677/// Maximum admins per collection.78pub const COLLECTION_ADMINS_LIMIT: u32 = 5;7980/// Maximum tokens per collection.81pub const COLLECTION_TOKEN_LIMIT: u32 = u32::MAX;8283/// Maximum tokens per account.84pub const ACCOUNT_TOKEN_OWNERSHIP_LIMIT: u32 = if cfg!(not(feature = "limit-testing")) {85 1_000_00086} else {87 1088};8990/// Default timeout for transfer sponsoring NFT item.91pub const NFT_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;92/// Default timeout for transfer sponsoring fungible item.93pub const FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;94/// Default timeout for transfer sponsoring refungible item.95pub const REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT: u32 = 5;9697/// Default timeout for sponsored approving.98pub const SPONSOR_APPROVE_TIMEOUT: u32 = 5;99100// Schema limits101pub const OFFCHAIN_SCHEMA_LIMIT: u32 = 8192;102pub const VARIABLE_ON_CHAIN_SCHEMA_LIMIT: u32 = 8192;103pub const CONST_ON_CHAIN_SCHEMA_LIMIT: u32 = 32768;104105// TODO: not used. Delete?106pub const COLLECTION_FIELD_LIMIT: u32 = CONST_ON_CHAIN_SCHEMA_LIMIT;107108/// Maximal length of a collection name.109pub const MAX_COLLECTION_NAME_LENGTH: u32 = 64;110111/// Maximal length of a collection description.112pub const MAX_COLLECTION_DESCRIPTION_LENGTH: u32 = 256;113114/// Maximal length of a token prefix.115pub const MAX_TOKEN_PREFIX_LENGTH: u32 = 16;116117/// Maximal length of a property key.118pub const MAX_PROPERTY_KEY_LENGTH: u32 = 256;119120/// Maximal length of a property value.121pub const MAX_PROPERTY_VALUE_LENGTH: u32 = 32768;122123/// A maximum number of token properties.124pub const MAX_PROPERTIES_PER_ITEM: u32 = 64;125126/// Maximal lenght of extended property value.127pub const MAX_AUX_PROPERTY_VALUE_LENGTH: u32 = 2048;128129/// Maximum size for all collection properties.130pub const MAX_COLLECTION_PROPERTIES_SIZE: u32 = 40960;131132/// Maximum size of all token properties.133pub const MAX_TOKEN_PROPERTIES_SIZE: u32 = 32768;134135/// How much items can be created per single136/// create_many call.137pub const MAX_ITEMS_PER_BATCH: u32 = 200;138139/// Used for limit bounded types of token custom data.140pub type CustomDataLimit = ConstU32<CUSTOM_DATA_LIMIT>;141142/// Collection id.143#[derive(144 Encode,145 Decode,146 PartialEq,147 Eq,148 PartialOrd,149 Ord,150 Clone,151 Copy,152 Debug,153 Default,154 TypeInfo,155 MaxEncodedLen,156)]157#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]158pub struct CollectionId(pub u32);159impl EncodeLike<u32> for CollectionId {}160impl EncodeLike<CollectionId> for u32 {}161162impl From<u32> for CollectionId {163 fn from(value: u32) -> Self {164 Self(value)165 }166}167168/// Token id.169#[derive(170 Encode,171 Decode,172 PartialEq,173 Eq,174 PartialOrd,175 Ord,176 Clone,177 Copy,178 Debug,179 Default,180 TypeInfo,181 MaxEncodedLen,182)]183#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]184pub struct TokenId(pub u32);185impl EncodeLike<u32> for TokenId {}186impl EncodeLike<TokenId> for u32 {}187188impl TokenId {189 /// Try to get next token id.190 ///191 /// If next id cause overflow, then [`ArithmeticError::Overflow`] returned.192 pub fn try_next(self) -> Result<TokenId, ArithmeticError> {193 self.0194 .checked_add(1)195 .ok_or(ArithmeticError::Overflow)196 .map(Self)197 }198}199200impl From<TokenId> for U256 {201 fn from(t: TokenId) -> Self {202 t.0.into()203 }204}205206impl TryFrom<U256> for TokenId {207 type Error = &'static str;208209 fn try_from(value: U256) -> Result<Self, Self::Error> {210 Ok(TokenId(value.try_into().map_err(|_| "too large token id")?))211 }212}213214/// Token data.215#[struct_versioning::versioned(version = 2, upper)]216#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]217#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]218pub struct TokenData<CrossAccountId> {219 /// Properties of token.220 pub properties: Vec<Property>,221222 /// Token owner.223 pub owner: Option<CrossAccountId>,224225 /// Token pieces.226 #[version(2.., upper(0))]227 pub pieces: u128,228}229230// TODO: unused type231pub struct OverflowError;232impl From<OverflowError> for &'static str {233 fn from(_: OverflowError) -> Self {234 "overflow occured"235 }236}237238/// Alias for decimal points type.239pub type DecimalPoints = u8;240241/// Collection mode.242///243/// Collection can represent various types of tokens.244/// Each collection can contain only one type of tokens at a time.245/// This type helps to understand which tokens the collection contains.246#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]247#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]248pub enum CollectionMode {249 /// Non fungible tokens.250 NFT,251 /// Fungible tokens.252 Fungible(DecimalPoints),253 /// Refungible tokens.254 ReFungible,255}256257impl CollectionMode {258 /// Get collection mod as number.259 pub fn id(&self) -> u8 {260 match self {261 CollectionMode::NFT => 1,262 CollectionMode::Fungible(_) => 2,263 CollectionMode::ReFungible => 3,264 }265 }266}267268// TODO: unused trait269pub trait SponsoringResolve<AccountId, Call> {270 fn resolve(who: &AccountId, call: &Call) -> Option<AccountId>;271}272273/// Access mode for some token operations.274#[derive(Encode, Decode, Eq, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]275#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]276pub enum AccessMode {277 /// Access grant for owner and admins. Used as default.278 Normal,279 /// Like a [`Normal`](AccessMode::Normal) but also users in allow list.280 AllowList,281}282impl Default for AccessMode {283 fn default() -> Self {284 Self::Normal285 }286}287288// TODO: remove in future.289#[derive(Encode, Decode, Eq, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]290#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]291pub enum SchemaVersion {292 ImageURL,293 Unique,294}295impl Default for SchemaVersion {296 fn default() -> Self {297 Self::ImageURL298 }299}300301// TODO: unused type302#[derive(Encode, Decode, Default, Debug, Clone, PartialEq, TypeInfo)]303#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]304pub struct Ownership<AccountId> {305 pub owner: AccountId,306 pub fraction: u128,307}308309/// The state of collection sponsorship.310#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]311#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]312pub enum SponsorshipState<AccountId> {313 /// The fees are applied to the transaction sender.314 Disabled,315 /// The sponsor is under consideration. Until the sponsor gives his consent,316 /// the fee will still be charged to sender.317 Unconfirmed(AccountId),318 /// Transactions are sponsored by specified account.319 Confirmed(AccountId),320}321322impl<AccountId> SponsorshipState<AccountId> {323 /// Get a sponsor of the collection who has confirmed his status.324 pub fn sponsor(&self) -> Option<&AccountId> {325 match self {326 Self::Confirmed(sponsor) => Some(sponsor),327 _ => None,328 }329 }330331 /// Get a sponsor of the collection who has pending or confirmed status.332 pub fn pending_sponsor(&self) -> Option<&AccountId> {333 match self {334 Self::Unconfirmed(sponsor) | Self::Confirmed(sponsor) => Some(sponsor),335 _ => None,336 }337 }338339 /// Whether the sponsorship is confirmed.340 pub fn confirmed(&self) -> bool {341 matches!(self, Self::Confirmed(_))342 }343}344345impl<T> Default for SponsorshipState<T> {346 fn default() -> Self {347 Self::Disabled348 }349}350351pub type CollectionName = BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>;352pub type CollectionDescription = BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>;353pub type CollectionTokenPrefix = BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>;354355#[derive(Bitfields, Clone, Copy, PartialEq, Eq, Debug, Default)]356#[bondrewd(enforce_bytes = 1)]357pub struct CollectionFlags {358 /// Tokens in foreign collections can be transferred, but not burnt359 #[bondrewd(bits = "0..1")]360 pub foreign: bool,361 /// Supports ERC721Metadata362 #[bondrewd(bits = "1..2")]363 pub erc721metadata: bool,364 /// External collections can't be managed using `unique` api365 #[bondrewd(bits = "7..8")]366 pub external: bool,367368 #[bondrewd(reserve, bits = "2..7")]369 pub reserved: u8,370}371bondrewd_codec!(CollectionFlags);372373/// Base structure for represent collection.374///375/// Used to provide basic functionality for all types of collections.376///377/// #### Note378/// Collection parameters, used in storage (see [`RpcCollection`] for the RPC version).379#[struct_versioning::versioned(version = 2, upper)]380#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen)]381pub struct Collection<AccountId> {382 /// Collection owner account.383 pub owner: AccountId,384385 /// Collection mode.386 pub mode: CollectionMode,387388 /// Access mode.389 #[version(..2)]390 pub access: AccessMode,391392 /// Collection name.393 pub name: CollectionName,394395 /// Collection description.396 pub description: CollectionDescription,397398 /// Token prefix.399 pub token_prefix: CollectionTokenPrefix,400401 #[version(..2)]402 pub mint_mode: bool,403404 #[version(..2)]405 pub offchain_schema: BoundedVec<u8, ConstU32<OFFCHAIN_SCHEMA_LIMIT>>,406407 #[version(..2)]408 pub schema_version: SchemaVersion,409410 /// The state of sponsorship of the collection.411 pub sponsorship: SponsorshipState<AccountId>,412413 /// Collection limits.414 pub limits: CollectionLimits,415416 /// Collection permissions.417 #[version(2.., upper(Default::default()))]418 pub permissions: CollectionPermissions,419420 #[version(2.., upper(Default::default()))]421 pub flags: CollectionFlags,422423 #[version(..2)]424 pub variable_on_chain_schema: BoundedVec<u8, ConstU32<VARIABLE_ON_CHAIN_SCHEMA_LIMIT>>,425426 #[version(..2)]427 pub const_on_chain_schema: BoundedVec<u8, ConstU32<CONST_ON_CHAIN_SCHEMA_LIMIT>>,428429 #[version(..2)]430 pub meta_update_permission: MetaUpdatePermission,431}432433#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]434#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]435pub struct RpcCollectionFlags {436 /// Is collection is foreign.437 pub foreign: bool,438 /// Collection supports ERC721Metadata.439 pub erc721metadata: bool,440}441442/// Collection parameters, used in RPC calls (see [`Collection`] for the storage version).443#[struct_versioning::versioned(version = 2, upper)]444#[derive(Encode, Decode, Clone, PartialEq, TypeInfo)]445#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]446pub struct RpcCollection<AccountId> {447 /// Collection owner account.448 pub owner: AccountId,449450 /// Collection mode.451 pub mode: CollectionMode,452453 /// Collection name.454 pub name: Vec<u16>,455456 /// Collection description.457 pub description: Vec<u16>,458459 /// Token prefix.460 pub token_prefix: Vec<u8>,461462 /// The state of sponsorship of the collection.463 pub sponsorship: SponsorshipState<AccountId>,464465 /// Collection limits.466 pub limits: CollectionLimits,467468 /// Collection permissions.469 pub permissions: CollectionPermissions,470471 /// Token property permissions.472 pub token_property_permissions: Vec<PropertyKeyPermission>,473474 /// Collection properties.475 pub properties: Vec<Property>,476477 /// Is collection read only.478 pub read_only: bool,479480 /// Extra collection flags481 #[version(2.., upper(RpcCollectionFlags {foreign: false, erc721metadata: false}))]482 pub flags: RpcCollectionFlags,483}484485/// Data used for create collection.486///487/// All fields are wrapped in [`Option`], where `None` means chain default.488#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, Derivative, MaxEncodedLen)]489#[derivative(Debug, Default(bound = ""))]490pub struct CreateCollectionData<AccountId> {491 /// Collection mode.492 #[derivative(Default(value = "CollectionMode::NFT"))]493 pub mode: CollectionMode,494495 /// Access mode.496 pub access: Option<AccessMode>,497498 /// Collection name.499 pub name: CollectionName,500501 /// Collection description.502 pub description: CollectionDescription,503504 /// Token prefix.505 pub token_prefix: CollectionTokenPrefix,506507 /// Pending collection sponsor.508 pub pending_sponsor: Option<AccountId>,509510 /// Collection limits.511 pub limits: Option<CollectionLimits>,512513 /// Collection permissions.514 pub permissions: Option<CollectionPermissions>,515516 /// Token property permissions.517 pub token_property_permissions: CollectionPropertiesPermissionsVec,518519 /// Collection properties.520 pub properties: CollectionPropertiesVec,521}522523/// Bounded vector of properties permissions. Max length is [`MAX_PROPERTIES_PER_ITEM`].524// TODO: maybe rename to PropertiesPermissionsVec525pub type CollectionPropertiesPermissionsVec =526 BoundedVec<PropertyKeyPermission, ConstU32<MAX_PROPERTIES_PER_ITEM>>;527528/// Bounded vector of properties. Max length is [`MAX_PROPERTIES_PER_ITEM`].529pub type CollectionPropertiesVec = BoundedVec<Property, ConstU32<MAX_PROPERTIES_PER_ITEM>>;530531/// Limits and restrictions of a collection.532///533/// All fields are wrapped in [`Option`], where `None` means chain default.534///535/// Update with `pallet_common::Pallet::clamp_limits`.536// IMPORTANT: When adding/removing fields from this struct - don't forget to also537#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]538#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]539// When adding/removing fields from this struct - don't forget to also update with `pallet_common::Pallet::clamp_limits`.540// TODO: move `pallet_common::Pallet::clamp_limits` into `impl CollectionLimits`.541// TODO: may be remove [`Option`] and **pub** from fields and create struct with default values.542pub struct CollectionLimits {543 /// How many tokens can a user have on one account.544 /// * Default - [`ACCOUNT_TOKEN_OWNERSHIP_LIMIT`].545 /// * Limit - [`MAX_TOKEN_OWNERSHIP`].546 pub account_token_ownership_limit: Option<u32>,547548 /// How many bytes of data are available for sponsorship.549 /// * Default - [`CUSTOM_DATA_LIMIT`].550 /// * Limit - [`CUSTOM_DATA_LIMIT`].551 pub sponsored_data_size: Option<u32>,552553 // FIXME should we delete this or repurpose it?554 /// Times in how many blocks we sponsor data.555 ///556 /// If is `Some(v)` then **setVariableMetadata** is sponsored if there is `v` block between transactions.557 ///558 /// * Default - [`SponsoringDisabled`](SponsoringRateLimit::SponsoringDisabled).559 /// * Limit - [`MAX_SPONSOR_TIMEOUT`].560 ///561 /// In any case, chain default: [`SponsoringRateLimit::SponsoringDisabled`]562 pub sponsored_data_rate_limit: Option<SponsoringRateLimit>,563 /// Maximum amount of tokens inside the collection. Chain default: [`COLLECTION_TOKEN_LIMIT`]564565 /// How many tokens can be mined into this collection.566 ///567 /// * Default - [`COLLECTION_TOKEN_LIMIT`].568 /// * Limit - [`COLLECTION_TOKEN_LIMIT`].569 pub token_limit: Option<u32>,570571 /// Timeouts for transfer sponsoring.572 ///573 /// * Default574 /// - **Fungible** - [`FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT`]575 /// - **NFT** - [`NFT_SPONSOR_TRANSFER_TIMEOUT`]576 /// - **Refungible** - [`REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT`]577 /// * Limit - [`MAX_SPONSOR_TIMEOUT`].578 pub sponsor_transfer_timeout: Option<u32>,579580 /// Timeout for sponsoring an approval in passed blocks.581 ///582 /// * Default - [`SPONSOR_APPROVE_TIMEOUT`].583 /// * Limit - [`MAX_SPONSOR_TIMEOUT`].584 pub sponsor_approve_timeout: Option<u32>,585586 /// Whether the collection owner of the collection can send tokens (which belong to other users).587 ///588 /// * Default - **false**.589 pub owner_can_transfer: Option<bool>,590591 /// Can the collection owner burn other people's tokens.592 ///593 /// * Default - **true**.594 pub owner_can_destroy: Option<bool>,595596 /// Is it possible to send tokens from this collection between users.597 ///598 /// * Default - **true**.599 pub transfers_enabled: Option<bool>,600}601602impl CollectionLimits {603 pub fn with_default_limits(collection_type: CollectionMode) -> Self {604 CollectionLimits {605 account_token_ownership_limit: Some(ACCOUNT_TOKEN_OWNERSHIP_LIMIT),606 sponsored_data_size: Some(CUSTOM_DATA_LIMIT),607 sponsored_data_rate_limit: Some(SponsoringRateLimit::SponsoringDisabled),608 token_limit: Some(COLLECTION_TOKEN_LIMIT),609 sponsor_transfer_timeout: match collection_type {610 CollectionMode::NFT => Some(NFT_SPONSOR_TRANSFER_TIMEOUT),611 CollectionMode::ReFungible => Some(REFUNGIBLE_SPONSOR_TRANSFER_TIMEOUT),612 CollectionMode::Fungible(_) => Some(FUNGIBLE_SPONSOR_TRANSFER_TIMEOUT),613 },614 sponsor_approve_timeout: Some(SPONSOR_APPROVE_TIMEOUT),615 owner_can_transfer: Some(false),616 owner_can_destroy: Some(true),617 transfers_enabled: Some(true),618 }619 }620621 /// Get effective value for [`account_token_ownership_limit`](self.account_token_ownership_limit).622 pub fn account_token_ownership_limit(&self) -> u32 {623 self.account_token_ownership_limit624 .unwrap_or(ACCOUNT_TOKEN_OWNERSHIP_LIMIT)625 .min(MAX_TOKEN_OWNERSHIP)626 }627628 /// Get effective value for [`sponsored_data_size`](self.sponsored_data_size).629 pub fn sponsored_data_size(&self) -> u32 {630 self.sponsored_data_size631 .unwrap_or(CUSTOM_DATA_LIMIT)632 .min(CUSTOM_DATA_LIMIT)633 }634635 /// Get effective value for [`token_limit`](self.token_limit).636 pub fn token_limit(&self) -> u32 {637 self.token_limit638 .unwrap_or(COLLECTION_TOKEN_LIMIT)639 .min(COLLECTION_TOKEN_LIMIT)640 }641642 // TODO: may be replace u32 to mode?643 /// Get effective value for [`sponsor_transfer_timeout`](self.sponsor_transfer_timeout).644 pub fn sponsor_transfer_timeout(&self, default: u32) -> u32 {645 self.sponsor_transfer_timeout646 .unwrap_or(default)647 .min(MAX_SPONSOR_TIMEOUT)648 }649650 /// Get effective value for [`sponsor_approve_timeout`](self.sponsor_approve_timeout).651 pub fn sponsor_approve_timeout(&self) -> u32 {652 self.sponsor_approve_timeout653 .unwrap_or(SPONSOR_APPROVE_TIMEOUT)654 .min(MAX_SPONSOR_TIMEOUT)655 }656657 /// Get effective value for [`owner_can_transfer`](self.owner_can_transfer).658 pub fn owner_can_transfer(&self) -> bool {659 self.owner_can_transfer.unwrap_or(false)660 }661662 /// Get effective value for [`owner_can_transfer_instaled`](self.owner_can_transfer_instaled).663 pub fn owner_can_transfer_instaled(&self) -> bool {664 self.owner_can_transfer.is_some()665 }666667 /// Get effective value for [`owner_can_destroy`](self.owner_can_destroy).668 pub fn owner_can_destroy(&self) -> bool {669 self.owner_can_destroy.unwrap_or(true)670 }671672 /// Get effective value for [`transfers_enabled`](self.transfers_enabled).673 pub fn transfers_enabled(&self) -> bool {674 self.transfers_enabled.unwrap_or(true)675 }676677 /// Get effective value for [`sponsored_data_rate_limit`](self.sponsored_data_rate_limit).678 pub fn sponsored_data_rate_limit(&self) -> Option<u32> {679 match self680 .sponsored_data_rate_limit681 .unwrap_or(SponsoringRateLimit::SponsoringDisabled)682 {683 SponsoringRateLimit::SponsoringDisabled => None,684 SponsoringRateLimit::Blocks(v) => Some(v.min(MAX_SPONSOR_TIMEOUT)),685 }686 }687}688689/// Permissions on certain operations within a collection.690///691/// Some fields are wrapped in [`Option`], where `None` means chain default.692///693/// Update with `pallet_common::Pallet::clamp_permissions`.694#[derive(Encode, Decode, Debug, Default, Clone, PartialEq, TypeInfo, MaxEncodedLen)]695#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]696// When adding/removing fields from this struct - don't forget to also update `pallet_common::Pallet::clamp_permissions`.697// TODO: move `pallet_common::Pallet::clamp_permissions` into `impl CollectionPermissions`.698pub struct CollectionPermissions {699 /// Access mode.700 ///701 /// * Default - [`AccessMode::Normal`].702 pub access: Option<AccessMode>,703704 /// Minting allowance.705 ///706 /// * Default - **false**.707 pub mint_mode: Option<bool>,708709 /// Permissions for nesting.710 ///711 /// * Default712 /// - `token_owner` - **false**713 /// - `collection_admin` - **false**714 /// - `restricted` - **None**715 pub nesting: Option<NestingPermissions>,716}717718impl CollectionPermissions {719 /// Get effective value for [`access`](self.access).720 pub fn access(&self) -> AccessMode {721 self.access.unwrap_or(AccessMode::Normal)722 }723724 /// Get effective value for [`mint_mode`](self.mint_mode).725 pub fn mint_mode(&self) -> bool {726 self.mint_mode.unwrap_or(false)727 }728729 /// Get effective value for [`nesting`](self.nesting).730 pub fn nesting(&self) -> &NestingPermissions {731 static DEFAULT: NestingPermissions = NestingPermissions {732 token_owner: false,733 collection_admin: false,734 restricted: None,735 #[cfg(feature = "runtime-benchmarks")]736 permissive: false,737 };738 self.nesting.as_ref().unwrap_or(&DEFAULT)739 }740}741742/// Inner set for collections allowed to nest.743type OwnerRestrictedSetInner = BoundedBTreeSet<CollectionId, ConstU32<16>>;744745/// Wraper for collections set allowing nest.746#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]747#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]748#[derivative(Debug)]749pub struct OwnerRestrictedSet(750 #[cfg_attr(feature = "serde1", serde(with = "bounded::set_serde"))]751 #[derivative(Debug(format_with = "bounded::set_debug"))]752 pub OwnerRestrictedSetInner,753);754755impl OwnerRestrictedSet {756 /// Create new set.757 pub fn new() -> Self {758 Self(Default::default())759 }760}761impl core::ops::Deref for OwnerRestrictedSet {762 type Target = OwnerRestrictedSetInner;763 fn deref(&self) -> &Self::Target {764 &self.0765 }766}767impl core::ops::DerefMut for OwnerRestrictedSet {768 fn deref_mut(&mut self) -> &mut Self::Target {769 &mut self.0770 }771}772773/// Part of collection permissions, if set, defines who is able to nest tokens into other tokens.774#[derive(Encode, Decode, Clone, PartialEq, TypeInfo, MaxEncodedLen, Derivative)]775#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]776#[derivative(Debug)]777pub struct NestingPermissions {778 /// Owner of token can nest tokens under it.779 pub token_owner: bool,780 /// Admin of token collection can nest tokens under token.781 pub collection_admin: bool,782 /// If set - only tokens from specified collections can be nested.783 pub restricted: Option<OwnerRestrictedSet>,784785 #[cfg(feature = "runtime-benchmarks")]786 /// Anyone can nest tokens, mutually exclusive with `token_owner`, `admin`.787 pub permissive: bool,788}789790/// Enum denominating how often can sponsoring occur if it is enabled.791///792/// Used for [`collection limits`](CollectionLimits).793#[derive(Encode, Decode, Debug, Clone, Copy, PartialEq, TypeInfo, MaxEncodedLen)]794#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]795pub enum SponsoringRateLimit {796 /// Sponsoring is disabled, and the collection sponsor will not pay for transactions797 SponsoringDisabled,798 /// Once per how many blocks can sponsorship of a transaction type occur799 Blocks(u32),800}801802/// Data used to describe an NFT at creation.803#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]804#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]805#[derivative(Debug)]806pub struct CreateNftData {807 /// Key-value pairs used to describe the token as metadata808 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]809 #[derivative(Debug(format_with = "bounded::vec_debug"))]810 /// Properties that wil be assignet to created item.811 pub properties: CollectionPropertiesVec,812}813814/// Data used to describe a Fungible token at creation.815#[derive(Encode, Decode, MaxEncodedLen, Default, Debug, Clone, PartialEq, TypeInfo)]816#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]817pub struct CreateFungibleData {818 /// Number of fungible coins minted819 pub value: u128,820}821822/// Data used to describe a Refungible token at creation.823#[derive(Encode, Decode, MaxEncodedLen, Default, PartialEq, Clone, Derivative, TypeInfo)]824#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]825#[derivative(Debug)]826pub struct CreateReFungibleData {827 /// Number of pieces the RFT is split into828 pub pieces: u128,829830 /// Key-value pairs used to describe the token as metadata831 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]832 #[derivative(Debug(format_with = "bounded::vec_debug"))]833 pub properties: CollectionPropertiesVec,834}835836// TODO: remove this.837#[derive(Encode, Decode, Debug, Clone, PartialEq, TypeInfo, MaxEncodedLen)]838#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]839pub enum MetaUpdatePermission {840 ItemOwner,841 Admin,842 None,843}844845/// Enum holding data used for creation of all three item types.846/// Unified data for create item.847#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]848#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]849pub enum CreateItemData {850 /// Data for create NFT.851 NFT(CreateNftData),852 /// Data for create Fungible item.853 Fungible(CreateFungibleData),854 /// Data for create ReFungible item.855 ReFungible(CreateReFungibleData),856}857858/// Extended data for create NFT.859#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]860#[derivative(Debug)]861pub struct CreateNftExData<CrossAccountId> {862 /// Properties that wil be assignet to created item.863 #[derivative(Debug(format_with = "bounded::vec_debug"))]864 pub properties: CollectionPropertiesVec,865866 /// Owner of creating item.867 pub owner: CrossAccountId,868}869870/// Extended data for create ReFungible item.871#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]872#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]873pub struct CreateRefungibleExMultipleOwners<CrossAccountId> {874 #[derivative(Debug(format_with = "bounded::map_debug"))]875 pub users: BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,876 #[derivative(Debug(format_with = "bounded::vec_debug"))]877 pub properties: CollectionPropertiesVec,878}879880/// Extended data for create ReFungible item.881#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]882#[derivative(Debug(bound = "CrossAccountId: fmt::Debug"))]883pub struct CreateRefungibleExSingleOwner<CrossAccountId> {884 pub user: CrossAccountId,885 pub pieces: u128,886 #[derivative(Debug(format_with = "bounded::vec_debug"))]887 pub properties: CollectionPropertiesVec,888}889890/// Unified extended data for creating item.891#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, TypeInfo, Derivative)]892#[derivative(Debug(bound = "CrossAccountId: fmt::Debug + Ord"))]893pub enum CreateItemExData<CrossAccountId> {894 /// Extended data for create NFT.895 NFT(896 #[derivative(Debug(format_with = "bounded::vec_debug"))]897 BoundedVec<CreateNftExData<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,898 ),899900 /// Extended data for create Fungible item.901 Fungible(902 #[derivative(Debug(format_with = "bounded::map_debug"))]903 BoundedBTreeMap<CrossAccountId, u128, ConstU32<MAX_ITEMS_PER_BATCH>>,904 ),905906 /// Extended data for create ReFungible item in case of907 /// many tokens, each may have only one owner908 RefungibleMultipleItems(909 #[derivative(Debug(format_with = "bounded::vec_debug"))]910 BoundedVec<CreateRefungibleExSingleOwner<CrossAccountId>, ConstU32<MAX_ITEMS_PER_BATCH>>,911 ),912913 /// Extended data for create ReFungible item in case of914 /// single token, which may have many owners915 RefungibleMultipleOwners(CreateRefungibleExMultipleOwners<CrossAccountId>),916}917918impl From<CreateNftData> for CreateItemData {919 fn from(item: CreateNftData) -> Self {920 CreateItemData::NFT(item)921 }922}923924impl From<CreateReFungibleData> for CreateItemData {925 fn from(item: CreateReFungibleData) -> Self {926 CreateItemData::ReFungible(item)927 }928}929930impl From<CreateFungibleData> for CreateItemData {931 fn from(item: CreateFungibleData) -> Self {932 CreateItemData::Fungible(item)933 }934}935936/// Token's address, dictated by its collection and token IDs.937#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]938#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]939// todo possibly rename to be used generally as an address pair940pub struct TokenChild {941 /// Token id.942 pub token: TokenId,943944 /// Collection id.945 pub collection: CollectionId,946}947948/// Collection statistics.949#[derive(Encode, Decode, MaxEncodedLen, PartialEq, Clone, Debug, TypeInfo)]950#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]951pub struct CollectionStats {952 /// Number of created items.953 pub created: u32,954955 /// Number of burned items.956 pub destroyed: u32,957958 /// Number of current items.959 pub alive: u32,960}961962/// This type works like [`PhantomData`] but supports generating _scale-info_ descriptions to generate node metadata.963#[derive(Encode, Decode, Clone, Debug)]964#[cfg_attr(feature = "std", derive(PartialEq))]965pub struct PhantomType<T>(core::marker::PhantomData<T>);966967impl<T: TypeInfo + 'static> TypeInfo for PhantomType<T> {968 type Identity = PhantomType<T>;969970 fn type_info() -> scale_info::Type {971 use scale_info::{972 Type, Path,973 build::{FieldsBuilder, UnnamedFields},974 form::MetaForm,975 type_params,976 };977 Type::builder()978 .path(Path::new("up_data_structs", "PhantomType"))979 .type_params(type_params!(T))980 .composite(981 <FieldsBuilder<MetaForm, UnnamedFields>>::default().field(|b| b.ty::<[T; 0]>()),982 )983 }984}985impl<T> MaxEncodedLen for PhantomType<T> {986 fn max_encoded_len() -> usize {987 0988 }989}990991/// Bounded vector of bytes.992pub type BoundedBytes<S> = BoundedVec<u8, S>;993994/// Extra properties for external collections.995pub type AuxPropertyValue = BoundedBytes<ConstU32<MAX_AUX_PROPERTY_VALUE_LENGTH>>;996997/// Property key.998pub type PropertyKey = BoundedBytes<ConstU32<MAX_PROPERTY_KEY_LENGTH>>;9991000/// Property value.1001pub type PropertyValue = BoundedBytes<ConstU32<MAX_PROPERTY_VALUE_LENGTH>>;10021003/// Property permission.1004#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone, Default)]1005#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1006pub struct PropertyPermission {1007 /// Permission to change the property and property permission.1008 ///1009 /// If it **false** then you can not change corresponding property even if [`collection_admin`] and [`token_owner`] are **true**.1010 pub mutable: bool,10111012 /// Change permission for the collection administrator.1013 pub collection_admin: bool,10141015 /// Permission to change the property for the owner of the token.1016 pub token_owner: bool,1017}10181019impl PropertyPermission {1020 /// Creates mutable property permission but changes restricted for collection admin and token owner.1021 pub fn none() -> Self {1022 Self {1023 mutable: true,1024 collection_admin: false,1025 token_owner: false,1026 }1027 }1028}10291030/// Property is simpl key-value record.1031#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, MaxEncodedLen)]1032#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1033pub struct Property {1034 /// Property key.1035 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1036 pub key: PropertyKey,10371038 /// Property value.1039 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1040 pub value: PropertyValue,1041}10421043impl Into<(PropertyKey, PropertyValue)> for Property {1044 fn into(self) -> (PropertyKey, PropertyValue) {1045 (self.key, self.value)1046 }1047}10481049/// Record for proprty key permission.1050#[derive(Encode, Decode, TypeInfo, Debug, MaxEncodedLen, PartialEq, Clone)]1051#[cfg_attr(feature = "serde1", derive(Serialize, Deserialize))]1052pub struct PropertyKeyPermission {1053 /// Key.1054 #[cfg_attr(feature = "serde1", serde(with = "bounded::vec_serde"))]1055 pub key: PropertyKey,10561057 /// Permission.1058 pub permission: PropertyPermission,1059}10601061impl Into<(PropertyKey, PropertyPermission)> for PropertyKeyPermission {1062 fn into(self) -> (PropertyKey, PropertyPermission) {1063 (self.key, self.permission)1064 }1065}10661067/// Errors for properties actions.1068#[derive(Debug)]1069pub enum PropertiesError {1070 /// The space allocated for properties has run out.1071 ///1072 /// * Limit for colection - [`MAX_COLLECTION_PROPERTIES_SIZE`].1073 /// * Limit for token - [`MAX_TOKEN_PROPERTIES_SIZE`].1074 NoSpaceForProperty,10751076 /// The property limit has been reached.1077 ///1078 /// * Limit - [`MAX_PROPERTIES_PER_ITEM`].1079 PropertyLimitReached,10801081 /// Property key contains not allowed character.1082 InvalidCharacterInPropertyKey,10831084 /// Property key length is too long.1085 ///1086 /// * Limit - [`MAX_PROPERTY_KEY_LENGTH`].1087 PropertyKeyIsTooLong,10881089 /// Property key is empty.1090 EmptyPropertyKey,1091}10921093/// Token owner error: it could be either `NotFound` ot `MultipleOwners`.1094#[derive(Debug)]1095pub enum TokenOwnerError {1096 NotFound,1097 MultipleOwners,1098}10991100/// Marker for scope of property.1101///1102/// Scoped property can't be changed by user. Used for external collections.1103#[derive(Encode, Decode, MaxEncodedLen, TypeInfo, PartialEq, Clone, Copy)]1104pub enum PropertyScope {1105 None,1106 Rmrk,1107}11081109impl PropertyScope {1110 /// Apply scope to property key.1111 pub fn apply(self, key: PropertyKey) -> Result<PropertyKey, PropertiesError> {1112 let scope_str: &[u8] = match self {1113 Self::None => return Ok(key),1114 Self::Rmrk => b"rmrk",1115 };11161117 [scope_str, b":", key.as_slice()]1118 .concat()1119 .try_into()1120 .map_err(|_| PropertiesError::PropertyKeyIsTooLong)1121 }1122}11231124/// Trait for operate with properties.1125pub trait TrySetProperty: Sized {1126 type Value;11271128 /// Try to set property with scope.1129 fn try_scoped_set(1130 &mut self,1131 scope: PropertyScope,1132 key: PropertyKey,1133 value: Self::Value,1134 ) -> Result<Option<Self::Value>, PropertiesError>;11351136 /// Try to set property with scope from iterator.1137 fn try_scoped_set_from_iter<I, KV>(1138 &mut self,1139 scope: PropertyScope,1140 iter: I,1141 ) -> Result<(), PropertiesError>1142 where1143 I: Iterator<Item = KV>,1144 KV: Into<(PropertyKey, Self::Value)>,1145 {1146 for kv in iter {1147 let (key, value) = kv.into();1148 self.try_scoped_set(scope, key, value)?;1149 }11501151 Ok(())1152 }11531154 /// Try to set property.1155 fn try_set(1156 &mut self,1157 key: PropertyKey,1158 value: Self::Value,1159 ) -> Result<Option<Self::Value>, PropertiesError> {1160 self.try_scoped_set(PropertyScope::None, key, value)1161 }11621163 /// Try to set property from iterator.1164 fn try_set_from_iter<I, KV>(&mut self, iter: I) -> Result<(), PropertiesError>1165 where1166 I: Iterator<Item = KV>,1167 KV: Into<(PropertyKey, Self::Value)>,1168 {1169 self.try_scoped_set_from_iter(PropertyScope::None, iter)1170 }1171}11721173/// Wrapped map for storing properties.1174#[derive(Encode, Decode, TypeInfo, Derivative, Clone, PartialEq, MaxEncodedLen)]1175#[derivative(Default(bound = ""))]1176pub struct PropertiesMap<Value>(1177 BoundedBTreeMap<PropertyKey, Value, ConstU32<MAX_PROPERTIES_PER_ITEM>>,1178);11791180impl<Value> PropertiesMap<Value> {1181 /// Create new property map.1182 pub fn new() -> Self {1183 Self(BoundedBTreeMap::new())1184 }11851186 /// Remove property from map.1187 pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<Value>, PropertiesError> {1188 Self::check_property_key(key)?;11891190 Ok(self.0.remove(key))1191 }11921193 /// Get property with appropriate key from map.1194 pub fn get(&self, key: &PropertyKey) -> Option<&Value> {1195 self.0.get(key)1196 }11971198 /// Check if map contains key.1199 pub fn contains_key(&self, key: &PropertyKey) -> bool {1200 self.0.contains_key(key)1201 }12021203 /// Check if map contains key with key validation.1204 fn check_property_key(key: &PropertyKey) -> Result<(), PropertiesError> {1205 if key.is_empty() {1206 return Err(PropertiesError::EmptyPropertyKey);1207 }12081209 for byte in key.as_slice().iter() {1210 let byte = *byte;12111212 if !byte.is_ascii_alphanumeric() && byte != b'_' && byte != b'-' && byte != b'.' {1213 return Err(PropertiesError::InvalidCharacterInPropertyKey);1214 }1215 }12161217 Ok(())1218 }12191220 pub fn values(&self) -> impl Iterator<Item = &Value> {1221 self.0.values()1222 }1223}12241225impl<Value> IntoIterator for PropertiesMap<Value> {1226 type Item = (PropertyKey, Value);1227 type IntoIter = <1228 BoundedBTreeMap<1229 PropertyKey,1230 Value,1231 ConstU32<MAX_PROPERTIES_PER_ITEM>1232 > as IntoIterator1233 >::IntoIter;12341235 fn into_iter(self) -> Self::IntoIter {1236 self.0.into_iter()1237 }1238}12391240impl<Value> TrySetProperty for PropertiesMap<Value> {1241 type Value = Value;12421243 fn try_scoped_set(1244 &mut self,1245 scope: PropertyScope,1246 key: PropertyKey,1247 value: Self::Value,1248 ) -> Result<Option<Self::Value>, PropertiesError> {1249 Self::check_property_key(&key)?;12501251 let key = scope.apply(key)?;1252 self.01253 .try_insert(key, value)1254 .map_err(|_| PropertiesError::PropertyLimitReached)1255 }1256}12571258/// Alias for property permissions map.1259pub type PropertiesPermissionMap = PropertiesMap<PropertyPermission>;12601261/// Wrapper for properties map with consumed space control.1262#[derive(Encode, Decode, TypeInfo, Clone, PartialEq, MaxEncodedLen)]1263pub struct Properties {1264 map: PropertiesMap<PropertyValue>,1265 consumed_space: u32,1266 space_limit: u32,1267}12681269impl Properties {1270 /// Create new properies container.1271 pub fn new(space_limit: u32) -> Self {1272 Self {1273 map: PropertiesMap::new(),1274 consumed_space: 0,1275 space_limit,1276 }1277 }12781279 /// Remove propery with appropiate key.1280 pub fn remove(&mut self, key: &PropertyKey) -> Result<Option<PropertyValue>, PropertiesError> {1281 let value = self.map.remove(key)?;12821283 if let Some(ref value) = value {1284 let value_len = value.len() as u32;1285 self.consumed_space -= value_len;1286 }12871288 Ok(value)1289 }12901291 /// Get property with appropriate key.1292 pub fn get(&self, key: &PropertyKey) -> Option<&PropertyValue> {1293 self.map.get(key)1294 }12951296 /// Recomputes the consumed space for the current properties state.1297 /// Needed to repair a token due to a bug fixed in the [PR #733](https://github.com/UniqueNetwork/unique-chain/pull/773).1298 pub fn recompute_consumed_space(&mut self) {1299 self.consumed_space = self.map.values().map(|value| value.len() as u32).sum();1300 }1301}13021303impl IntoIterator for Properties {1304 type Item = (PropertyKey, PropertyValue);1305 type IntoIter = <PropertiesMap<PropertyValue> as IntoIterator>::IntoIter;13061307 fn into_iter(self) -> Self::IntoIter {1308 self.map.into_iter()1309 }1310}13111312impl TrySetProperty for Properties {1313 type Value = PropertyValue;13141315 fn try_scoped_set(1316 &mut self,1317 scope: PropertyScope,1318 key: PropertyKey,1319 value: Self::Value,1320 ) -> Result<Option<Self::Value>, PropertiesError> {1321 let value_len = value.len();13221323 if self.consumed_space as usize + value_len > self.space_limit as usize1324 && !cfg!(feature = "runtime-benchmarks")1325 {1326 return Err(PropertiesError::NoSpaceForProperty);1327 }13281329 let value_len = value_len as u32;1330 let old_value = self.map.try_scoped_set(scope, key, value)?;13311332 let old_value_len = old_value.as_ref().map(|v| v.len() as u32).unwrap_or(0);13331334 if value_len > old_value_len {1335 self.consumed_space += value_len - old_value_len;1336 } else {1337 self.consumed_space -= old_value_len - value_len;1338 }13391340 Ok(old_value)1341 }1342}13431344/// Utility struct for using in `StorageMap`.1345pub struct CollectionProperties;13461347impl Get<Properties> for CollectionProperties {1348 fn get() -> Properties {1349 Properties::new(MAX_COLLECTION_PROPERTIES_SIZE)1350 }1351}13521353/// Utility struct for using in `StorageMap`.1354pub struct TokenProperties;13551356impl Get<Properties> for TokenProperties {1357 fn get() -> Properties {1358 Properties::new(MAX_TOKEN_PROPERTIES_SIZE)1359 }1360}primitives/rmrk-rpc/CHANGELOG.mddiffbeforeafterboth--- a/primitives/rmrk-rpc/CHANGELOG.md
+++ /dev/null
@@ -1,10 +0,0 @@
-<!-- bureaucrate goes here -->
-## [v0.0.2] 2022-08-16
-
-### Other changes
-
-- build: Upgrade polkadot to v0.9.27 2c498572636f2b34d53b1c51b7283a761a7dc90a
-
-- build: Upgrade polkadot to v0.9.26 85515e54c4ca1b82a2630034e55dcc804c643bf8
-
-- build: Upgrade polkadot to v0.9.25 cdfb9bdc7b205ff1b5134f034ef9973d769e5e6b
\ No newline at end of file
primitives/rmrk-rpc/Cargo.tomldiffbeforeafterboth--- a/primitives/rmrk-rpc/Cargo.toml
+++ /dev/null
@@ -1,16 +0,0 @@
-[package]
-edition = "2021"
-license = ""
-name = "rmrk-rpc"
-version = "0.0.2"
-
-[dependencies]
-codec = { workspace = true }
-rmrk-traits = { workspace = true }
-sp-api = { workspace = true }
-sp-runtime = { workspace = true }
-sp-std = { workspace = true }
-
-[features]
-default = ["std"]
-std = ["codec/std", "rmrk-traits/std", "sp-api/std", "sp-runtime/std", "sp-std/std"]
primitives/rmrk-rpc/src/lib.rsdiffbeforeafterboth--- a/primitives/rmrk-rpc/src/lib.rs
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-#![cfg_attr(not(feature = "std"), no_std)]
-
-use sp_api::{Encode, Decode};
-use sp_std::vec::Vec;
-use sp_runtime::DispatchError;
-use rmrk_traits::{primitives::*, NftChild};
-
-pub type Result<T> = core::result::Result<T, DispatchError>;
-
-pub type RpcString = Vec<u8>;
-
-pub type PropertyKey = RpcString;
-
-pub type ThemeName = RpcString;
-
-sp_api::decl_runtime_apis! {
- pub trait RmrkApi<
- AccountId,
- CollectionInfo,
- NftInfo,
- ResourceInfo,
- PropertyInfo,
- BaseInfo,
- PartType,
- Theme
- >
- where
- AccountId: Encode,
- CollectionInfo: Decode,
- NftInfo: Decode,
- ResourceInfo: Decode,
- PropertyInfo: Decode,
- BaseInfo: Decode,
- PartType: Decode,
- Theme: Decode,
- {
- fn last_collection_idx() -> Result<CollectionId>;
-
- fn collection_by_id(id: CollectionId) -> Result<Option<CollectionInfo>>;
-
- fn nft_by_id(collection_id: CollectionId, nft_id: NftId) -> Result<Option<NftInfo>>;
-
- fn account_tokens(account_id: AccountId, collection_id: CollectionId) -> Result<Vec<NftId>>;
-
- fn nft_children(collection_id: CollectionId, nft_id: NftId) -> Result<Vec<NftChild>>;
-
- fn collection_properties(collection_id: CollectionId, filter_keys: Option<Vec<PropertyKey>>) -> Result<Vec<PropertyInfo>>;
-
- fn nft_properties(collection_id: CollectionId, nft_id: NftId, filter_keys: Option<Vec<PropertyKey>>) -> Result<Vec<PropertyInfo>>;
-
- fn nft_resources(collection_id: CollectionId, nft_id: NftId) -> Result<Vec<ResourceInfo>>;
-
- fn nft_resource_priority(collection_id: CollectionId, nft_id: NftId, resource_id: ResourceId) -> Result<Option<u32>>;
-
- fn base(base_id: BaseId) -> Result<Option<BaseInfo>>;
-
- fn base_parts(base_id: BaseId) -> Result<Vec<PartType>>;
-
- fn theme_names(base_id: BaseId) -> Result<Vec<ThemeName>>;
-
- fn theme(base_id: BaseId, theme_name: ThemeName, filter_keys: Option<Vec<PropertyKey>>) -> Result<Option<Theme>>;
- }
-}
primitives/rmrk-traits/Cargo.tomldiffbeforeafterboth--- a/primitives/rmrk-traits/Cargo.toml
+++ /dev/null
@@ -1,21 +0,0 @@
-[package]
-authors = ["RMRK Team", "Unique Network <support@uniquenetwork.io>"]
-description = "RMRK proxy data structs definitions"
-edition = "2021"
-homepage = "https://unique.network"
-license = 'GPLv3'
-name = "rmrk-traits"
-repository = 'https://github.com/UniqueNetwork/unique-chain'
-version = "0.1.0"
-
-[dependencies]
-# Note: `package = "parity-scale-codec"` must be supplied since the `Encode` macro searches for it.
-codec = { workspace = true, package = "parity-scale-codec" }
-
-scale-info = { workspace = true }
-serde = { workspace = true, optional = true }
-
-[features]
-default = ["std"]
-serde1 = ["serde/alloc"]
-std = ["codec/std", "serde/std", "serde1"]
primitives/rmrk-traits/src/base.rsdiffbeforeafterboth--- a/primitives/rmrk-traits/src/base.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (C) 2021-2022 RMRK
-// This file is part of rmrk-substrate.
-// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
-
-use codec::{Decode, Encode, MaxEncodedLen};
-use scale_info::TypeInfo;
-
-#[cfg(feature = "std")]
-use serde::Serialize;
-
-#[cfg(feature = "std")]
-use crate::serialize;
-
-#[cfg_attr(feature = "std", derive(PartialEq, Eq, Serialize))]
-#[derive(Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
-#[cfg_attr(
- feature = "std",
- serde(bound = r#"
- AccountId: Serialize,
- BoundedString: AsRef<[u8]>
- "#)
-)]
-pub struct BaseInfo<AccountId, BoundedString> {
- /// Original creator of the Base
- pub issuer: AccountId,
-
- /// Specifies how an NFT should be rendered, ie "svg"
- #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]
- pub base_type: BoundedString,
-
- /// User provided symbol during Base creation
- #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]
- pub symbol: BoundedString,
-}
primitives/rmrk-traits/src/collection.rsdiffbeforeafterboth--- a/primitives/rmrk-traits/src/collection.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (C) 2021-2022 RMRK
-// This file is part of rmrk-substrate.
-// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
-
-use codec::{Decode, Encode, MaxEncodedLen};
-use scale_info::TypeInfo;
-
-#[cfg(feature = "std")]
-use serde::Serialize;
-
-#[cfg(feature = "std")]
-use crate::serialize;
-
-#[cfg_attr(feature = "std", derive(PartialEq, Eq, Serialize))]
-#[derive(Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
-#[cfg_attr(
- feature = "std",
- serde(bound = r#"
- AccountId: Serialize,
- BoundedString: AsRef<[u8]>,
- BoundedSymbol: AsRef<[u8]>
- "#)
-)]
-pub struct CollectionInfo<BoundedString, BoundedSymbol, AccountId> {
- /// Current bidder and bid price.
- pub issuer: AccountId,
-
- #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]
- pub metadata: BoundedString,
- pub max: Option<u32>,
-
- #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]
- pub symbol: BoundedSymbol,
- pub nfts_count: u32,
-}
primitives/rmrk-traits/src/lib.rsdiffbeforeafterboth--- a/primitives/rmrk-traits/src/lib.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (C) 2021-2022 RMRK
-// This file is part of rmrk-substrate.
-// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
-
-#![cfg_attr(not(feature = "std"), no_std)]
-
-pub mod base;
-pub mod collection;
-pub mod nft;
-pub mod part;
-pub mod property;
-pub mod resource;
-pub mod theme;
-
-#[cfg(feature = "std")]
-mod serialize;
-
-pub use base::BaseInfo;
-pub use part::{EquippableList, FixedPart, PartType, SlotPart};
-pub use theme::{Theme, ThemeProperty};
-pub use collection::CollectionInfo;
-pub use nft::{AccountIdOrCollectionNftTuple, NftInfo, RoyaltyInfo, NftChild};
-pub use property::PropertyInfo;
-pub use resource::{BasicResource, ComposableResource, ResourceInfo, ResourceTypes, SlotResource};
-pub mod primitives {
- pub type CollectionId = u32;
- pub type ResourceId = u32;
- pub type NftId = u32;
- pub type BaseId = u32;
- pub type SlotId = u32;
- pub type PartId = u32;
- pub type ZIndex = u32;
-}
primitives/rmrk-traits/src/nft.rsdiffbeforeafterboth--- a/primitives/rmrk-traits/src/nft.rs
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (C) 2021-2022 RMRK
-// This file is part of rmrk-substrate.
-// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
-
-use codec::{Decode, Encode, MaxEncodedLen};
-use scale_info::TypeInfo;
-
-#[cfg(feature = "std")]
-use serde::Serialize;
-
-#[cfg(feature = "std")]
-use crate::serialize;
-
-use crate::primitives::*;
-
-#[derive(Encode, Decode, Eq, PartialEq, Copy, Clone, Debug, TypeInfo, MaxEncodedLen)]
-#[cfg_attr(feature = "std", derive(Serialize))]
-pub enum AccountIdOrCollectionNftTuple<AccountId> {
- AccountId(AccountId),
- CollectionAndNftTuple(CollectionId, NftId),
-}
-
-/// Royalty information (recipient and amount)
-#[cfg_attr(feature = "std", derive(PartialEq, Eq, Serialize))]
-#[derive(Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
-pub struct RoyaltyInfo<AccountId, RoyaltyAmount> {
- /// Recipient (AccountId) of the royalty
- pub recipient: AccountId,
- /// Amount (Permill) of the royalty
- pub amount: RoyaltyAmount,
-}
-
-/// Nft info.
-#[cfg_attr(feature = "std", derive(PartialEq, Eq, Serialize))]
-#[derive(Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
-#[cfg_attr(
- feature = "std",
- serde(bound = r#"
- AccountId: Serialize,
- RoyaltyAmount: Serialize,
- BoundedString: AsRef<[u8]>
- "#)
-)]
-pub struct NftInfo<AccountId, RoyaltyAmount, BoundedString> {
- /// The owner of the NFT, can be either an Account or a tuple (CollectionId, NftId)
- pub owner: AccountIdOrCollectionNftTuple<AccountId>,
- /// Royalty (optional)
- pub royalty: Option<RoyaltyInfo<AccountId, RoyaltyAmount>>,
-
- /// Arbitrary data about an instance, e.g. IPFS hash
- #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]
- pub metadata: BoundedString,
-
- /// Equipped state
- pub equipped: bool,
- /// Pending state (if sent to NFT)
- pub pending: bool,
-}
-
-#[cfg_attr(feature = "std", derive(PartialEq, Eq, Serialize))]
-#[derive(Encode, Decode, TypeInfo, MaxEncodedLen)]
-pub struct NftChild {
- pub collection_id: CollectionId,
- pub nft_id: NftId,
-}
primitives/rmrk-traits/src/part.rsdiffbeforeafterboth--- a/primitives/rmrk-traits/src/part.rs
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (C) 2021-2022 RMRK
-// This file is part of rmrk-substrate.
-// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
-
-use codec::{Decode, Encode, MaxEncodedLen};
-use scale_info::TypeInfo;
-
-#[cfg(feature = "std")]
-use serde::Serialize;
-
-#[cfg(feature = "std")]
-use crate::serialize;
-
-use crate::primitives::*;
-
-#[cfg_attr(feature = "std", derive(Serialize))]
-#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, Eq, MaxEncodedLen)]
-#[cfg_attr(feature = "std", serde(bound = "BoundedString: AsRef<[u8]>"))]
-pub struct FixedPart<BoundedString> {
- pub id: PartId,
- pub z: ZIndex,
-
- #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]
- pub src: BoundedString,
-}
-
-#[cfg_attr(feature = "std", derive(Serialize))]
-#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, Eq, MaxEncodedLen)]
-#[cfg_attr(
- feature = "std",
- serde(bound = "BoundedCollectionList: AsRef<[CollectionId]>")
-)]
-pub enum EquippableList<BoundedCollectionList> {
- All,
- Empty,
- Custom(#[cfg_attr(feature = "std", serde(with = "serialize::vec"))] BoundedCollectionList),
-}
-
-#[cfg_attr(feature = "std", derive(Serialize))]
-#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, Eq, MaxEncodedLen)]
-#[cfg_attr(
- feature = "std",
- serde(bound = r#"
- BoundedString: AsRef<[u8]>,
- BoundedCollectionList: AsRef<[CollectionId]>
- "#)
-)]
-pub struct SlotPart<BoundedString, BoundedCollectionList> {
- pub id: PartId,
- pub equippable: EquippableList<BoundedCollectionList>,
-
- #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]
- pub src: BoundedString,
-
- pub z: ZIndex,
-}
-
-#[cfg_attr(feature = "std", derive(Serialize))]
-#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq, Eq, MaxEncodedLen)]
-#[cfg_attr(
- feature = "std",
- serde(bound = r#"
- BoundedString: AsRef<[u8]>,
- BoundedCollectionList: AsRef<[CollectionId]>
- "#)
-)]
-pub enum PartType<BoundedString, BoundedCollectionList> {
- FixedPart(FixedPart<BoundedString>),
- SlotPart(SlotPart<BoundedString, BoundedCollectionList>),
-}
-
-impl<BoundedString, BoundedCollectionList> PartType<BoundedString, BoundedCollectionList> {
- pub fn id(&self) -> PartId {
- match self {
- Self::FixedPart(part) => part.id,
- Self::SlotPart(part) => part.id,
- }
- }
-
- pub fn src(&self) -> &BoundedString {
- match self {
- Self::FixedPart(part) => &part.src,
- Self::SlotPart(part) => &part.src,
- }
- }
-
- pub fn z_index(&self) -> ZIndex {
- match self {
- Self::FixedPart(part) => part.z,
- Self::SlotPart(part) => part.z,
- }
- }
-}
primitives/rmrk-traits/src/property.rsdiffbeforeafterboth--- a/primitives/rmrk-traits/src/property.rs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (C) 2021-2022 RMRK
-// This file is part of rmrk-substrate.
-// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
-
-use codec::{Decode, Encode};
-use scale_info::TypeInfo;
-
-#[cfg(feature = "std")]
-use serde::Serialize;
-
-#[cfg(feature = "std")]
-use crate::serialize;
-
-#[cfg_attr(feature = "std", derive(Serialize))]
-#[derive(Encode, Decode, PartialEq, TypeInfo)]
-#[cfg_attr(
- feature = "std",
- serde(bound = r#"
- BoundedKey: AsRef<[u8]>,
- BoundedValue: AsRef<[u8]>
- "#)
-)]
-pub struct PropertyInfo<BoundedKey, BoundedValue> {
- /// Key of the property
- #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]
- pub key: BoundedKey,
-
- /// Value of the property
- #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]
- pub value: BoundedValue,
-}
primitives/rmrk-traits/src/resource.rsdiffbeforeafterboth--- a/primitives/rmrk-traits/src/resource.rs
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright (C) 2021-2022 RMRK
-// This file is part of rmrk-substrate.
-// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
-
-use codec::{Decode, Encode, MaxEncodedLen};
-use scale_info::TypeInfo;
-
-#[cfg(feature = "std")]
-use serde::Serialize;
-
-#[cfg(feature = "std")]
-use crate::serialize;
-
-use crate::primitives::*;
-
-#[derive(Encode, Decode, Eq, PartialEq, Clone, Debug, TypeInfo, MaxEncodedLen)]
-#[cfg_attr(feature = "std", derive(Serialize))]
-#[cfg_attr(feature = "std", serde(bound = "BoundedString: AsRef<[u8]>"))]
-pub struct BasicResource<BoundedString> {
- /// If the resource is Media, the base property is absent. Media src should be a URI like an
- /// IPFS hash.
- #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]
- pub src: Option<BoundedString>,
-
- /// Reference to IPFS location of metadata
- #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]
- pub metadata: Option<BoundedString>,
-
- /// Optional location or identier of license
- #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]
- pub license: Option<BoundedString>,
-
- /// If the resource has the thumb property, this will be a URI to a thumbnail of the given
- /// resource. For example, if we have a composable NFT like a Kanaria bird, the resource is
- /// complex and too detailed to show in a search-results page or a list. Also, if a bird owns
- /// another bird, showing the full render of one bird inside the other's inventory might be a
- /// bit of a strain on the browser. For this reason, the thumb value can contain a URI to an
- /// image that is lighter and faster to load but representative of this resource.
- #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]
- pub thumb: Option<BoundedString>,
-}
-
-#[derive(Encode, Decode, Eq, PartialEq, Clone, Debug, TypeInfo, MaxEncodedLen)]
-#[cfg_attr(feature = "std", derive(Serialize))]
-#[cfg_attr(
- feature = "std",
- serde(bound = r#"
- BoundedString: AsRef<[u8]>,
- BoundedParts: AsRef<[PartId]>
- "#)
-)]
-pub struct ComposableResource<BoundedString, BoundedParts> {
- /// If a resource is composed, it will have an array of parts that compose it
- #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]
- pub parts: BoundedParts,
-
- /// A Base is uniquely identified by the combination of the word `base`, its minting block
- /// number, and user provided symbol during Base creation, glued by dashes `-`, e.g.
- /// base-4477293-kanaria_superbird.
- pub base: BaseId,
-
- /// If the resource is Media, the base property is absent. Media src should be a URI like an
- /// IPFS hash.
- #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]
- pub src: Option<BoundedString>,
-
- /// Reference to IPFS location of metadata
- #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]
- pub metadata: Option<BoundedString>,
-
- /// If the resource has the slot property, it was designed to fit into a specific Base's slot.
- /// The baseslot will be composed of two dot-delimited values, like so:
- /// "base-4477293-kanaria_superbird.machine_gun_scope". This means: "This resource is
- /// compatible with the machine_gun_scope slot of base base-4477293-kanaria_superbird
-
- /// Optional location or identier of license
- #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]
- pub license: Option<BoundedString>,
-
- /// If the resource has the thumb property, this will be a URI to a thumbnail of the given
- /// resource. For example, if we have a composable NFT like a Kanaria bird, the resource is
- /// complex and too detailed to show in a search-results page or a list. Also, if a bird owns
- /// another bird, showing the full render of one bird inside the other's inventory might be a
- /// bit of a strain on the browser. For this reason, the thumb value can contain a URI to an
- /// image that is lighter and faster to load but representative of this resource.
- #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]
- pub thumb: Option<BoundedString>,
-}
-
-#[derive(Encode, Decode, Eq, PartialEq, Clone, Debug, TypeInfo, MaxEncodedLen)]
-#[cfg_attr(feature = "std", derive(Serialize))]
-#[cfg_attr(feature = "std", serde(bound = "BoundedString: AsRef<[u8]>"))]
-pub struct SlotResource<BoundedString> {
- /// A Base is uniquely identified by the combination of the word `base`, its minting block
- /// number, and user provided symbol during Base creation, glued by dashes `-`, e.g.
- /// base-4477293-kanaria_superbird.
- pub base: BaseId,
-
- /// If the resource is Media, the base property is absent. Media src should be a URI like an
- /// IPFS hash.
- #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]
- pub src: Option<BoundedString>,
-
- /// Reference to IPFS location of metadata
- #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]
- pub metadata: Option<BoundedString>,
-
- /// If the resource has the slot property, it was designed to fit into a specific Base's slot.
- /// The baseslot will be composed of two dot-delimited values, like so:
- /// "base-4477293-kanaria_superbird.machine_gun_scope". This means: "This resource is
- /// compatible with the machine_gun_scope slot of base base-4477293-kanaria_superbird
- pub slot: SlotId,
-
- /// The license field, if present, should contain a link to a license (IPFS or static HTTP
- /// url), or an identifier, like RMRK_nocopy or ipfs://ipfs/someHashOfLicense.
- #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]
- pub license: Option<BoundedString>,
-
- /// If the resource has the thumb property, this will be a URI to a thumbnail of the given
- /// resource. For example, if we have a composable NFT like a Kanaria bird, the resource is
- /// complex and too detailed to show in a search-results page or a list. Also, if a bird owns
- /// another bird, showing the full render of one bird inside the other's inventory might be a
- /// bit of a strain on the browser. For this reason, the thumb value can contain a URI to an
- /// image that is lighter and faster to load but representative of this resource.
- #[cfg_attr(feature = "std", serde(with = "serialize::opt_vec"))]
- pub thumb: Option<BoundedString>,
-}
-
-#[derive(Encode, Decode, Eq, PartialEq, Clone, Debug, TypeInfo, MaxEncodedLen)]
-#[cfg_attr(feature = "std", derive(Serialize))]
-#[cfg_attr(
- feature = "std",
- serde(bound = r#"
- BoundedString: AsRef<[u8]>,
- BoundedParts: AsRef<[PartId]>
- "#)
-)]
-pub enum ResourceTypes<BoundedString, BoundedParts> {
- Basic(BasicResource<BoundedString>),
- Composable(ComposableResource<BoundedString, BoundedParts>),
- Slot(SlotResource<BoundedString>),
-}
-
-#[derive(Encode, Decode, Eq, PartialEq, Clone, Debug, TypeInfo, MaxEncodedLen)]
-#[cfg_attr(feature = "std", derive(Serialize))]
-#[cfg_attr(
- feature = "std",
- serde(bound = r#"
- BoundedString: AsRef<[u8]>,
- BoundedParts: AsRef<[PartId]>
- "#)
-)]
-pub struct ResourceInfo<BoundedString, BoundedParts> {
- /// ID is a unique identifier for a resource across all those of a single NFT.
- /// The combination of a collection ID, an NFT ID, and the resource ID must be
- /// unique across the entire RMRK ecosystem.
- //#[cfg_attr(feature = "std", serde(with = "serialize::vec"))]
- pub id: ResourceId,
-
- /// Resource type and the accordingly structured data stored
- pub resource: ResourceTypes<BoundedString, BoundedParts>,
-
- /// If resource is sent to non-rootowned NFT, pending will be false and need to be accepted
- pub pending: bool,
-
- /// If resource removal request is sent by non-rootowned NFT, pending will be true and need to be accepted
- pub pending_removal: bool,
-}
primitives/rmrk-traits/src/serialize.rsdiffbeforeafterboth--- a/primitives/rmrk-traits/src/serialize.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (C) 2021-2022 RMRK
-// This file is part of rmrk-substrate.
-// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
-
-use core::convert::AsRef;
-use serde::ser::{self, Serialize};
-
-pub mod vec {
- use super::*;
-
- pub fn serialize<D, V, C>(value: &C, serializer: D) -> Result<D::Ok, D::Error>
- where
- D: ser::Serializer,
- V: Serialize,
- C: AsRef<[V]>,
- {
- value.as_ref().serialize(serializer)
- }
-}
-
-pub mod opt_vec {
- use super::*;
-
- pub fn serialize<D, V, C>(value: &Option<C>, serializer: D) -> Result<D::Ok, D::Error>
- where
- D: ser::Serializer,
- V: Serialize,
- C: AsRef<[V]>,
- {
- match value {
- Some(value) => super::vec::serialize(value, serializer),
- None => serializer.serialize_none(),
- }
- }
-}
primitives/rmrk-traits/src/theme.rsdiffbeforeafterboth--- a/primitives/rmrk-traits/src/theme.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (C) 2021-2022 RMRK
-// This file is part of rmrk-substrate.
-// License: Apache 2.0 modified by RMRK, see https://github.com/rmrk-team/rmrk-substrate/blob/main/LICENSE
-
-use codec::{Decode, Encode};
-use scale_info::TypeInfo;
-
-#[cfg(feature = "std")]
-use serde::Serialize;
-
-#[cfg(feature = "std")]
-use crate::serialize;
-
-#[cfg_attr(feature = "std", derive(Eq, Serialize))]
-#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq)]
-#[cfg_attr(
- feature = "std",
- serde(bound = r#"
- BoundedString: AsRef<[u8]>,
- PropertyList: AsRef<[ThemeProperty<BoundedString>]>,
- "#)
-)]
-pub struct Theme<BoundedString, PropertyList> {
- /// Name of the theme
- #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]
- pub name: BoundedString,
-
- /// Theme properties
- #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]
- pub properties: PropertyList,
- /// Inheritability
- pub inherit: bool,
-}
-
-#[cfg_attr(feature = "std", derive(Eq, Serialize))]
-#[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq)]
-#[cfg_attr(feature = "std", serde(bound = "BoundedString: AsRef<[u8]>"))]
-pub struct ThemeProperty<BoundedString> {
- /// Key of the property
- #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]
- pub key: BoundedString,
-
- /// Value of the property
- #[cfg_attr(feature = "std", serde(with = "serialize::vec"))]
- pub value: BoundedString,
-}
runtime/common/config/pallets/mod.rsdiffbeforeafterboth--- a/runtime/common/config/pallets/mod.rs
+++ b/runtime/common/config/pallets/mod.rs
@@ -35,9 +35,6 @@
};
use sp_arithmetic::Perbill;
-#[cfg(feature = "rmrk")]
-pub mod rmrk;
-
#[cfg(feature = "scheduler")]
pub mod scheduler;
runtime/common/config/pallets/rmrk.rsdiffbeforeafterboth--- a/runtime/common/config/pallets/rmrk.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-use crate::{Runtime, RuntimeEvent};
-
-impl pallet_proxy_rmrk_core::Config for Runtime {
- type WeightInfo = pallet_proxy_rmrk_core::weights::SubstrateWeight<Self>;
- type RuntimeEvent = RuntimeEvent;
-}
-
-impl pallet_proxy_rmrk_equip::Config for Runtime {
- type WeightInfo = pallet_proxy_rmrk_equip::weights::SubstrateWeight<Self>;
- type RuntimeEvent = RuntimeEvent;
-}
runtime/common/construct_runtime.rsdiffbeforeafterboth--- a/runtime/common/construct_runtime.rs
+++ b/runtime/common/construct_runtime.rs
@@ -82,11 +82,9 @@
Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69,
Structure: pallet_structure::{Pallet, Call, Storage, Event<T>} = 70,
- #[cfg(feature = "rmrk")]
- RmrkCore: pallet_proxy_rmrk_core::{Pallet, Call, Storage, Event<T>} = 71,
+ // RmrkCore: pallet_proxy_rmrk_core::{Pallet, Call, Storage, Event<T>} = 71,
- #[cfg(feature = "rmrk")]
- RmrkEquip: pallet_proxy_rmrk_equip::{Pallet, Call, Storage, Event<T>} = 72,
+ // RmrkEquip: pallet_proxy_rmrk_equip::{Pallet, Call, Storage, Event<T>} = 72,
#[cfg(feature = "app-promotion")]
AppPromotion: pallet_app_promotion::{Pallet, Call, Storage, Event<T>} = 73,
runtime/common/maintenance.rsdiffbeforeafterboth--- a/runtime/common/maintenance.rs
+++ b/runtime/common/maintenance.rs
@@ -70,11 +70,6 @@
#[cfg(feature = "scheduler")]
RuntimeCall::Scheduler(_) => Err(TransactionValidityError::Invalid(InvalidTransaction::Call)),
- #[cfg(feature = "rmrk")]
- RuntimeCall::RmrkCore(_) | RuntimeCall::RmrkEquip(_) => {
- Err(TransactionValidityError::Invalid(InvalidTransaction::Call))
- }
-
#[cfg(feature = "app-promotion")]
RuntimeCall::AppPromotion(_) => {
Err(TransactionValidityError::Invalid(InvalidTransaction::Call))
runtime/common/runtime_apis.rsdiffbeforeafterboth--- a/runtime/common/runtime_apis.rs
+++ b/runtime/common/runtime_apis.rs
@@ -231,149 +231,6 @@
}
}
- impl rmrk_rpc::RmrkApi<
- Block,
- AccountId,
- RmrkCollectionInfo<AccountId>,
- RmrkInstanceInfo<AccountId>,
- RmrkResourceInfo,
- RmrkPropertyInfo,
- RmrkBaseInfo<AccountId>,
- RmrkPartType,
- RmrkTheme
- > for Runtime {
- fn last_collection_idx() -> Result<RmrkCollectionId, DispatchError> {
- #[cfg(feature = "rmrk")]
- return pallet_proxy_rmrk_core::rpc::last_collection_idx::<Runtime>();
-
- #[cfg(not(feature = "rmrk"))]
- return unsupported!();
- }
-
- #[allow(unused_variables)]
- fn collection_by_id(collection_id: RmrkCollectionId) -> Result<Option<RmrkCollectionInfo<AccountId>>, DispatchError> {
- #[cfg(feature = "rmrk")]
- return pallet_proxy_rmrk_core::rpc::collection_by_id::<Runtime>(collection_id);
-
- #[cfg(not(feature = "rmrk"))]
- return unsupported!();
- }
-
- #[allow(unused_variables)]
- fn nft_by_id(collection_id: RmrkCollectionId, nft_by_id: RmrkNftId) -> Result<Option<RmrkInstanceInfo<AccountId>>, DispatchError> {
- #[cfg(feature = "rmrk")]
- return pallet_proxy_rmrk_core::rpc::nft_by_id::<Runtime>(collection_id, nft_by_id);
-
- #[cfg(not(feature = "rmrk"))]
- return unsupported!();
- }
-
- #[allow(unused_variables)]
- fn account_tokens(account_id: AccountId, collection_id: RmrkCollectionId) -> Result<Vec<RmrkNftId>, DispatchError> {
- #[cfg(feature = "rmrk")]
- return pallet_proxy_rmrk_core::rpc::account_tokens::<Runtime>(account_id, collection_id);
-
- #[cfg(not(feature = "rmrk"))]
- return unsupported!();
- }
-
- #[allow(unused_variables)]
- fn nft_children(collection_id: RmrkCollectionId, nft_id: RmrkNftId) -> Result<Vec<RmrkNftChild>, DispatchError> {
- #[cfg(feature = "rmrk")]
- return pallet_proxy_rmrk_core::rpc::nft_children::<Runtime>(collection_id, nft_id);
-
- #[cfg(not(feature = "rmrk"))]
- return unsupported!();
- }
-
- #[allow(unused_variables)]
- fn collection_properties(
- collection_id: RmrkCollectionId,
- filter_keys: Option<Vec<RmrkPropertyKey>>
- ) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
- #[cfg(feature = "rmrk")]
- return pallet_proxy_rmrk_core::rpc::collection_properties::<Runtime>(collection_id, filter_keys);
-
- #[cfg(not(feature = "rmrk"))]
- return unsupported!();
- }
-
- #[allow(unused_variables)]
- fn nft_properties(
- collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
- filter_keys: Option<Vec<RmrkPropertyKey>>
- ) -> Result<Vec<RmrkPropertyInfo>, DispatchError> {
- #[cfg(feature = "rmrk")]
- return pallet_proxy_rmrk_core::rpc::nft_properties::<Runtime>(collection_id, nft_id, filter_keys);
-
- #[cfg(not(feature = "rmrk"))]
- return unsupported!();
- }
-
- #[allow(unused_variables)]
- fn nft_resources(collection_id: RmrkCollectionId,nft_id: RmrkNftId) -> Result<Vec<RmrkResourceInfo>, DispatchError> {
- #[cfg(feature = "rmrk")]
- return pallet_proxy_rmrk_core::rpc::nft_resources::<Runtime>(collection_id, nft_id);
-
- #[cfg(not(feature = "rmrk"))]
- return unsupported!();
- }
-
- #[allow(unused_variables)]
- fn nft_resource_priority(
- collection_id: RmrkCollectionId,
- nft_id: RmrkNftId,
- resource_id: RmrkResourceId
- ) -> Result<Option<u32>, DispatchError> {
- #[cfg(feature = "rmrk")]
- return pallet_proxy_rmrk_core::rpc::nft_resource_priority::<Runtime>(collection_id, nft_id, resource_id);
-
- #[cfg(not(feature = "rmrk"))]
- return unsupported!();
- }
-
- #[allow(unused_variables)]
- fn base(base_id: RmrkBaseId) -> Result<Option<RmrkBaseInfo<AccountId>>, DispatchError> {
- #[cfg(feature = "rmrk")]
- return pallet_proxy_rmrk_equip::rpc::base::<Runtime>(base_id);
-
- #[cfg(not(feature = "rmrk"))]
- return unsupported!();
- }
-
- #[allow(unused_variables)]
- fn base_parts(base_id: RmrkBaseId) -> Result<Vec<RmrkPartType>, DispatchError> {
- #[cfg(feature = "rmrk")]
- return pallet_proxy_rmrk_equip::rpc::base_parts::<Runtime>(base_id);
-
- #[cfg(not(feature = "rmrk"))]
- return unsupported!();
- }
-
- #[allow(unused_variables)]
- fn theme_names(base_id: RmrkBaseId) -> Result<Vec<RmrkThemeName>, DispatchError> {
- #[cfg(feature = "rmrk")]
- return pallet_proxy_rmrk_equip::rpc::theme_names::<Runtime>(base_id);
-
- #[cfg(not(feature = "rmrk"))]
- return unsupported!();
- }
-
- #[allow(unused_variables)]
- fn theme(
- base_id: RmrkBaseId,
- theme_name: RmrkThemeName,
- filter_keys: Option<Vec<RmrkPropertyKey>>
- ) -> Result<Option<RmrkTheme>, DispatchError> {
- #[cfg(feature = "rmrk")]
- return pallet_proxy_rmrk_equip::rpc::theme::<Runtime>(base_id, theme_name, filter_keys);
-
- #[cfg(not(feature = "rmrk"))]
- return unsupported!();
- }
- }
-
impl sp_api::Core<Block> for Runtime {
fn version() -> RuntimeVersion {
VERSION
@@ -701,13 +558,7 @@
#[cfg(feature = "scheduler")]
list_benchmark!(list, extra, pallet_unique_scheduler_v2, Scheduler);
-
- #[cfg(feature = "rmrk")]
- list_benchmark!(list, extra, pallet_proxy_rmrk_core, RmrkCore);
- #[cfg(feature = "rmrk")]
- list_benchmark!(list, extra, pallet_proxy_rmrk_equip, RmrkEquip);
-
#[cfg(feature = "collator-selection")]
list_benchmark!(list, extra, pallet_collator_selection, CollatorSelection);
@@ -771,12 +622,6 @@
#[cfg(feature = "scheduler")]
add_benchmark!(params, batches, pallet_unique_scheduler_v2, Scheduler);
-
- #[cfg(feature = "rmrk")]
- add_benchmark!(params, batches, pallet_proxy_rmrk_core, RmrkCore);
-
- #[cfg(feature = "rmrk")]
- add_benchmark!(params, batches, pallet_proxy_rmrk_equip, RmrkEquip);
#[cfg(feature = "collator-selection")]
add_benchmark!(params, batches, pallet_collator_selection, CollatorSelection);
runtime/opal/Cargo.tomldiffbeforeafterboth--- a/runtime/opal/Cargo.toml
+++ b/runtime/opal/Cargo.toml
@@ -41,8 +41,6 @@
'pallet-inflation/runtime-benchmarks',
'pallet-maintenance/runtime-benchmarks',
'pallet-nonfungible/runtime-benchmarks',
- 'pallet-proxy-rmrk-core/runtime-benchmarks',
- 'pallet-proxy-rmrk-equip/runtime-benchmarks',
'pallet-refungible/runtime-benchmarks',
'pallet-structure/runtime-benchmarks',
'pallet-timestamp/runtime-benchmarks',
@@ -95,8 +93,6 @@
'pallet-identity/std',
'pallet-inflation/std',
'pallet-nonfungible/std',
- 'pallet-proxy-rmrk-core/std',
- 'pallet-proxy-rmrk-equip/std',
'pallet-randomness-collective-flip/std',
'pallet-refungible/std',
'pallet-structure/std',
@@ -108,7 +104,6 @@
'pallet-unique-scheduler-v2/std',
'pallet-unique/std',
'parachain-info/std',
- 'rmrk-rpc/std',
'serde',
'sp-api/std',
'sp-block-builder/std',
@@ -176,8 +171,6 @@
'pallet-inflation/try-runtime',
'pallet-maintenance/try-runtime',
'pallet-nonfungible/try-runtime',
- 'pallet-proxy-rmrk-core/try-runtime',
- 'pallet-proxy-rmrk-equip/try-runtime',
'pallet-randomness-collective-flip/try-runtime',
'pallet-refungible/try-runtime',
'pallet-structure/try-runtime',
@@ -197,7 +190,6 @@
foreign-assets = []
pallet-test-utils = []
refungible = []
-rmrk = []
scheduler = []
################################################################################
@@ -282,14 +274,11 @@
pallet-inflation = { workspace = true }
pallet-maintenance = { workspace = true }
pallet-nonfungible = { workspace = true }
-pallet-proxy-rmrk-core = { workspace = true }
-pallet-proxy-rmrk-equip = { workspace = true }
pallet-refungible = { workspace = true }
pallet-structure = { workspace = true }
pallet-unique = { workspace = true }
pallet-unique-scheduler-v2 = { workspace = true }
precompile-utils-macro = { workspace = true }
-rmrk-rpc = { workspace = true }
scale-info = { workspace = true }
up-common = { workspace = true }
up-data-structs = { workspace = true }
runtime/quartz/Cargo.tomldiffbeforeafterboth--- a/runtime/quartz/Cargo.toml
+++ b/runtime/quartz/Cargo.toml
@@ -42,8 +42,6 @@
'pallet-inflation/runtime-benchmarks',
'pallet-maintenance/runtime-benchmarks',
'pallet-nonfungible/runtime-benchmarks',
- 'pallet-proxy-rmrk-core/runtime-benchmarks',
- 'pallet-proxy-rmrk-equip/runtime-benchmarks',
'pallet-refungible/runtime-benchmarks',
'pallet-structure/runtime-benchmarks',
'pallet-timestamp/runtime-benchmarks',
@@ -95,8 +93,6 @@
'pallet-fungible/std',
'pallet-inflation/std',
'pallet-nonfungible/std',
- 'pallet-proxy-rmrk-core/std',
- 'pallet-proxy-rmrk-equip/std',
'pallet-randomness-collective-flip/std',
'pallet-refungible/std',
'pallet-structure/std',
@@ -107,7 +103,6 @@
'pallet-treasury/std',
'pallet-unique/std',
'parachain-info/std',
- 'rmrk-rpc/std',
'serde',
'sp-api/std',
'sp-block-builder/std',
@@ -171,8 +166,6 @@
'pallet-inflation/try-runtime',
'pallet-maintenance/try-runtime',
'pallet-nonfungible/try-runtime',
- 'pallet-proxy-rmrk-core/try-runtime',
- 'pallet-proxy-rmrk-equip/try-runtime',
'pallet-randomness-collective-flip/try-runtime',
'pallet-refungible/try-runtime',
'pallet-structure/try-runtime',
@@ -189,7 +182,6 @@
collator-selection = []
foreign-assets = []
refungible = []
-rmrk = []
scheduler = []
################################################################################
@@ -228,7 +220,6 @@
pallet-xcm = { workspace = true }
parachain-info = { workspace = true }
polkadot-parachain = { workspace = true }
-rmrk-rpc = { workspace = true }
smallvec = { workspace = true }
sp-api = { workspace = true }
sp-arithmetic = { workspace = true }
@@ -260,8 +251,6 @@
pallet-identity = { workspace = true }
pallet-inflation = { workspace = true }
pallet-nonfungible = { workspace = true }
-pallet-proxy-rmrk-core = { workspace = true }
-pallet-proxy-rmrk-equip = { workspace = true }
pallet-refungible = { workspace = true }
pallet-structure = { workspace = true }
pallet-unique = { workspace = true }
runtime/unique/Cargo.tomldiffbeforeafterboth--- a/runtime/unique/Cargo.toml
+++ b/runtime/unique/Cargo.toml
@@ -39,8 +39,6 @@
'pallet-inflation/runtime-benchmarks',
'pallet-maintenance/runtime-benchmarks',
'pallet-nonfungible/runtime-benchmarks',
- 'pallet-proxy-rmrk-core/runtime-benchmarks',
- 'pallet-proxy-rmrk-equip/runtime-benchmarks',
'pallet-refungible/runtime-benchmarks',
'pallet-structure/runtime-benchmarks',
'pallet-timestamp/runtime-benchmarks',
@@ -93,8 +91,6 @@
'pallet-fungible/std',
'pallet-inflation/std',
'pallet-nonfungible/std',
- 'pallet-proxy-rmrk-core/std',
- 'pallet-proxy-rmrk-equip/std',
'pallet-randomness-collective-flip/std',
'pallet-refungible/std',
'pallet-structure/std',
@@ -105,7 +101,6 @@
'pallet-treasury/std',
'pallet-unique/std',
'parachain-info/std',
- 'rmrk-rpc/std',
'sp-api/std',
'sp-block-builder/std',
'sp-core/std',
@@ -169,8 +164,6 @@
'pallet-inflation/try-runtime',
'pallet-maintenance/try-runtime',
'pallet-nonfungible/try-runtime',
- 'pallet-proxy-rmrk-core/try-runtime',
- 'pallet-proxy-rmrk-equip/try-runtime',
'pallet-randomness-collective-flip/try-runtime',
'pallet-refungible/try-runtime',
'pallet-structure/try-runtime',
@@ -187,7 +180,6 @@
collator-selection = []
foreign-assets = []
refungible = []
-rmrk = []
scheduler = []
################################################################################
@@ -255,12 +247,9 @@
pallet-identity = { workspace = true }
pallet-inflation = { workspace = true }
pallet-nonfungible = { workspace = true }
-pallet-proxy-rmrk-core = { workspace = true }
-pallet-proxy-rmrk-equip = { workspace = true }
pallet-refungible = { workspace = true }
pallet-structure = { workspace = true }
pallet-unique = { workspace = true }
-rmrk-rpc = { workspace = true }
scale-info = { workspace = true }
up-common = { workspace = true }
up-data-structs = { workspace = true }
tests/package.jsondiffbeforeafterboth--- a/tests/package.json
+++ b/tests/package.json
@@ -43,7 +43,6 @@
"testEthFractionalizer": "yarn setup && mocha --timeout 9999999 -r ts-node/register './**/eth/fractionalizer/**/*.*test.ts'",
"testEthMarketplace": "yarn setup && mocha --timeout 9999999 -r ts-node/register './**/eth/marketplace/**/*.*test.ts'",
"testEvent": "yarn setup && mocha --timeout 9999999 -r ts-node/register ./src/check-event/*.*test.ts",
- "testRmrk": "yarn setup && mocha --timeout 9999999 -r ts-node/register ./**/rmrk/*.*test.ts",
"testEthPayable": "mocha --timeout 9999999 -r ts-node/register './**/eth/payable.test.ts'",
"testEvmCoder": "mocha --timeout 9999999 -r ts-node/register './**/eth/evmCoder.test.ts'",
"testNesting": "mocha --timeout 9999999 -r ts-node/register ./**/nest.test.ts",
tests/src/.outdated/rmrk/acceptNft.seqtest.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/acceptNft.seqtest.ts
+++ /dev/null
@@ -1,107 +0,0 @@
-import {expect} from 'chai';
-import {getApiConnection} from '../substrate/substrate-api';
-import {
- createCollection,
- mintNft,
- sendNft,
- acceptNft,
-} from './util/tx';
-import {NftIdTuple} from './util/fetch';
-import {isNftChildOfAnother, expectTxFailure, requirePallets, Pallets} from './util/helpers';
-
-describe('integration test: accept NFT', () => {
- let api: any;
- before(async function() {
- api = await getApiConnection();
- await requirePallets(this, [Pallets.RmrkCore]);
- });
-
-
- const alice = '//Alice';
- const bob = '//Bob';
-
- const createTestCollection = async (issuerUri: string) => {
- return await createCollection(
- api,
- issuerUri,
- 'accept-metadata',
- null,
- 'acpt',
- );
- };
-
- it('accept NFT', async () => {
- const ownerAlice = alice;
- const ownerBob = bob;
-
- const aliceCollectionId = await createTestCollection(alice);
- const bobCollectionId = await createTestCollection(bob);
-
- const parentNftId = await mintNft(api, alice, ownerAlice, aliceCollectionId, 'parent-nft-metadata');
- const childNftId = await mintNft(api, bob, ownerBob, bobCollectionId, 'child-nft-metadata');
-
- const newOwnerNFT: NftIdTuple = [aliceCollectionId, parentNftId];
-
- await sendNft(api, 'pending', ownerBob, bobCollectionId, childNftId, newOwnerNFT);
- await acceptNft(api, alice, bobCollectionId, childNftId, newOwnerNFT);
-
- const isChild = await isNftChildOfAnother(api, bobCollectionId, childNftId, newOwnerNFT);
- expect(isChild).to.be.true;
- });
-
- it('[negative] unable to accept NFT by a not-an-owner', async () => {
- const ownerAlice = alice;
- const ownerBob = bob;
-
- const aliceCollectionId = await createTestCollection(alice);
- const bobCollectionId = await createTestCollection(bob);
-
- const parentNftId = await mintNft(api, alice, ownerAlice, aliceCollectionId, 'parent-nft-metadata');
- const childNftId = await mintNft(api, bob, ownerBob, bobCollectionId, 'child-nft-metadata');
-
- const newOwnerNFT: NftIdTuple = [aliceCollectionId, parentNftId];
-
- await sendNft(api, 'pending', ownerBob, bobCollectionId, childNftId, newOwnerNFT);
- const tx = acceptNft(api, bob, bobCollectionId, childNftId, newOwnerNFT);
-
- await expectTxFailure(/rmrkCore\.NoPermission/, tx);
- });
-
- it('[negative] unable to accept non-existing NFT', async () => {
- const collectionId = 0;
- const maxNftId = 0xFFFFFFFF;
-
- const owner = alice;
- const aliceCollectionId = await createTestCollection(alice);
-
- const parentNftId = await mintNft(api, alice, owner, aliceCollectionId, 'parent-nft-metadata');
-
- const newOwnerNFT: NftIdTuple = [aliceCollectionId, parentNftId];
-
- const tx = acceptNft(api, alice, collectionId, maxNftId, newOwnerNFT);
-
- await expectTxFailure(/rmrkCore\.NoAvailableNftId/, tx);
- });
-
- it('[negative] unable to accept NFT which is not sent', async () => {
- const ownerAlice = alice;
- const ownerBob = bob;
-
- const aliceCollectionId = await createTestCollection(alice);
- const bobCollectionId = await createTestCollection(bob);
-
- const parentNftId = await mintNft(api, alice, ownerAlice, aliceCollectionId, 'parent-nft-metadata');
- const childNftId = await mintNft(api, bob, ownerBob, bobCollectionId, 'child-nft-metadata');
-
- const newOwnerNFT: NftIdTuple = [aliceCollectionId, parentNftId];
-
- const tx = acceptNft(api, alice, bobCollectionId, childNftId, newOwnerNFT);
-
- await expectTxFailure(/rmrkCore\.NoPermission/, tx);
-
- const isChild = await isNftChildOfAnother(api, bobCollectionId, childNftId, newOwnerNFT);
- expect(isChild).to.be.false;
- });
-
- after(async() => { await api.disconnect(); });
-});
tests/src/.outdated/rmrk/addResource.seqtest.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/addResource.seqtest.ts
+++ /dev/null
@@ -1,435 +0,0 @@
-import {expect} from 'chai';
-import {getApiConnection} from '../substrate/substrate-api';
-import {NftIdTuple} from './util/fetch';
-import {expectTxFailure, getResourceById, requirePallets, Pallets} from './util/helpers';
-import {
- addNftBasicResource,
- acceptNftResource,
- createCollection,
- mintNft,
- sendNft,
- addNftSlotResource,
- addNftComposableResource,
-} from './util/tx';
-import {RmrkTraitsResourceResourceInfo as ResourceInfo} from '@polkadot/types/lookup';
-
-describe('integration test: add NFT resource', () => {
- const alice = '//Alice';
- const bob = '//Bob';
- const src = 'test-res-src';
- const metadata = 'test-res-metadata';
- const license = 'test-res-license';
- const thumb = 'test-res-thumb';
-
- const nonexistentId = 99999;
-
- let api: any;
- before(async function() {
- api = await getApiConnection();
- await requirePallets(this, [Pallets.RmrkCore]);
- });
-
- it('add resource', async () => {
- const collectionIdAlice = await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const nftAlice = await mintNft(
- api,
- alice,
- alice,
- collectionIdAlice,
- 'nft-metadata',
- );
-
- await addNftBasicResource(
- api,
- alice,
- 'added',
- collectionIdAlice,
- nftAlice,
- src,
- metadata,
- license,
- thumb,
- );
- });
-
- it('add a resource to the nested NFT', async () => {
- const collectionIdAlice = await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const parentNftId = await mintNft(api, alice, alice, collectionIdAlice, 'parent-nft-metadata');
- const childNftId = await mintNft(api, alice, alice, collectionIdAlice, 'child-nft-metadata');
-
- const newOwnerNFT: NftIdTuple = [collectionIdAlice, parentNftId];
-
- await sendNft(api, 'sent', alice, collectionIdAlice, childNftId, newOwnerNFT);
-
- await addNftBasicResource(
- api,
- alice,
- 'added',
- collectionIdAlice,
- childNftId,
- src,
- metadata,
- license,
- thumb,
- );
- });
-
- it('add multiple resources', async () => {
- const collectionIdAlice = await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const nftAlice = await mintNft(
- api,
- alice,
- alice,
- collectionIdAlice,
- 'nft-metadata',
- );
-
- const baseId = 42;
- const slotId = 10;
- const parts = [0, 5, 2];
-
- const resourcesInfo = [];
- const resourceNum = 4;
-
- const checkResource = (resource: ResourceInfo, resType: string, expectedId: number, expected: {
- src: string,
- metadata: string,
- license: string,
- thumb: string
- }) => {
-
- // FIXME A workaround. It seems it is a PolkadotJS bug.
- // All of the following are `false`.
- //
- // console.log('>>> basic:', resource.resource.isBasic);
- // console.log('>>> composable:', resource.resource.isComposable);
- // console.log('>>> slot:', resource.resource.isSlot);
- const resourceJson = (resource.resource.toHuman() as any)[resType];
-
- expect(resource.id.toNumber(), 'Error: Invalid resource Id')
- .to.be.eq(expectedId);
-
- expect(resourceJson.src, 'Error: Invalid resource src')
- .to.be.eq(expected.src);
- expect(resourceJson.metadata, 'Error: Invalid resource metadata')
- .to.be.eq(expected.metadata);
- expect(resourceJson.license, 'Error: Invalid resource license')
- .to.be.eq(expected.license);
- expect(resourceJson.thumb, 'Error: Invalid resource thumb')
- .to.be.eq(expected.thumb);
- };
-
- for (let i = 0; i < resourceNum; i++) {
- resourcesInfo.push({
- src: src + 'r-' + i,
- metadata: metadata + 'r-' + i,
- license: license + 'r-' + i,
- thumb: thumb + 'r-' + i,
- });
- }
-
- const firstBasicResourceId = await addNftBasicResource(
- api,
- alice,
- 'added',
- collectionIdAlice,
- nftAlice,
- resourcesInfo[0].src,
- resourcesInfo[0].metadata,
- resourcesInfo[0].license,
- resourcesInfo[0].thumb,
- );
-
- const secondBasicResourceId = await addNftBasicResource(
- api,
- alice,
- 'added',
- collectionIdAlice,
- nftAlice,
- resourcesInfo[1].src,
- resourcesInfo[1].metadata,
- resourcesInfo[1].license,
- resourcesInfo[1].thumb,
- );
-
- const composableResourceId = await addNftComposableResource(
- api,
- alice,
- 'added',
- collectionIdAlice,
- nftAlice,
- parts,
- baseId,
- resourcesInfo[2].src,
- resourcesInfo[2].metadata,
- resourcesInfo[2].license,
- resourcesInfo[2].thumb,
- );
-
- const slotResourceId = await addNftSlotResource(
- api,
- alice,
- 'added',
- collectionIdAlice,
- nftAlice,
- baseId,
- slotId,
- resourcesInfo[3].src,
- resourcesInfo[3].metadata,
- resourcesInfo[3].license,
- resourcesInfo[3].thumb,
- );
-
- const firstResource = await getResourceById(api, collectionIdAlice, nftAlice, firstBasicResourceId);
- await checkResource(firstResource, 'Basic', firstBasicResourceId, resourcesInfo[0]);
-
- const secondResource = await getResourceById(api, collectionIdAlice, nftAlice, secondBasicResourceId);
- await checkResource(secondResource, 'Basic', secondBasicResourceId, resourcesInfo[1]);
-
- const composableResource = await getResourceById(api, collectionIdAlice, nftAlice, composableResourceId);
- await checkResource(composableResource, 'Composable', composableResourceId, resourcesInfo[2]);
-
- const slotResource = await getResourceById(api, collectionIdAlice, nftAlice, slotResourceId);
- await checkResource(slotResource, 'Slot', slotResourceId, resourcesInfo[3]);
- });
-
- it('[negative]: unable to add a resource to the non-existing NFT', async () => {
- const collectionIdAlice = await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const tx = addNftBasicResource(
- api,
- alice,
- 'added',
- collectionIdAlice,
- nonexistentId,
- src,
- metadata,
- license,
- thumb,
- );
-
- await expectTxFailure(/rmrkCore\.NoAvailableNftId/, tx);
- });
-
- it('[negative]: unable to add a resource by a not-an-owner user', async () => {
- const collectionIdAlice = await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const nftAlice = await mintNft(
- api,
- alice,
- alice,
- collectionIdAlice,
- 'nft-metadata',
- );
-
- const tx = addNftBasicResource(
- api,
- bob,
- 'added',
- collectionIdAlice,
- nftAlice,
- src,
- metadata,
- license,
- thumb,
- );
-
- await expectTxFailure(/rmrkCore\.NoPermission/, tx);
- });
-
- it('[negative]: unable to add a resource to the nested NFT if it isnt root owned by the caller', async () => {
- const collectionIdAlice = await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const parentNftId = await mintNft(api, alice, alice, collectionIdAlice, 'parent-nft-metadata');
- const childNftId = await mintNft(api, alice, alice, collectionIdAlice, 'child-nft-metadata');
-
- const newOwnerNFT: NftIdTuple = [collectionIdAlice, parentNftId];
-
- await sendNft(api, 'sent', alice, collectionIdAlice, childNftId, newOwnerNFT);
-
- const tx = addNftBasicResource(
- api,
- bob,
- 'added',
- collectionIdAlice,
- childNftId,
- src,
- metadata,
- license,
- thumb,
- );
-
- await expectTxFailure(/rmrkCore\.NoPermission/, tx);
- });
-
- it('accept resource', async () => {
- const collectionIdBob = await createCollection(
- api,
- bob,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const nftAlice = await mintNft(
- api,
- bob,
- alice,
- collectionIdBob,
- 'nft-metadata',
- );
-
- const resourceId = await addNftBasicResource(
- api,
- bob,
- 'pending',
- collectionIdBob,
- nftAlice,
- src,
- metadata,
- license,
- thumb,
- );
-
- await acceptNftResource(api, alice, collectionIdBob, nftAlice, resourceId);
- });
-
- it('[negative]: unable to accept a non-existing resource', async () => {
- const collectionIdBob = await createCollection(
- api,
- bob,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const nftAlice = await mintNft(
- api,
- bob,
- alice,
- collectionIdBob,
- 'nft-metadata',
- );
-
- const tx = acceptNftResource(api, alice, collectionIdBob, nftAlice, nonexistentId);
- await expectTxFailure(/rmrkCore\.ResourceDoesntExist/, tx);
- });
-
- it('[negative]: unable to accept a resource by a not-an-NFT-owner user', async () => {
- const collectionIdBob = await createCollection(
- api,
- bob,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const nftAlice = await mintNft(
- api,
- bob,
- alice,
- collectionIdBob,
- 'nft-metadata',
- );
-
- const resourceId = await addNftBasicResource(
- api,
- bob,
- 'pending',
- collectionIdBob,
- nftAlice,
- src,
- metadata,
- license,
- thumb,
- );
-
- const tx = acceptNftResource(api, bob, collectionIdBob, nftAlice, resourceId);
-
- await expectTxFailure(/rmrkCore\.NoPermission/, tx);
- });
-
- it('[negative]: unable to accept a resource to a non-target NFT', async () => {
- const collectionIdBob = await createCollection(
- api,
- bob,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const nftAlice = await mintNft(
- api,
- bob,
- alice,
- collectionIdBob,
- 'nft-metadata',
- );
-
- const wrongNft = await mintNft(
- api,
- bob,
- alice,
- collectionIdBob,
- 'nft-metadata',
- );
-
- const resourceId = await addNftBasicResource(
- api,
- bob,
- 'pending',
- collectionIdBob,
- nftAlice,
- src,
- metadata,
- license,
- thumb,
- );
-
- const tx = acceptNftResource(api, bob, collectionIdBob, wrongNft, resourceId);
-
- await expectTxFailure(/rmrkCore\.ResourceDoesntExist/, tx);
- });
-
-
- after(async() => { await api.disconnect(); });
-});
tests/src/.outdated/rmrk/addTheme.seqtest.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/addTheme.seqtest.ts
+++ /dev/null
@@ -1,129 +0,0 @@
-import {expect} from 'chai';
-import {getApiConnection} from '../substrate/substrate-api';
-import {createBase, addTheme} from './util/tx';
-import {expectTxFailure, requirePallets, Pallets} from './util/helpers';
-import {getThemeNames} from './util/fetch';
-
-describe('integration test: add Theme to Base', () => {
- let api: any;
- before(async function() {
- api = await getApiConnection();
- await requirePallets(this, [Pallets.RmrkEquip]);
- });
-
- const alice = '//Alice';
- const bob = '//Bob';
-
- it('add default theme', async () => {
- const baseId = await createBase(api, alice, 'default-themed-base', 'DTBase', []);
- await addTheme(api, alice, baseId, {
- name: 'default',
- properties: [
- {
- key: 'some-key',
- value: 'some-key-value',
- },
- {
- key: 'another-key',
- value: 'another-key-value',
- },
- ],
- });
- });
-
- it('add default theme and a custom one', async () => {
- const baseId = await createBase(api, alice, '2-themed-base', '2TBase', []);
- await addTheme(api, alice, baseId, {
- name: 'default',
- properties: [
- {
- key: 'default-key',
- value: 'default-key-value',
- },
- ],
- });
- await addTheme(api, alice, baseId, {
- name: 'custom-theme',
- properties: [
- {
- key: 'custom-key-0',
- value: 'custom-key-value-0',
- },
- {
- key: 'custom-key-1',
- value: 'custom-key-value-1',
- },
- ],
- });
- });
-
- it('fetch filtered theme keys', async () => {
- const baseId = await createBase(api, alice, '2-themed-base', '2TBase', []);
- await addTheme(api, alice, baseId, {
- name: 'default',
- properties: [
- {
- key: 'first-key',
- value: 'first-key-value',
- },
- {
- key: 'second-key',
- value: 'second-key-value',
- },
- ],
- }, ['second-key']);
- });
-
- it('fetch theme names', async() => {
- const baseId = await createBase(api, alice, '3-themed-base', '3TBase', []);
- const names = [
- 'default',
- 'first-theme',
- 'second-theme',
- ];
-
- for (let i = 0; i < names.length; i++) {
- await addTheme(api, alice, baseId, {name: names[i], properties: [{key: 'dummy', value: 'dummy'}]});
- }
-
- const fetchedNames = await getThemeNames(api, baseId);
-
- for (let i = 0; i < names.length; i++) {
- const isFound = fetchedNames.find((name) => name === names[i]) !== undefined;
-
- expect(isFound, 'Error: invalid theme names').to.be.true;
- }
- });
-
- it('[negative] unable to add theme to non-existing base', async () => {
- const maxBaseId = 0xFFFFFFFF;
- const tx = addTheme(api, alice, maxBaseId, {
- name: 'default',
- properties: [],
- });
-
- await expectTxFailure(/rmrkEquip\.BaseDoesntExist/, tx);
- });
-
- it('[negative] unable to add custom theme if no default theme', async () => {
- const baseId = await createBase(api, alice, 'no-default-themed-base', 'NDTBase', []);
- const tx = addTheme(api, alice, baseId, {
- name: 'custom-theme',
- properties: [],
- });
-
- await expectTxFailure(/rmrkEquip\.NeedsDefaultThemeFirst/, tx);
- });
-
- it('[negative] unable to add theme by a not-an-owner', async () => {
- const baseId = await createBase(api, alice, 'no-default-themed-base', 'NDTBase', []);
- const tx = addTheme(api, bob, baseId, {
- name: 'default',
- properties: [],
- });
-
- await expectTxFailure(/rmrkEquip\.PermissionError/, tx);
- });
-
- after(async() => { await api.disconnect(); });
-});
tests/src/.outdated/rmrk/burnNft.seqtest.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/burnNft.seqtest.ts
+++ /dev/null
@@ -1,170 +0,0 @@
-import {getApiConnection} from '../substrate/substrate-api';
-import {expectTxFailure, requirePallets, Pallets} from './util/helpers';
-import {NftIdTuple, getChildren} from './util/fetch';
-import {burnNft, createCollection, sendNft, mintNft} from './util/tx';
-
-import chai from 'chai';
-import chaiAsPromised from 'chai-as-promised';
-
-chai.use(chaiAsPromised);
-const expect = chai.expect;
-
-describe('integration test: burn nft', () => {
- const alice = '//Alice';
- const bob = '//Bob';
-
- let api: any;
- before(async function() {
- api = await getApiConnection();
- await requirePallets(this, [Pallets.RmrkCore]);
- });
-
-
- it('burn nft', async () => {
- await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- ).then(async (collectionId) => {
- const nftId = await mintNft(
- api,
- alice,
- alice,
- collectionId,
- 'nft-metadata',
- );
- await burnNft(api, alice, collectionId, nftId);
- });
- });
-
- it('burn nft with children', async () => {
- const collectionId = await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const parentNftId = await mintNft(
- api,
- alice,
- alice,
- collectionId,
- 'nft-metadata',
- );
-
- const childNftId = await mintNft(
- api,
- alice,
- alice,
- collectionId,
- 'nft-metadata',
- );
-
- const newOwnerNFT: NftIdTuple = [collectionId, parentNftId];
-
- await sendNft(api, 'sent', alice, collectionId, childNftId, newOwnerNFT);
-
- const childrenBefore = await getChildren(api, collectionId, parentNftId);
- expect(childrenBefore.length === 1, 'Error: parent NFT should have children')
- .to.be.true;
-
- const child = childrenBefore[0];
- expect(child.collectionId.eq(collectionId), 'Error: invalid child collection Id')
- .to.be.true;
-
- expect(child.nftId.eq(childNftId), 'Error: invalid child NFT Id')
- .to.be.true;
-
- await burnNft(api, alice, collectionId, parentNftId);
-
- const childrenAfter = await getChildren(api, collectionId, parentNftId);
-
- expect(childrenAfter.length === 0, 'Error: children should be burned').to.be.true;
- });
-
- it('burn child nft', async () => {
- const collectionId = await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const parentNftId = await mintNft(
- api,
- alice,
- alice,
- collectionId,
- 'nft-metadata',
- );
-
- const childNftId = await mintNft(
- api,
- alice,
- alice,
- collectionId,
- 'nft-metadata',
- );
-
- const newOwnerNFT: NftIdTuple = [collectionId, parentNftId];
-
- await sendNft(api, 'sent', alice, collectionId, childNftId, newOwnerNFT);
-
- const childrenBefore = await getChildren(api, collectionId, parentNftId);
- expect(childrenBefore.length === 1, 'Error: parent NFT should have children')
- .to.be.true;
-
- const child = childrenBefore[0];
- expect(child.collectionId.eq(collectionId), 'Error: invalid child collection Id')
- .to.be.true;
-
- expect(child.nftId.eq(childNftId), 'Error: invalid child NFT Id')
- .to.be.true;
-
- await burnNft(api, alice, collectionId, childNftId);
-
- const childrenAfter = await getChildren(api, collectionId, parentNftId);
-
- expect(childrenAfter.length === 0, 'Error: children should be burned').to.be.true;
- });
-
- it('[negative] burn non-existing NFT', async () => {
- await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- ).then(async (collectionId) => {
- const tx = burnNft(api, alice, collectionId, 99999);
- await expectTxFailure(/rmrkCore\.NoAvailableNftId/, tx);
- });
- });
-
- it('[negative] burn not an owner NFT user', async () => {
- await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- ).then(async (collectionId) => {
- const nftId = await mintNft(
- api,
- alice,
- alice,
- collectionId,
- 'nft-metadata',
- );
- const tx = burnNft(api, bob, collectionId, nftId);
- await expectTxFailure(/rmrkCore\.NoPermission/, tx);
- });
- });
-
- after(async() => { await api.disconnect(); });
-});
tests/src/.outdated/rmrk/changeCollectionIssuer.seqtest.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/changeCollectionIssuer.seqtest.ts
+++ /dev/null
@@ -1,53 +0,0 @@
-import {getApiConnection} from '../substrate/substrate-api';
-import {expectTxFailure, requirePallets, Pallets} from './util/helpers';
-import {
- changeIssuer,
- createCollection,
-} from './util/tx';
-
-describe('integration test: collection issuer', () => {
- const alice = '//Alice';
- const bob = '//Bob';
-
- let api: any;
- before(async function() {
- api = await getApiConnection();
- await requirePallets(this, [Pallets.RmrkCore]);
- });
-
-
-
- it('change collection issuer', async () => {
- await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- ).then(async (collectionId) => {
- await changeIssuer(api, alice, collectionId, bob);
- });
- });
-
- it('[negative] change not an owner NFT collection issuer', async () => {
- await createCollection(api, bob, 'test-metadata', null, 'test-symbol').then(async (collectionId) => {
- const tx = changeIssuer(api, alice, collectionId, bob);
- await expectTxFailure(/rmrkCore\.NoPermission/, tx);
- });
- });
-
- it('[negative] change non-existigit NFT collection issuer', async () => {
- await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- ).then(async () => {
- const tx = changeIssuer(api, alice, 99999, bob);
- await expectTxFailure(/rmrkCore\.CollectionUnknown/, tx);
- });
- });
-
- after(async() => { await api.disconnect(); });
-});
tests/src/.outdated/rmrk/createBase.seqtest.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/createBase.seqtest.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-import {getApiConnection} from '../substrate/substrate-api';
-import {requirePallets, Pallets} from './util/helpers';
-import {createCollection, createBase} from './util/tx';
-
-describe('integration test: create new Base', () => {
- let api: any;
- before(async function() {
- api = await getApiConnection();
- await requirePallets(this, [Pallets.RmrkCore, Pallets.RmrkEquip]);
- });
-
- const alice = '//Alice';
-
- it('create empty Base', async () => {
- await createBase(api, alice, 'empty-base-type', 'EBase', []);
- });
-
- it('create Base with fixed part', async () => {
- await createBase(api, alice, 'fixedpart-base-type', 'FPBase', [
- {
- 'FixedPart': {
- id: 42,
- z: 0,
- src: 'some-fixed-url',
- },
- },
- ]);
- });
-
- it('create Base with slot part (no collection)', async () => {
- await createBase(api, alice, 'slotpart-base-type', 'SPBase', [
- {
- 'SlotPart': {
- id: 112,
- equippable: 'Empty',
- z: 0,
- src: 'some-fallback-slot-url',
- },
- },
- ]);
- });
-
- it('create Base with slot part (any collection)', async () => {
- await createBase(api, alice, 'slotpartany-base-type', 'SPABase', [
- {
- 'SlotPart': {
- id: 222,
- equippable: 'All',
- z: 1,
- src: 'some-fallback-slot-url',
- },
- },
- ]);
- });
-
- it('create Base with slot part (custom collections)', async () => {
- const firstCollectionId = await createCollection(
- api,
- alice,
- 'first-collection-meta',
- null,
- 'first-collection',
- );
-
- const secondCollectionId = await createCollection(
- api,
- alice,
- 'first-collection-meta',
- null,
- 'first-collection',
- );
-
- await createBase(api, alice, 'slotpartcustom-base-type', 'SPCBase', [
- {
- 'SlotPart': {
- id: 1024,
- equippable: {
- 'Custom': [firstCollectionId, secondCollectionId],
- },
- z: 2,
- src: 'some-fallback-slot-url',
- },
- },
- ]);
- });
-
- after(async() => { await api.disconnect(); });
-});
tests/src/.outdated/rmrk/createCollection.seqtest.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/createCollection.seqtest.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import {getApiConnection} from '../substrate/substrate-api';
-import {requirePallets, Pallets} from './util/helpers';
-import {createCollection} from './util/tx';
-
-describe('Integration test: create new collection', () => {
- let api: any;
- before(async function () {
- api = await getApiConnection();
- await requirePallets(this, [Pallets.RmrkCore]);
- });
-
-
-
- const alice = '//Alice';
-
- it('create NFT collection', async () => {
- await createCollection(api, alice, 'test-metadata', 42, 'test-symbol');
- });
-
- it('create NFT collection without token limit', async () => {
- await createCollection(api, alice, 'no-limit-metadata', null, 'no-limit-symbol');
- });
-
- after(async() => { await api.disconnect(); });
-});
tests/src/.outdated/rmrk/deleteCollection.seqtest.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/deleteCollection.seqtest.ts
+++ /dev/null
@@ -1,46 +0,0 @@
-import {getApiConnection} from '../substrate/substrate-api';
-import {expectTxFailure, requirePallets, Pallets} from './util/helpers';
-import {createCollection, deleteCollection} from './util/tx';
-
-describe('integration test: delete collection', () => {
- let api: any;
- before(async function () {
- api = await getApiConnection();
- await requirePallets(this, [Pallets.RmrkCore]);
- });
-
- const alice = '//Alice';
- const bob = '//Bob';
-
- it('delete NFT collection', async () => {
- await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- ).then(async (collectionId) => {
- await deleteCollection(api, alice, collectionId.toString());
- });
- });
-
- it('[negative] delete non-existing NFT collection', async () => {
- const tx = deleteCollection(api, alice, '99999');
- await expectTxFailure(/rmrkCore\.CollectionUnknown/, tx);
- });
-
- it('[negative] delete not an owner NFT collection', async () => {
- await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- ).then(async (collectionId) => {
- const tx = deleteCollection(api, bob, collectionId.toString());
- await expectTxFailure(/rmrkCore.NoPermission/, tx);
- });
- });
-
- after(async() => { await api.disconnect(); });
-});
tests/src/.outdated/rmrk/equipNft.seqtest.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/equipNft.seqtest.ts
+++ /dev/null
@@ -1,340 +0,0 @@
-import {ApiPromise} from '@polkadot/api';
-import {expect} from 'chai';
-import {getApiConnection} from '../substrate/substrate-api';
-import {getNft, NftIdTuple} from './util/fetch';
-import {expectTxFailure, requirePallets, Pallets} from './util/helpers';
-import {
- addNftComposableResource,
- addNftSlotResource,
- createBase,
- createCollection,
- equipNft,
- mintNft,
- sendNft,
- unequipNft,
-} from './util/tx';
-
-const alice = '//Alice';
-const bob = '//Bob';
-
-const composableParts: number[] = [5, 2, 7];
-const composableSrc = 'test-cmp-src';
-const composableMetadata = 'test-cmp-metadata';
-const composableLicense = 'test-comp-license';
-const composableThumb = 'test-comp-thumb';
-
-const slotSrc = 'test-slot-src';
-const slotLicense = 'test-slot-license';
-const slotMetadata = 'test-slot-metadata';
-const slotThumb = 'test-slot-thumb';
-
-const slotId = 1;
-
-function createTestCollection(api: ApiPromise): Promise<number> {
- return createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-}
-
-async function mintTestNft(api: ApiPromise, collectionId: number): Promise<number> {
- return await mintNft(
- api,
- alice,
- alice,
- collectionId,
- 'nft-metadata',
- );
-}
-
-async function mintChildNft(api: ApiPromise, collectionId: number, parentNftId: number): Promise<number> {
- const nftChildId = await mintTestNft(api, collectionId);
-
- const parentNFT: NftIdTuple = [collectionId, parentNftId];
-
- await sendNft(api, 'sent', alice, collectionId, nftChildId, parentNFT);
-
- return nftChildId;
-}
-
-function createTestBase(api: ApiPromise): Promise<number> {
- return createBase(api, alice, 'test-base', 'DTBase', [
- {
- SlotPart: {
- id: slotId,
- equippable: 'All',
- z: 1,
- src: slotSrc,
- },
- },
- ]);
-}
-
-async function addTestComposable(api: ApiPromise, collectionId: number, nftId: number, baseId: number) {
- await addNftComposableResource(
- api,
- alice,
- 'added',
- collectionId,
- nftId,
- composableParts,
- baseId,
- composableSrc,
- composableMetadata,
- composableLicense,
- composableThumb,
- );
-}
-
-async function addTestSlot(api: ApiPromise, collectionId: number, nftId: number, baseId: number, slotId: number): Promise<number> {
- return await addNftSlotResource(
- api,
- alice,
- 'added',
- collectionId,
- nftId,
- baseId,
- slotId,
- slotSrc,
- slotMetadata,
- slotLicense,
- slotThumb,
- );
-}
-
-async function checkEquipStatus(
- api: ApiPromise,
- expectedStatus: 'equipped' | 'unequipped',
- collectionId: number,
- nftId: number,
-) {
- const itemNftDataOpt = await getNft(api, collectionId, nftId);
- expect(itemNftDataOpt.isSome, 'Error: unable to fetch item NFT data');
-
- const itemNftData = itemNftDataOpt.unwrap();
- expect(itemNftData.equipped.isTrue, `Error: item NFT should be ${expectedStatus}`)
- .to.be.equal(expectedStatus === 'equipped');
-}
-
-describe.skip('integration test: Equip NFT', () => {
-
- let api: any;
-
- before(async function () {
- api = await getApiConnection();
- await requirePallets(this, [Pallets.RmrkCore, Pallets.RmrkEquip]);
- });
-
- it('equip nft', async () => {
- const collectionId = await createTestCollection(api);
- const nftParentId = await mintTestNft(api, collectionId);
- const nftChildId = await mintChildNft(api, collectionId, nftParentId);
-
- const baseId = await createTestBase(api);
-
- await addTestComposable(api, collectionId, nftParentId, baseId);
- const resourceId = await addTestSlot(api, collectionId, nftChildId, baseId, slotId);
-
- const equipperNFT: NftIdTuple = [collectionId, nftParentId];
- const itemNFT: NftIdTuple = [collectionId, nftChildId];
-
- await equipNft(api, alice, itemNFT, equipperNFT, resourceId, baseId, slotId);
-
- await checkEquipStatus(api, 'equipped', collectionId, nftChildId);
- });
-
- it('unequip nft', async () => {
- const collectionId = await createTestCollection(api);
- const nftParentId = await mintTestNft(api, collectionId);
- const nftChildId = await mintChildNft(api, collectionId, nftParentId);
-
- const baseId = await createTestBase(api);
-
- await addTestComposable(api, collectionId, nftParentId, baseId);
- const resourceId = await addTestSlot(api, collectionId, nftChildId, baseId, slotId);
-
- const equipperNFT: NftIdTuple = [collectionId, nftParentId];
- const itemNFT: NftIdTuple = [collectionId, nftChildId];
-
- await equipNft(api, alice, itemNFT, equipperNFT, resourceId, baseId, slotId);
-
- await checkEquipStatus(api, 'equipped', collectionId, nftChildId);
-
- await unequipNft(api, alice, itemNFT, equipperNFT, resourceId, baseId, slotId);
- await checkEquipStatus(api, 'unequipped', collectionId, nftChildId);
- });
-
- it('[negative] equip NFT onto non-existing NFT', async () => {
- const collectionId = await createTestCollection(api);
-
- const nftChildId = await mintNft(
- api,
- alice,
- alice,
- collectionId,
- 'nft-metadata',
- );
-
- const itemNFT: NftIdTuple = [collectionId, nftChildId];
- const invalidEquipperNFT: NftIdTuple = [collectionId, 9999999];
-
- const baseId = 0;
- const resourceId = 0;
-
- const tx = equipNft(api, alice, itemNFT, invalidEquipperNFT, resourceId, baseId, slotId);
- await expectTxFailure(/rmrkCore\.NoAvailableNftId/, tx);
- });
-
- it('[negative] equip non-existing NFT', async () => {
- const collectionId = await createTestCollection(api);
- const nftParentId = await mintNft(
- api,
- alice,
- alice,
- collectionId,
- 'nft-metadata',
- );
-
- const baseId = await createTestBase(api);
-
- await addTestComposable(api, collectionId, nftParentId, baseId);
-
- const equipperNFT: NftIdTuple = [collectionId, nftParentId];
- const invalidItemNFT: NftIdTuple = [collectionId, 99999999];
-
- const resourceId = 0;
-
- const tx = equipNft(api, alice, invalidItemNFT, equipperNFT, resourceId, baseId, slotId);
- await expectTxFailure(/rmrkCore\.NoAvailableNftId/, tx);
- });
-
- it('[negative] equip NFT by a not-an-owner user', async () => {
- const collectionId = await createTestCollection(api);
- const nftParentId = await mintTestNft(api, collectionId);
- const nftChildId = await mintChildNft(api, collectionId, nftParentId);
-
- const baseId = await createTestBase(api);
-
- await addTestComposable(api, collectionId, nftParentId, baseId);
-
- const equipperNFT: NftIdTuple = [collectionId, nftParentId];
- const itemNFT: NftIdTuple = [collectionId, nftChildId];
-
- const resourceId = await addTestSlot(api, collectionId, nftChildId, baseId, slotId);
-
- const tx = equipNft(api, bob, itemNFT, equipperNFT, resourceId, baseId, slotId);
- await expectTxFailure(/rmrkEquip\.PermissionError/, tx);
- });
-
- it('[negative] unable to equip NFT onto indirect parent NFT', async () => {
- const collectionId = await createTestCollection(api);
- const nftParentId = await mintTestNft(api, collectionId);
- const nftChildId = await mintChildNft(api, collectionId, nftParentId);
- const nftGrandchildId = await mintChildNft(api, collectionId, nftChildId);
-
- const baseId = await createTestBase(api);
-
- await addTestComposable(api, collectionId, nftParentId, baseId);
- const resourceId = await addTestSlot(api, collectionId, nftGrandchildId, baseId, slotId);
-
- const equipperNFT: NftIdTuple = [collectionId, nftParentId];
- const itemNFT: NftIdTuple = [collectionId, nftGrandchildId];
-
- const tx = equipNft(api, alice, itemNFT, equipperNFT, resourceId, baseId, slotId);
- await expectTxFailure(/rmrkEquip\.MustBeDirectParent/, tx);
- });
-
- it('[negative] unable to equip NFT onto parent NFT with another base', async () => {
- const collectionId = await createTestCollection(api);
- const nftParentId = await mintTestNft(api, collectionId);
- const nftChildId = await mintChildNft(api, collectionId, nftParentId);
-
- const baseId = await createTestBase(api);
-
- await addTestComposable(api, collectionId, nftParentId, baseId);
- const resourceId = await addTestSlot(api, collectionId, nftChildId, baseId, slotId);
-
- const equipperNFT: NftIdTuple = [collectionId, nftParentId];
- const itemNFT: NftIdTuple = [collectionId, nftChildId];
-
- const invalidBaseId = 99999;
-
- const tx = equipNft(api, alice, itemNFT, equipperNFT, resourceId, invalidBaseId, slotId);
- await expectTxFailure(/rmrkEquip\.NoResourceForThisBaseFoundOnNft/, tx);
- });
-
- it('[negative] unable to equip NFT into slot with another id', async () => {
- const collectionId = await createTestCollection(api);
- const nftParentId = await mintTestNft(api, collectionId);
- const nftChildId = await mintChildNft(api, collectionId, nftParentId);
-
- const baseId = await createTestBase(api);
-
- await addTestComposable(api, collectionId, nftParentId, baseId);
- const resourceId = await addTestSlot(api, collectionId, nftChildId, baseId, slotId);
-
- const equipperNFT: NftIdTuple = [collectionId, nftParentId];
- const itemNFT: NftIdTuple = [collectionId, nftChildId];
-
- const incorrectSlotId = slotId + 1;
- const tx = equipNft(api, alice, itemNFT, equipperNFT, resourceId, baseId, incorrectSlotId);
- await expectTxFailure(/rmrkEquip\.ItemHasNoResourceToEquipThere/, tx);
- });
-
- it('[negative] unable to equip NFT with incorrect slot (fixed part)', async () => {
- const collectionId = await createTestCollection(api);
- const nftParentId = await mintTestNft(api, collectionId);
- const nftChildId = await mintChildNft(api, collectionId, nftParentId);
-
- const baseId = await createBase(api, alice, 'test-base', 'DTBase', [
- {
- FixedPart: {
- id: slotId,
- equippable: 'All',
- z: 1,
- src: slotSrc,
- },
- },
- ]);
-
- await addTestComposable(api, collectionId, nftParentId, baseId);
- const resourceId = await addTestSlot(api, collectionId, nftChildId, baseId, slotId);
-
- const equipperNFT: NftIdTuple = [collectionId, nftParentId];
- const itemNFT: NftIdTuple = [collectionId, nftChildId];
-
- const tx = equipNft(api, alice, itemNFT, equipperNFT, resourceId, baseId, slotId);
- await expectTxFailure(/rmrkEquip\.CantEquipFixedPart/, tx);
- });
-
- it('[negative] unable to equip NFT from a collection that is not allowed by the slot', async () => {
- const collectionId = await createTestCollection(api);
- const nftParentId = await mintTestNft(api, collectionId);
- const nftChildId = await mintChildNft(api, collectionId, nftParentId);
-
- const baseId = await createBase(api, alice, 'test-base', 'DTBase', [
- {
- SlotPart: {
- id: 1,
- z: 1,
- equippable: 'Empty',
- src: slotSrc,
- },
- },
- ]);
-
- await addTestComposable(api, collectionId, nftParentId, baseId);
- const resourceId = await addTestSlot(api, collectionId, nftChildId, baseId, slotId);
-
- const equipperNFT: NftIdTuple = [collectionId, nftParentId];
- const itemNFT: NftIdTuple = [collectionId, nftChildId];
-
- const tx = equipNft(api, alice, itemNFT, equipperNFT, resourceId, baseId, slotId);
- await expectTxFailure(/rmrkEquip\.CollectionNotEquippable/, tx);
- });
-
- after(async() => { await api.disconnect(); });
-});
tests/src/.outdated/rmrk/getOwnedNfts.seqtest.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/getOwnedNfts.seqtest.ts
+++ /dev/null
@@ -1,80 +0,0 @@
-import {expect} from 'chai';
-import {getApiConnection} from '../substrate/substrate-api';
-import {requirePallets, Pallets} from './util/helpers';
-import {getOwnedNfts} from './util/fetch';
-import {mintNft, createCollection} from './util/tx';
-
-describe('integration test: get owned NFTs', () => {
- let api: any;
-
- before(async function () {
- api = await getApiConnection();
- await requirePallets(this, [Pallets.RmrkCore]);
- });
-
-
- const alice = '//Alice';
-
- it('fetch all NFTs owned by a user', async () => {
- const owner = alice;
- const collectionMetadata = 'aliceCollectionMetadata';
- const collectionMax = null;
- const collectionSymbol = 'AliceSym';
- const recipientUri = null;
- const royalty = null;
- const nftMetadata = 'alice-NFT-metadata';
-
- const collectionId = await createCollection(
- api,
- alice,
- collectionMetadata,
- collectionMax,
- collectionSymbol,
- );
-
- const nftIds = [
- await mintNft(
- api,
- alice,
- owner,
- collectionId,
- nftMetadata + '-0',
- recipientUri,
- royalty,
- ),
- await mintNft(
- api,
- alice,
- owner,
- collectionId,
- nftMetadata + '-1',
- recipientUri,
- royalty,
- ),
- await mintNft(
- api,
- alice,
- owner,
- collectionId,
- nftMetadata + '-2',
- recipientUri,
- royalty,
- ),
- ];
-
- const ownedNfts = await getOwnedNfts(api, alice, collectionId);
-
- const isFound = (nftId: number) => {
- return ownedNfts.find((ownedNftId) => {
- return ownedNftId === nftId;
- }) !== undefined;
- };
-
- nftIds.forEach((nftId) => {
- expect(isFound(nftId), `NFT ${nftId} should be owned by ${alice}`)
- .to.be.true;
- });
- });
-
- after(async() => { await api.disconnect(); });
-});
tests/src/.outdated/rmrk/lockCollection.seqtest.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/lockCollection.seqtest.ts
+++ /dev/null
@@ -1,116 +0,0 @@
-import {getApiConnection} from '../substrate/substrate-api';
-import {expectTxFailure, requirePallets, Pallets} from './util/helpers';
-import {createCollection, lockCollection, mintNft} from './util/tx';
-
-describe('integration test: lock collection', () => {
- const alice = '//Alice';
- const bob = '//Bob';
- const max = 5;
-
- let api: any;
- before(async function () {
- api = await getApiConnection();
- await requirePallets(this, [Pallets.RmrkCore]);
- });
-
- it('lock collection', async () => {
- await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- ).then(async (collectionId) => {
- await lockCollection(api, alice, collectionId);
- });
- });
-
- it('[negative] lock non-existing NFT collection', async () => {
- const tx = lockCollection(api, alice, 99999);
- await expectTxFailure(/rmrkCore\.CollectionUnknown/, tx);
- });
-
- it('[negative] lock not an owner NFT collection issuer', async () => {
- await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- ).then(async (collectionId) => {
- const tx = lockCollection(api, bob, collectionId);
- await expectTxFailure(/rmrkCore\.NoPermission/, tx);
- });
- });
-
- it('lock collection with minting', async () => {
- await createCollection(
- api,
- alice,
- 'test-metadata',
- max,
- 'test-symbol',
- ).then(async (collectionId) => {
- for (let i = 0; i < 5; i++) {
- await mintNft(
- api,
- alice,
- alice,
- collectionId,
- 'test-metadata',
- null,
- null,
- );
- }
- await lockCollection(api, alice, collectionId, max);
- });
- });
-
- it('[negative] unable to mint NFT inside a locked collection', async () => {
- await createCollection(
- api,
- alice,
- 'test-metadata',
- max,
- 'test-symbol',
- ).then(async (collectionId) => {
- await lockCollection(api, alice, collectionId);
- const tx = mintNft(
- api,
- alice,
- alice,
- collectionId,
- 'test-metadata',
- null,
- null,
- );
- await expectTxFailure(/rmrkCore\.CollectionFullOrLocked/, tx);
- });
- });
-
- it('[negative] unable to mint NFT inside a full collection', async () => {
- await createCollection(api, alice, 'test-metadata', 1, 'test-symbol').then(async (collectionId) => {
- await mintNft(
- api,
- alice,
- alice,
- collectionId,
- 'test-metadata',
- null,
- null,
- );
- const tx = mintNft(
- api,
- alice,
- alice,
- collectionId,
- 'test-metadata',
- null,
- null,
- );
- await expectTxFailure(/rmrkCore\.CollectionFullOrLocked/, tx);
- });
- });
-
- after(async() => { await api.disconnect(); });
-});
tests/src/.outdated/rmrk/mintNft.seqtest.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/mintNft.seqtest.ts
+++ /dev/null
@@ -1,211 +0,0 @@
-import {expect} from 'chai';
-import {getApiConnection} from '../substrate/substrate-api';
-import {getNft} from './util/fetch';
-import {expectTxFailure, requirePallets, Pallets} from './util/helpers';
-import {createCollection, mintNft} from './util/tx';
-
-describe('integration test: mint new NFT', () => {
- let api: any;
-
- before(async function () {
- api = await getApiConnection();
- await requirePallets(this, [Pallets.RmrkCore]);
- });
-
-
- const alice = '//Alice';
- const bob = '//Bob';
- const maxCollectionId = 0xFFFFFFFF;
- const maxNftId = 0xFFFFFFFF;
-
- it('mint NFT', async () => {
- const owner = null;
- const collectionMetadata = 'mintingCollectionMetadata';
- const collectionMax = null;
- const collectionSymbol = 'MCS';
- const recipientUri = null;
- const royalty = null;
- const nftMetadata = 'NFT-test-metadata';
-
- const collectionId = await createCollection(
- api,
- alice,
- collectionMetadata,
- collectionMax,
- collectionSymbol,
- );
-
- await mintNft(
- api,
- alice,
- owner,
- collectionId,
- nftMetadata,
- recipientUri,
- royalty,
- );
- });
-
- it('mint NFT and set another owner', async () => {
- const owner = bob;
- const collectionMetadata = 'setOwnerCollectionMetadata';
- const collectionMax = null;
- const collectionSymbol = 'SOCS';
- const recipientUri = null;
- const royalty = null;
- const nftMetadata = 'setOwner-NFT-metadata';
-
- const collectionId = await createCollection(
- api,
- alice,
- collectionMetadata,
- collectionMax,
- collectionSymbol,
- );
-
- await mintNft(
- api,
- alice,
- owner,
- collectionId,
- nftMetadata,
- recipientUri,
- royalty,
- );
- });
-
- it('mint NFT with recipient and roalty', async () => {
- const owner = alice;
- const collectionMetadata = 'mintingCollectionMetadata';
- const collectionMax = null;
- const collectionSymbol = 'MCS';
- const recipientUri = bob;
- const royalty = 70000;
- const nftMetadata = 'recipient-royalty-NFT-test-metadata';
-
- const collectionId = await createCollection(
- api,
- alice,
- collectionMetadata,
- collectionMax,
- collectionSymbol,
- );
-
- await mintNft(
- api,
- alice,
- owner,
- collectionId,
- nftMetadata,
- recipientUri,
- royalty,
- );
- });
-
- it('mint NFT with resources', async () => {
- const owner = alice;
- const collectionMetadata = 'mintingCollectionMetadata';
- const collectionMax = null;
- const collectionSymbol = 'MCS';
- const nftMetadata = 'NFT-with-resources-test-metadata';
- const resources = [
- {
- basic: {
- metadata: 'basic-resource-nft-minting',
- },
- }, {
- slot: {
- metadata: 'slot-resource-nft-minting',
- slot: 9,
- },
- }, {
- composable: {
- metadata: 'composable-resource-nft-minting',
- parts: [0, 5, 2],
- },
- }, {
- slot: {
- metadata: 'slot-resource-nft-minting-2',
- thumb: 'srnm2',
- base: 5,
- },
- },
- ];
-
- const collectionId = await createCollection(
- api,
- alice,
- collectionMetadata,
- collectionMax,
- collectionSymbol,
- );
-
- await mintNft(
- api,
- alice,
- owner,
- collectionId,
- nftMetadata,
- null,
- null,
- true,
- resources,
- );
- });
-
- it('[negative] unable to mint NFT within non-existing collection', async () => {
- const owner = alice;
- const recipientUri = null;
- const royalty = null;
- const nftMetadata = 'NFT-test-metadata';
-
- const tx = mintNft(
- api,
- alice,
- owner,
- maxCollectionId,
- nftMetadata,
- recipientUri,
- royalty,
- );
-
- await expectTxFailure(/rmrkCore\.CollectionUnknown/, tx);
- });
-
- it("[negative] unable to mint NFT by a user that isn't the owner of the collection", async () => {
- const owner = alice;
- const collectionMetadata = 'mintingCollectionMetadata';
- const collectionMax = null;
- const collectionSymbol = 'MCS';
- const recipientUri = null;
- const royalty = null;
- const nftMetadata = 'NFT-test-metadata';
-
- const collectionId = await createCollection(
- api,
- alice,
- collectionMetadata,
- collectionMax,
- collectionSymbol,
- );
-
- const tx = mintNft(
- api,
- bob,
- owner,
- collectionId,
- nftMetadata,
- recipientUri,
- royalty,
- );
-
- await expectTxFailure(/rmrkCore\.NoPermission/, tx);
- });
-
- it('[negative] unable to fetch non-existing NFT', async () => {
- const nft = await getNft(api, maxCollectionId, maxNftId);
- expect(nft.isSome).to.be.false;
- });
-
- after(async() => { await api.disconnect(); });
-});
tests/src/.outdated/rmrk/rejectNft.seqtest.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/rejectNft.seqtest.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-import {expect} from 'chai';
-import {getApiConnection} from '../substrate/substrate-api';
-import {
- createCollection,
- mintNft,
- sendNft,
- rejectNft,
-} from './util/tx';
-import {NftIdTuple} from './util/fetch';
-import {isNftChildOfAnother, expectTxFailure, requirePallets, Pallets} from './util/helpers';
-
-describe('integration test: reject NFT', () => {
- let api: any;
- before(async function () {
- api = await getApiConnection();
- await requirePallets(this, [Pallets.RmrkCore]);
- });
-
-
-
- const alice = '//Alice';
- const bob = '//Bob';
-
- const createTestCollection = async (issuerUri: string) => {
- return await createCollection(
- api,
- issuerUri,
- 'reject-metadata',
- null,
- 'rjct',
- );
- };
-
- it('reject NFT', async () => {
- const ownerAlice = alice;
- const ownerBob = bob;
-
- const aliceCollectionId = await createTestCollection(alice);
- const bobCollectionId = await createTestCollection(bob);
-
- const parentNftId = await mintNft(api, alice, ownerAlice, aliceCollectionId, 'parent-nft-metadata');
- const childNftId = await mintNft(api, bob, ownerBob, bobCollectionId, 'child-nft-metadata');
-
- const newOwnerNFT: NftIdTuple = [aliceCollectionId, parentNftId];
-
- await sendNft(api, 'pending', ownerBob, bobCollectionId, childNftId, newOwnerNFT);
- await rejectNft(api, alice, bobCollectionId, childNftId);
-
- const isChild = await isNftChildOfAnother(api, bobCollectionId, childNftId, newOwnerNFT);
- expect(isChild, 'Error: rejected NFT is still a child of the target NFT').to.be.false;
- });
-
- it('[negative] unable to reject NFT by a not-an-owner', async () => {
- const ownerAlice = alice;
- const ownerBob = bob;
-
- const aliceCollectionId = await createTestCollection(alice);
- const bobCollectionId = await createTestCollection(bob);
-
- const parentNftId = await mintNft(api, alice, ownerAlice, aliceCollectionId, 'parent-nft-metadata');
- const childNftId = await mintNft(api, bob, ownerBob, bobCollectionId, 'child-nft-metadata');
-
- const newOwnerNFT: NftIdTuple = [aliceCollectionId, parentNftId];
-
- await sendNft(api, 'pending', ownerBob, bobCollectionId, childNftId, newOwnerNFT);
- const tx = rejectNft(api, bob, bobCollectionId, childNftId);
-
- await expectTxFailure(/rmrkCore\.CannotRejectNonOwnedNft/, tx);
- });
-
- it('[negative] unable to reject non-existing NFT', async () => {
- const maxNftId = 0xFFFFFFFF;
-
- const collectionId = await createTestCollection(alice);
-
- const tx = rejectNft(api, alice, collectionId, maxNftId);
-
- await expectTxFailure(/rmrkCore\.NoAvailableNftId/, tx);
- });
-
- it('[negative] unable to reject NFT which is not sent', async () => {
- const ownerAlice = alice;
-
- const collectionId = await createTestCollection(alice);
-
- const nftId = await mintNft(api, alice, ownerAlice, collectionId, 'parent-nft-metadata');
-
- const tx = rejectNft(api, alice, collectionId, nftId);
-
- await expectTxFailure(/rmrkCore\.CannotRejectNonPendingNft/, tx);
- });
-
- after(async() => { await api.disconnect(); });
-});
tests/src/.outdated/rmrk/removeResource.seqtest.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/removeResource.seqtest.ts
+++ /dev/null
@@ -1,340 +0,0 @@
-import {getApiConnection} from '../substrate/substrate-api';
-import {NftIdTuple} from './util/fetch';
-import {expectTxFailure, requirePallets, Pallets} from './util/helpers';
-import {
- acceptResourceRemoval, addNftBasicResource, createCollection, mintNft, removeNftResource, sendNft,
-} from './util/tx';
-
-
-
-
-describe('Integration test: remove nft resource', () => {
- let api: any;
- before(async function() {
- api = await getApiConnection();
- await requirePallets(this, [Pallets.RmrkCore]);
- });
-
- const alice = '//Alice';
- const bob = '//Bob';
- const src = 'test-basic-src';
- const metadata = 'test-basic-metadata';
- const license = 'test-basic-license';
- const thumb = 'test-basic-thumb';
-
- it('deleting a resource directly by the NFT owner', async () => {
- const collectionIdAlice = await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const nftAlice = await mintNft(
- api,
- alice,
- alice,
- collectionIdAlice,
- 'nft-metadata',
- );
-
- const resourceId = await addNftBasicResource(
- api,
- alice,
- 'added',
- collectionIdAlice,
- nftAlice,
- src,
- metadata,
- license,
- thumb,
- );
-
- await removeNftResource(api, 'removed', alice, collectionIdAlice, nftAlice, resourceId);
- });
-
- it('deleting resources indirectly by the NFT owner', async () => {
- const collectionIdAlice = await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const parentNftId = await mintNft(api, alice, alice, collectionIdAlice, 'parent-nft-metadata');
- const childNftId = await mintNft(api, alice, alice, collectionIdAlice, 'child-nft-metadata');
-
- const resourceId = await addNftBasicResource(
- api,
- alice,
- 'added',
- collectionIdAlice,
- childNftId,
- src,
- metadata,
- license,
- thumb,
- );
-
- const newOwnerNFT: NftIdTuple = [collectionIdAlice, parentNftId];
-
- await sendNft(api, 'sent', alice, collectionIdAlice, childNftId, newOwnerNFT);
-
- await removeNftResource(api, 'removed', alice, collectionIdAlice, childNftId, resourceId);
- });
-
- it('deleting a resource by the collection owner', async () => {
- const collectionIdAlice = await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const nftBob = await mintNft(
- api,
- alice,
- bob,
- collectionIdAlice,
- 'nft-metadata',
- );
-
- const resourceId = await addNftBasicResource(
- api,
- alice,
- 'pending',
- collectionIdAlice,
- nftBob,
- src,
- metadata,
- license,
- thumb,
- );
-
- await removeNftResource(api, 'pending', alice, collectionIdAlice, nftBob, resourceId);
- await acceptResourceRemoval(api, bob, collectionIdAlice, nftBob, resourceId);
- });
-
- it('deleting a resource in a nested NFT by the collection owner', async () => {
- const collectionIdAlice = await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const parentNftId = await mintNft(
- api,
- alice,
- bob,
- collectionIdAlice,
- 'parent-nft-metadata',
- );
- const childNftId = await mintNft(
- api,
- alice,
- bob,
- collectionIdAlice,
- 'child-nft-metadata',
- );
-
- const resourceId = await addNftBasicResource(
- api,
- alice,
- 'pending',
- collectionIdAlice,
- childNftId,
- src,
- metadata,
- license,
- thumb,
- );
-
- const newOwnerNFT: NftIdTuple = [collectionIdAlice, parentNftId];
-
- await sendNft(api, 'sent', bob, collectionIdAlice, childNftId, newOwnerNFT);
-
- await removeNftResource(api, 'pending', alice, collectionIdAlice, childNftId, resourceId);
- await acceptResourceRemoval(api, bob, collectionIdAlice, childNftId, resourceId);
- });
-
- it('[negative]: can\'t delete a resource in a non-existing collection', async () => {
- const collectionIdAlice = await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const nftAlice = await mintNft(
- api,
- alice,
- alice,
- collectionIdAlice,
- 'nft-metadata',
- );
-
- const resourceId = await addNftBasicResource(
- api,
- alice,
- 'added',
- collectionIdAlice,
- nftAlice,
- src,
- metadata,
- license,
- thumb,
- );
-
- const tx = removeNftResource(api, 'removed', alice, 0xFFFFFFFF, nftAlice, resourceId);
- await expectTxFailure(/rmrkCore\.CollectionUnknown/, tx); // FIXME: inappropriate error message (NoAvailableNftId)
- });
-
- it('[negative]: only collection owner can delete a resource', async () => {
- const collectionIdAlice = await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const nftAlice = await mintNft(
- api,
- alice,
- alice,
- collectionIdAlice,
- 'nft-metadata',
- );
-
- const resourceId = await addNftBasicResource(
- api,
- alice,
- 'added',
- collectionIdAlice,
- nftAlice,
- src,
- metadata,
- license,
- thumb,
- );
-
- const tx = removeNftResource(api, 'removed', bob, collectionIdAlice, nftAlice, resourceId);
- await expectTxFailure(/rmrkCore\.NoPermission/, tx);
- });
-
- it('[negative]: cannot delete a resource that does not exist', async () => {
- const collectionIdAlice = await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const nftAlice = await mintNft(
- api,
- alice,
- alice,
- collectionIdAlice,
- 'nft-metadata',
- );
-
- const tx = removeNftResource(api, 'removed', alice, collectionIdAlice, nftAlice, 127);
- await expectTxFailure(/rmrkCore\.ResourceDoesntExist/, tx);
- });
-
- it('[negative]: Cannot accept deleting resource without owner attempt do delete it', async () => {
- const collectionIdAlice = await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const nftBob = await mintNft(
- api,
- alice,
- bob,
- collectionIdAlice,
- 'nft-metadata',
- );
-
- const resourceId = await addNftBasicResource(
- api,
- alice,
- 'pending',
- collectionIdAlice,
- nftBob,
- src,
- metadata,
- license,
- thumb,
- );
-
- const tx = acceptResourceRemoval(api, bob, collectionIdAlice, nftBob, resourceId);
- await expectTxFailure(/rmrkCore\.ResourceNotPending/, tx);
- });
-
- it('[negative]: cannot confirm the deletion of a non-existing resource', async () => {
- const collectionIdAlice = await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const nftBob = await mintNft(
- api,
- alice,
- bob,
- collectionIdAlice,
- 'nft-metadata',
- );
-
- const tx = acceptResourceRemoval(api, bob, collectionIdAlice, nftBob, 127);
- await expectTxFailure(/rmrkCore\.ResourceDoesntExist/, tx);
- });
-
- it('[negative]: Non-owner user cannot confirm the deletion of resource', async () => {
- const collectionIdAlice = await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- );
-
- const nftAlice = await mintNft(
- api,
- alice,
- alice,
- collectionIdAlice,
- 'nft-metadata',
- );
-
- const resourceId = await addNftBasicResource(
- api,
- alice,
- 'added',
- collectionIdAlice,
- nftAlice,
- src,
- metadata,
- license,
- thumb,
- );
-
- const tx = acceptResourceRemoval(api, bob, collectionIdAlice, nftAlice, resourceId);
- await expectTxFailure(/rmrkCore\.NoPermission/, tx);
- });
-
- after(async() => { await api.disconnect(); });
-});
tests/src/.outdated/rmrk/rmrkIsolation.seqtest.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/rmrkIsolation.seqtest.ts
+++ /dev/null
@@ -1,225 +0,0 @@
-import {executeTransaction} from '../substrate/substrate-api';
-import {IKeyringPair} from '@polkadot/types/types';
-import {itSub, expect, usingPlaygrounds, Pallets, requirePalletsOrSkip} from '../../util';
-import {UniqueHelper} from '../../util/playgrounds/unique';
-
-let alice: IKeyringPair;
-let bob: IKeyringPair;
-
-async function createRmrkCollection(helper: UniqueHelper, sender: IKeyringPair): Promise<{uniqueId: number, rmrkId: number}> {
- const result = await helper.executeExtrinsic(sender, 'api.tx.rmrkCore.createCollection', ['metadata', null, 'symbol'], true);
-
- const uniqueId = helper.util.extractCollectionIdFromCreationResult(result);
-
- let rmrkId = null;
- result.result.events.forEach(({event: {data, method, section}}) => {
- if ((section === 'rmrkCore') && (method === 'CollectionCreated')) {
- rmrkId = parseInt(data[1].toString(), 10);
- }
- });
-
- if (rmrkId === null) {
- throw Error('No rmrkCore.CollectionCreated event was found!');
- }
-
- return {
- uniqueId,
- rmrkId,
- };
-}
-
-async function createRmrkNft(helper: UniqueHelper, sender: IKeyringPair, collectionId: number): Promise<number> {
- const result = await helper.executeExtrinsic(
- sender,
- 'api.tx.rmrkCore.mintNft',
- [
- sender.address,
- collectionId,
- sender.address,
- null,
- 'nft-metadata',
- true,
- null,
- ],
- true,
- );
-
- let rmrkNftId = null;
- result.result.events.forEach(({event: {data, method, section}}) => {
- if ((section === 'rmrkCore') && (method === 'NftMinted')) {
- rmrkNftId = parseInt(data[2].toString(), 10);
- }
- });
-
- if (rmrkNftId === null) {
- throw Error('No rmrkCore.NftMinted event was found!');
- }
-
- return rmrkNftId;
-}
-
-describe('RMRK External Integration Test', () => {
- before(async function() {
- await usingPlaygrounds(async (_helper, privateKey) => {
- alice = await privateKey('//Alice');
- });
- });
-
- itSub.ifWithPallets('Creates a new RMRK collection that is mapped to a different ID and is tagged as external', [Pallets.RmrkCore], async ({helper}) => {
- // throw away collection to bump last Unique collection ID to test ID mapping
- await helper.nft.mintCollection(alice, {tokenPrefix: 'unqt'});
-
- const collectionIds = await createRmrkCollection(helper, alice);
-
- expect(collectionIds.rmrkId).to.be.lessThan(collectionIds.uniqueId, 'collection ID mapping');
-
- const collection = (await helper.nft.getCollectionObject(collectionIds.uniqueId).getData())!; // (await getDetailedCollectionInfo(api, collectionIds.uniqueId))!;
- expect(collection.raw.readOnly, 'tagged external').to.be.true;
- });
-});
-
-describe('Negative Integration Test: External Collections, Internal Ops', () => {
- let uniqueCollectionId: number;
- let rmrkCollectionId: number;
- let rmrkNftId: number;
- let normalizedAlice: {Substrate: string};
-
- before(async function() {
- await usingPlaygrounds(async (helper, privateKey) => {
- alice = await privateKey('//Alice');
- bob = await privateKey('//Bob');
- normalizedAlice = {Substrate: helper.address.normalizeSubstrateToChainFormat(alice.address)};
-
- requirePalletsOrSkip(this, helper, [Pallets.RmrkCore]);
-
- const collectionIds = await createRmrkCollection(helper, alice);
- uniqueCollectionId = collectionIds.uniqueId;
- rmrkCollectionId = collectionIds.rmrkId;
-
- rmrkNftId = await createRmrkNft(helper, alice, rmrkCollectionId);
- });
- });
-
- itSub.ifWithPallets('[Negative] Forbids Unique operations with an external collection, handled by dispatch_call', [Pallets.RmrkCore], async ({helper}) => {
- // Collection item creation
-
- await expect(helper.nft.mintToken(alice, {collectionId: uniqueCollectionId, owner: {Substrate: alice.address}}), 'creating item')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- const txCreateMultipleItems = helper.getApi().tx.unique.createMultipleItems(uniqueCollectionId, normalizedAlice, [{NFT: {}}, {NFT: {}}]);
- await expect(executeTransaction(helper.getApi(), alice, txCreateMultipleItems), 'creating multiple')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- await expect(helper.nft.mintMultipleTokens(alice, uniqueCollectionId, [{owner: {Substrate: alice.address}}]), 'creating multiple ex')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- // Collection properties
-
- await expect(helper.nft.setProperties(alice, uniqueCollectionId, [{key: 'a', value: '1'}, {key: 'b'}]), 'setting collection properties')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- await expect(helper.nft.deleteProperties(alice, uniqueCollectionId, ['a']), 'deleting collection properties')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- await expect(helper.nft.setTokenPropertyPermissions(alice, uniqueCollectionId, [{key: 'a', permission: {mutable: true}}]), 'setting property permissions')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- // NFT
-
- await expect(helper.nft.burnToken(alice, uniqueCollectionId, rmrkNftId, 1n), 'burning')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- await expect(helper.nft.burnTokenFrom(alice, uniqueCollectionId, rmrkNftId, {Substrate: alice.address}, 1n), 'burning-from')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- await expect(helper.nft.transferToken(alice, uniqueCollectionId, rmrkNftId, {Substrate: bob.address}), 'transferring')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- await expect(helper.nft.approveToken(alice, uniqueCollectionId, rmrkNftId, {Substrate: bob.address}), 'approving')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- await expect(helper.nft.transferTokenFrom(alice, uniqueCollectionId, rmrkNftId, {Substrate: alice.address}, {Substrate: bob.address}), 'transferring-from')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- // NFT properties
-
- await expect(helper.nft.setTokenProperties(alice, uniqueCollectionId, rmrkNftId, [{key: 'a', value: '2'}]), 'setting token properties')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- await expect(helper.nft.deleteTokenProperties(alice, uniqueCollectionId, rmrkNftId, ['a']))
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
- });
-
- itSub.ifWithPallets('[Negative] Forbids Unique collection operations with an external collection', [Pallets.RmrkCore], async ({helper}) => {
- await expect(helper.nft.burn(alice, uniqueCollectionId), 'destroying collection')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- // Allow list
-
- await expect(helper.nft.addToAllowList(alice, uniqueCollectionId, {Substrate: bob.address}), 'adding to allow list')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- await expect(helper.nft.removeFromAllowList(alice, uniqueCollectionId, {Substrate: bob.address}), 'removing from allowlist')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- // Owner / Admin / Sponsor
-
- await expect(helper.nft.changeOwner(alice, uniqueCollectionId, bob.address), 'changing owner')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- await expect(helper.nft.addAdmin(alice, uniqueCollectionId, {Substrate: bob.address}), 'adding admin')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- await expect(helper.nft.removeAdmin(alice, uniqueCollectionId, {Substrate: bob.address}), 'removing admin')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- await expect(helper.nft.setSponsor(alice, uniqueCollectionId, bob.address), 'setting sponsor')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- await expect(helper.nft.confirmSponsorship(alice, uniqueCollectionId), 'confirming sponsor')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- await expect(helper.nft.removeSponsor(alice, uniqueCollectionId), 'removing sponsor')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- // Limits / permissions / transfers
-
- const txSetTransfers = helper.getApi().tx.unique.setTransfersEnabledFlag(uniqueCollectionId, true);
- await expect(executeTransaction(helper.getApi(), alice, txSetTransfers), 'setting transfers enabled flag')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- await expect(helper.nft.setLimits(alice, uniqueCollectionId, {transfersEnabled: false}), 'setting collection limits')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
-
- await expect(helper.nft.setPermissions(alice, uniqueCollectionId, {access: 'AllowList'}), 'setting collection permissions')
- .to.be.rejectedWith(/common\.CollectionIsExternal/);
- });
-});
-
-describe('Negative Integration Test: Internal Collections, External Ops', () => {
- let collectionId: number;
- let nftId: number;
-
- before(async () => {
- await usingPlaygrounds(async (helper, privateKey) => {
- alice = await privateKey('//Alice');
- bob = await privateKey('//Bob');
-
- const collection = await helper.nft.mintCollection(alice, {tokenPrefix: 'iceo'});
- collectionId = collection.collectionId;
- nftId = (await collection.mintToken(alice)).tokenId;
- });
- });
-
- itSub.ifWithPallets('[Negative] Forbids RMRK operations with the internal collection and NFT (due to the lack of mapping)', [Pallets.RmrkCore], async ({helper}) => {
- const api = helper.getApi();
-
- const txChangeOwner = api.tx.rmrkCore.changeCollectionIssuer(collectionId, bob.address);
- await expect(executeTransaction(api, alice, txChangeOwner), 'changing collection issuer')
- .to.be.rejectedWith(/rmrkCore\.CollectionUnknown/);
-
- const maxBurns = 10;
- const txBurnItem = api.tx.rmrkCore.burnNft(collectionId, nftId, maxBurns);
- await expect(executeTransaction(api, alice, txBurnItem), 'burning NFT').to.be.rejectedWith(/rmrkCore\.CollectionUnknown/);
- });
-});
tests/src/.outdated/rmrk/sendNft.seqtest.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/sendNft.seqtest.ts
+++ /dev/null
@@ -1,255 +0,0 @@
-import {expect} from 'chai';
-import {getApiConnection} from '../substrate/substrate-api';
-import {createCollection, mintNft, sendNft} from './util/tx';
-import {NftIdTuple} from './util/fetch';
-import {isNftChildOfAnother, expectTxFailure, requirePallets, Pallets} from './util/helpers';
-
-describe('integration test: send NFT', () => {
- let api: any;
- before(async function () {
- api = await getApiConnection();
- await requirePallets(this, [Pallets.RmrkCore]);
- });
-
- const maxNftId = 0xFFFFFFFF;
-
- const alice = '//Alice';
- const bob = '//Bob';
-
- const createTestCollection = async (issuerUri: string) => {
- return await createCollection(
- api,
- issuerUri,
- 'nft-collection-metadata',
- null,
- 'nft-collection',
- );
- };
-
-
- it('send NFT to another user', async () => {
- const originalOwnerUri = alice;
- const newOwnerUri = bob;
-
- const collectionId = await createTestCollection(alice);
-
- const nftId = await mintNft(api, alice, originalOwnerUri, collectionId, 'nft-metadata');
-
- await sendNft(api, 'sent', originalOwnerUri, collectionId, nftId, newOwnerUri);
- });
-
- it('[negative] unable to send non-existing NFT', async () => {
- const originalOwnerUri = alice;
- const newOwnerUri = bob;
-
- const collectionId = 0;
- const tx = sendNft(api, 'sent', originalOwnerUri, collectionId, maxNftId, newOwnerUri);
-
- await expectTxFailure(/rmrkCore\.NoAvailableNftId/, tx);
- });
-
- it('[negative] unable to send NFT by a not-an-owner', async () => {
- const originalOwnerUri = alice;
- const newOwnerUri = bob;
-
- const collectionId = await createTestCollection(alice);
-
- const nftId = await mintNft(api, alice, originalOwnerUri, collectionId, 'nft-metadata');
-
- const tx = sendNft(api, 'sent', newOwnerUri, collectionId, nftId, newOwnerUri);
- await expectTxFailure(/rmrkCore\.NoPermission/, tx);
- });
-
- it('send NFT to another NFT (same owner)', async () => {
- const originalOwnerUri = alice;
-
- const collectionId = await createTestCollection(alice);
-
- const parentNftId = await mintNft(api, alice, originalOwnerUri, collectionId, 'parent-nft-metadata');
- const childNftId = await mintNft(api, alice, originalOwnerUri, collectionId, 'child-nft-metadata');
-
- const newOwnerNFT: NftIdTuple = [collectionId, parentNftId];
-
- await sendNft(api, 'sent', alice, collectionId, childNftId, newOwnerNFT);
-
- const isChild = await isNftChildOfAnother(api, collectionId, childNftId, newOwnerNFT);
- expect(isChild).to.be.true;
- });
-
- it('[negative] send non-existing NFT to another NFT', async () => {
- const originalOwnerUri = alice;
-
- const collectionId = await createTestCollection(alice);
-
- const parentNftId = await mintNft(api, alice, originalOwnerUri, collectionId, 'parent-nft-metadata');
- const childNftId = maxNftId;
-
- const newOwnerNFT: NftIdTuple = [collectionId, parentNftId];
-
- const tx = sendNft(api, 'sent', alice, collectionId, childNftId, newOwnerNFT);
-
- await expectTxFailure(/rmrkCore\.NoAvailableNftId/, tx);
-
- const isChild = await isNftChildOfAnother(api, collectionId, childNftId, newOwnerNFT);
- expect(isChild).to.be.false;
- });
-
- it('send NFT to another NFT (by not-an-owner)', async () => {
- const originalOwnerUri = alice;
-
- const collectionId = await createTestCollection(alice);
-
- const author = alice;
- const attacker = bob;
-
- const parentNftId = await mintNft(api, author, originalOwnerUri, collectionId, 'parent-nft-metadata');
- const childNftId = await mintNft(api, author, originalOwnerUri, collectionId, 'child-nft-metadata');
-
- const newOwnerNFT: NftIdTuple = [collectionId, parentNftId];
-
- const tx = sendNft(api, 'sent', attacker, collectionId, childNftId, newOwnerNFT);
-
- await expectTxFailure(/rmrkCore\.NoPermission/, tx);
-
- const isChild = await isNftChildOfAnother(api, collectionId, childNftId, newOwnerNFT);
- expect(isChild).to.be.false;
- });
-
- it('[negative] send NFT to non-existing NFT', async () => {
- const originalOwnerUri = alice;
-
- const collectionId = await createTestCollection(alice);
-
- const parentNftId = maxNftId;
- const childNftId = await mintNft(api, alice, originalOwnerUri, collectionId, 'child-nft-metadata');
-
- const newOwnerNFT: NftIdTuple = [collectionId, parentNftId];
-
- const tx = sendNft(api, 'sent', alice, collectionId, childNftId, newOwnerNFT);
-
- await expectTxFailure(/rmrkCore\.NoAvailableNftId/, tx);
-
- const isChild = await isNftChildOfAnother(api, collectionId, childNftId, newOwnerNFT);
- expect(isChild).to.be.false;
- });
-
- it('send NFT to another NFT owned by another user', async () => {
- const ownerAlice = alice;
- const ownerBob = bob;
-
- const aliceCollectionId = await createTestCollection(alice);
- const bobCollectionId = await createTestCollection(bob);
-
- const parentNftId = await mintNft(api, alice, ownerAlice, aliceCollectionId, 'parent-nft-metadata');
- const childNftId = await mintNft(api, bob, ownerBob, bobCollectionId, 'child-nft-metadata');
-
- const newOwnerNFT: NftIdTuple = [aliceCollectionId, parentNftId];
-
- await sendNft(api, 'pending', bob, bobCollectionId, childNftId, newOwnerNFT);
- });
-
- it('[negative] unable to send NFT to itself', async () => {
- const nftOwner = alice;
- const collectionId = await createTestCollection(alice);
-
- const nftId = await mintNft(api, alice, nftOwner, collectionId, 'ouroboros-nft-metadata');
-
- const newOwnerNFT: NftIdTuple = [collectionId, nftId];
-
- const tx = sendNft(api, 'sent', alice, collectionId, nftId, newOwnerNFT);
-
- await expectTxFailure(/rmrkCore\.CannotSendToDescendentOrSelf/, tx);
-
- const isChild = await isNftChildOfAnother(api, collectionId, nftId, newOwnerNFT);
- expect(isChild).to.be.false;
- });
-
- it('[negative] unable to send NFT to child NFT', async () => {
- const originalOwnerUri = alice;
-
- const collectionId = await createTestCollection(alice);
-
- const parentNftId = await mintNft(api, alice, originalOwnerUri, collectionId, 'parent-nft-metadata');
- const childNftId = await mintNft(api, alice, originalOwnerUri, collectionId, 'child-nft-metadata');
-
- const newOwnerNFT: NftIdTuple = [collectionId, parentNftId];
-
- await sendNft(api, 'sent', alice, collectionId, childNftId, newOwnerNFT);
-
- const isChild = await isNftChildOfAnother(api, collectionId, childNftId, newOwnerNFT);
- expect(isChild).to.be.true;
-
- const descendentOwner: NftIdTuple = [collectionId, childNftId];
- const tx = sendNft(api, 'sent', alice, collectionId, parentNftId, descendentOwner);
-
- await expectTxFailure(/rmrkCore\.CannotSendToDescendentOrSelf/, tx);
- const isOuroboros = await isNftChildOfAnother(api, collectionId, parentNftId, descendentOwner);
- expect(isOuroboros).to.be.false;
- });
-
- it('[negative] unable to send NFT to descendent NFT', async () => {
- const originalOwnerUri = alice;
-
- const collectionId = await createTestCollection(alice);
-
- const parentNftId = await mintNft(api, alice, originalOwnerUri, collectionId, 'parent-nft-metadata');
- const childNftId = await mintNft(api, alice, originalOwnerUri, collectionId, 'child-nft-metadata');
- const grandsonNftId = await mintNft(api, alice, originalOwnerUri, collectionId, 'grandson-nft-metadata');
-
- const ownerParentNFT: NftIdTuple = [collectionId, parentNftId];
-
- await sendNft(api, 'sent', alice, collectionId, childNftId, ownerParentNFT);
-
- const isChild = await isNftChildOfAnother(api, collectionId, childNftId, ownerParentNFT);
- expect(isChild).to.be.true;
-
- const ownerChildNFT: NftIdTuple = [collectionId, childNftId];
- await sendNft(api, 'sent', alice, collectionId, grandsonNftId, ownerChildNFT);
-
- const isGrandson = await isNftChildOfAnother(api, collectionId, grandsonNftId, ownerChildNFT);
- expect(isGrandson).to.be.true;
-
- const ownerGrandsonNFT: NftIdTuple = [collectionId, grandsonNftId];
- const tx = sendNft(api, 'sent', alice, collectionId, parentNftId, ownerGrandsonNFT);
-
- await expectTxFailure(/rmrkCore\.CannotSendToDescendentOrSelf/, tx);
- const isOuroboros = await isNftChildOfAnother(api, collectionId, parentNftId, ownerGrandsonNFT);
- expect(isOuroboros).to.be.false;
- });
-
- it('send nested NFT to another user', async () => {
- const originalOwner = alice;
- const newOwner = bob;
-
- const collectionId = await createTestCollection(alice);
-
- const parentNftId = await mintNft(api, alice, originalOwner, collectionId, 'parent-nft-metadata');
- const childNftId = await mintNft(api, alice, originalOwner, collectionId, 'child-nft-metadata');
-
- const parentNftTuple: NftIdTuple = [collectionId, parentNftId];
-
- await sendNft(api, 'sent', originalOwner, collectionId, childNftId, parentNftTuple);
-
- await sendNft(api, 'sent', originalOwner, collectionId, childNftId, newOwner);
- });
-
- it('[negative] send nested NFT to another user (by a not-root-owner)', async () => {
- const originalOwner = alice;
- const newOwner = bob;
-
- const collectionId = await createTestCollection(alice);
-
- const parentNftId = await mintNft(api, alice, originalOwner, collectionId, 'parent-nft-metadata');
- const childNftId = await mintNft(api, alice, originalOwner, collectionId, 'child-nft-metadata');
-
- const parentNftTuple: NftIdTuple = [collectionId, parentNftId];
-
- await sendNft(api, 'sent', originalOwner, collectionId, childNftId, parentNftTuple);
-
- const tx = sendNft(api, 'sent', newOwner, collectionId, childNftId, newOwner);
-
- await expectTxFailure(/rmrkCore\.NoPermission/, tx);
- });
-
- after(async() => { await api.disconnect(); });
-});
tests/src/.outdated/rmrk/setCollectionProperty.seqtest.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/setCollectionProperty.seqtest.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-import {getApiConnection} from '../substrate/substrate-api';
-import {expectTxFailure, requirePallets, Pallets} from './util/helpers';
-import {createCollection, setPropertyCollection} from './util/tx';
-
-describe('integration test: set collection property', () => {
- const alice = '//Alice';
- const bob = '//Bob';
-
- let api: any;
- before(async function () {
- api = await getApiConnection();
- await requirePallets(this, [Pallets.RmrkCore]);
- });
-
- it('set collection property', async () => {
- await createCollection(
- api,
- alice,
- 'test-metadata',
- null,
- 'test-symbol',
- ).then(async (collectionId) => {
- await setPropertyCollection(api, alice, collectionId, 'test_key', '42');
- await setPropertyCollection(api, alice, collectionId, 'test_key', '10');
- await setPropertyCollection(
- api,
- alice,
- collectionId,
- 'second_test_key',
- '111',
- );
- });
- });
-
- it('[negative] set non-existing collection property', async () => {
- const tx = setPropertyCollection(
- api,
- alice,
- 9999,
- 'test_key',
- '42',
- );
- await expectTxFailure(/rmrkCore\.CollectionUnknown/, tx);
- });
-
- it('[negative] set property not an owner NFT collection issuer', async () => {
- await createCollection(
- api,
- bob,
- 'test-metadata',
- null,
- 'test-symbol',
- ).then(async (collectionId) => {
- const tx = setPropertyCollection(
- api,
- alice,
- collectionId,
- 'test_key',
- '42',
- );
- await expectTxFailure(/rmrkCore\.NoPermission/, tx);
- });
- });
-
- after(async() => { await api.disconnect(); });
-});
tests/src/.outdated/rmrk/setEquippableList.seqtest.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/setEquippableList.seqtest.ts
+++ /dev/null
@@ -1,114 +0,0 @@
-import {getApiConnection} from '../substrate/substrate-api';
-import {expectTxFailure, requirePallets, Pallets} from './util/helpers';
-import {createCollection, createBase, setEquippableList} from './util/tx';
-
-describe("integration test: set slot's Equippable List", () => {
- let api: any;
- before(async function () {
- api = await getApiConnection();
- await requirePallets(this, [Pallets.RmrkCore]);
- });
-
- const alice = '//Alice';
- const bob = '//Bob';
-
- it("set Base's slot Equippable List", async () => {
- const collectionIds = [
- await createCollection(
- api,
- alice,
- 'equiplist-collection-metadata',
- null,
- 'equiplist-0',
- ),
- await createCollection(
- api,
- alice,
- 'equiplist-collection-metadata',
- null,
- 'equiplist-1',
- ),
- ];
-
- const slotId = 202;
-
- const baseId = await createBase(api, alice, 'slotpartany-base-type', 'slotpartany', [
- {
- 'SlotPart': {
- id: slotId,
- equippable: 'All',
- z: 1,
- src: 'some-fallback-slot-url',
- },
- },
- ]);
-
- await setEquippableList(api, alice, baseId, slotId, 'All');
- await setEquippableList(api, alice, baseId, slotId, 'Empty');
- await setEquippableList(api, alice, baseId, slotId, {'Custom': collectionIds});
- });
-
- it('[negative] unable to set equippable list of a slot of non-existing base', async () => {
- const maxBaseId = 0xFFFFFFFF;
- const slotId = 0;
-
- const tx = setEquippableList(api, alice, maxBaseId, slotId, 'All');
- await expectTxFailure(/rmrkEquip\.BaseDoesntExist/, tx);
- });
-
- it('[negative] unable to set equippable list by a not-an-owner', async () => {
- const slotId = 42;
-
- const baseId = await createBase(api, alice, 'slotpartany-base-type', 'slotpartany', [
- {
- 'SlotPart': {
- id: slotId,
- equippable: 'All',
- z: 1,
- src: 'some-fallback-slot-url',
- },
- },
- ]);
-
- const tx = setEquippableList(api, bob, baseId, slotId, 'All');
- await expectTxFailure(/rmrkEquip\.PermissionError/, tx);
- });
-
- it('[negative] unable to set equippable list to a fixed part', async () => {
- const fixedPartId = 42;
-
- const baseId = await createBase(api, alice, 'fixedpart-base-type', 'fixedpart', [
- {
- 'FixedPart': {
- id: fixedPartId,
- z: 0,
- src: 'fixed-part-url',
- },
- },
- ]);
-
- const tx = setEquippableList(api, alice, baseId, fixedPartId, 'All');
- await expectTxFailure(/rmrkEquip\.NoEquippableOnFixedPart/, tx);
- });
-
- it('[negative] unable to set equippable list to non-existing slot', async () => {
- const slotId = 777;
- const maxSlotId = 0xFFFFFFFF;
-
- const baseId = await createBase(api, alice, 'slotpartany-base-type', 'slotpartany', [
- {
- 'SlotPart': {
- id: slotId,
- equippable: 'All',
- z: 1,
- src: 'some-fallback-slot-url',
- },
- },
- ]);
-
- const tx = setEquippableList(api, alice, baseId, maxSlotId, 'All');
- await expectTxFailure(/rmrkEquip\.PartDoesntExist/, tx);
- });
-
- after(async() => { await api.disconnect(); });
-});
tests/src/.outdated/rmrk/setNftProperty.seqtest.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/setNftProperty.seqtest.ts
+++ /dev/null
@@ -1,88 +0,0 @@
-import {getApiConnection} from '../substrate/substrate-api';
-import {NftIdTuple} from './util/fetch';
-import {expectTxFailure, requirePallets, Pallets} from './util/helpers';
-import {createCollection, mintNft, sendNft, setNftProperty} from './util/tx';
-
-describe('integration test: set NFT property', () => {
- let api: any;
- before(async function () {
- api = await getApiConnection();
- await requirePallets(this, [Pallets.RmrkCore]);
- });
-
- const alice = '//Alice';
- const bob = '//Bob';
-
- const createTestCollection = async (issuerUri: string) => {
- return await createCollection(
- api,
- issuerUri,
- 'setprop-nft-collection-metadata',
- null,
- 'setprop',
- );
- };
-
- it('set NFT property', async () => {
- const ownerAlice = alice;
-
- const collectionId = await createTestCollection(alice);
- const nftId = await mintNft(api, alice, ownerAlice, collectionId, 'prop-nft');
-
- await setNftProperty(api, alice, collectionId, nftId, 'test-key', 'test-key-value');
- await setNftProperty(api, alice, collectionId, nftId, 'test-key', 'updated-key-value');
- await setNftProperty(api, alice, collectionId, nftId, 'second-test-key', 'second-test-key-value');
- });
-
- it('[negative] unable to set a property of non-existing NFT', async () => {
- const collectionId = 0;
- const maxNftId = 0xFFFFFFFF;
-
- const tx = setNftProperty(api, alice, collectionId, maxNftId, 'test-key', 'test-value');
-
- await expectTxFailure(/rmrkCore\.NoAvailableNftId/, tx);
- });
-
- it('[negative] unable to set a property by not-an-owner', async () => {
- const ownerAlice = alice;
-
- const collectionId = await createTestCollection(alice);
- const nftId = await mintNft(api, alice, ownerAlice, collectionId, 'prop-nft');
-
- const tx = setNftProperty(api, bob, collectionId, nftId, 'test-key', 'test-key-value');
-
- await expectTxFailure(/rmrkCore\.NoPermission/, tx);
- });
-
- it('set a property to nested NFT', async () => {
- const ownerAlice = alice;
-
- const collectionId = await createTestCollection(alice);
- const parentNftId = await mintNft(api, alice, ownerAlice, collectionId, 'prop-parent-nft');
- const childNftId = await mintNft(api, alice, ownerAlice, collectionId, 'prop-child-nft');
-
- const ownerNft: NftIdTuple = [collectionId, parentNftId];
-
- await sendNft(api, 'sent', ownerAlice, collectionId, childNftId, ownerNft);
-
- await setNftProperty(api, alice, collectionId, childNftId, 'test-key', 'test-key-value');
- });
-
- it('[negative] set a property to nested NFT (by not-root-owner)', async () => {
- const ownerAlice = alice;
-
- const collectionId = await createTestCollection(alice);
- const parentNftId = await mintNft(api, alice, ownerAlice, collectionId, 'prop-parent-nft');
- const childNftId = await mintNft(api, alice, ownerAlice, collectionId, 'prop-child-nft');
-
- const ownerNft: NftIdTuple = [collectionId, parentNftId];
-
- await sendNft(api, 'sent', ownerAlice, collectionId, childNftId, ownerNft);
-
- const tx = setNftProperty(api, bob, collectionId, childNftId, 'test-key', 'test-key-value');
-
- await expectTxFailure(/rmrkCore\.NoPermission/, tx);
- });
-
- after(async() => { await api.disconnect(); });
-});
tests/src/.outdated/rmrk/setResourcePriorities.seqtest.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/setResourcePriorities.seqtest.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import {getApiConnection} from '../substrate/substrate-api';
-import {expectTxFailure, requirePallets, Pallets} from './util/helpers';
-import {mintNft, createCollection, setResourcePriorities} from './util/tx';
-
-describe('integration test: set NFT resource priorities', () => {
- let api: any;
- before(async function () {
- api = await getApiConnection();
- await requirePallets(this, [Pallets.RmrkCore]);
- });
-
- const alice = '//Alice';
- const bob = '//Bob';
-
- const createTestCollection = (issuerUri: string) => {
- return createCollection(
- api,
- issuerUri,
- 'resprio-collection-metadata',
- null,
- 'resprio',
- );
- };
-
- it('set NFT resource priorities', async () => {
- const owner = alice;
-
- const collectionId = await createTestCollection(alice);
- const nftId = await mintNft(api, alice, owner, collectionId, 'resprio-nft-metadata');
-
- await setResourcePriorities(api, alice, collectionId, nftId, [10, 42]);
- });
-
- it('[negative] set NFT resource priorities by a not-an-owner', async () => {
- const owner = alice;
- const attacker = bob;
-
- const collectionId = await createTestCollection(alice);
- const nftId = await mintNft(api, alice, owner, collectionId, 'resprio-nft-metadata');
-
- const tx = setResourcePriorities(api, attacker, collectionId, nftId, [10, 42]);
-
- await expectTxFailure(/rmrkCore\.NoPermission/, tx);
- });
-
- it('[negative] set NFT resource priorities to non-existing NFT', async () => {
- const collectionId = 0;
- const maxNftId = 0xFFFFFFFF;
-
- const tx = setResourcePriorities(api, alice, collectionId, maxNftId, [10, 42]);
-
- await expectTxFailure(/rmrkCore\.NoAvailableNftId/, tx);
- });
-
- after(async() => { await api.disconnect(); });
-});
tests/src/.outdated/rmrk/util/fetch.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/util/fetch.ts
+++ /dev/null
@@ -1,130 +0,0 @@
-import {ApiPromise} from '@polkadot/api';
-import type {Option} from '@polkadot/types-codec';
-import type {
- RmrkTraitsCollectionCollectionInfo as Collection,
- RmrkTraitsNftNftInfo as Nft,
- RmrkTraitsResourceResourceInfo as Resource,
- RmrkTraitsBaseBaseInfo as Base,
- RmrkTraitsPartPartType as PartType,
- RmrkTraitsNftNftChild as NftChild,
- RmrkTraitsTheme as Theme,
- RmrkTraitsPropertyPropertyInfo as Property,
-} from '../../../interfaces/default/types'; // '@polkadot/types/lookup';
-import '../../../interfaces/augment-api';
-import '../../../interfaces/augment-api-query';
-import privateKey from '../../substrate/privateKey';
-
-export type NftIdTuple = [number, number];
-
-export async function getCollectionsCount(api: ApiPromise): Promise<number> {
- return (await api.rpc.rmrk.lastCollectionIdx()).toNumber();
-}
-
-export function getCollection(api: ApiPromise, id: number): Promise<Option<Collection>> {
- return api.rpc.rmrk.collectionById(id);
-}
-
-export async function getOwnedNfts(
- api: ApiPromise,
- ownerUri: string,
- collectionId: number,
-): Promise<number[]> {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const owner = privateKey(ownerUri, Number(ss58Format));
-
- return (await api.rpc.rmrk.accountTokens(owner.address, collectionId))
- .map((value) => value.toNumber());
-}
-
-export function getNft(api: ApiPromise, collectionId: number, nftId: number): Promise<Option<Nft>> {
- return api.rpc.rmrk.nftById(collectionId, nftId);
-}
-
-export async function getCollectionProperties(api: ApiPromise, collectionId: number): Promise<Property[]> {
- return (await api.rpc.rmrk.collectionProperties(collectionId)).toArray();
-}
-
-export async function getNftProperties(api: ApiPromise, collectionId: number, nftId: number): Promise<Property[]> {
- return (await api.rpc.rmrk.nftProperties(collectionId, nftId)).toArray();
-}
-
-export async function getChildren(
- api: ApiPromise,
- collectionId: number,
- nftId: number,
-): Promise<NftChild[]> {
- return (await api.rpc.rmrk.nftChildren(collectionId, nftId)).toArray();
-}
-
-export function getBase(api: ApiPromise, baseId: number): Promise<Option<Base>> {
- return api.rpc.rmrk.base(baseId);
-}
-
-export async function getParts(api: ApiPromise, baseId: number): Promise<PartType[]> {
- return (await api.rpc.rmrk.baseParts(baseId)).toArray();
-}
-
-export async function getEquippableList(
- api: ApiPromise,
- baseId: number,
- slotId: number,
-): Promise<'All' | 'Empty' | { 'Custom': number[] } | null> {
- const parts = await getParts(api, baseId);
-
- const part = parts.find((part) => {
- if (part.isSlotPart) {
- return part.asSlotPart.id.toNumber() === slotId;
- } else {
- return false;
- }
- });
-
- if (part) {
- const slot = part.asSlotPart;
- if (slot.equippable.isCustom) {
- return {
- 'Custom': slot.equippable.asCustom
- .toArray()
- .map((collectionId) => collectionId.toNumber()),
- };
- } else if (slot.equippable.isAll) {
- return 'All';
- } else {
- return 'Empty';
- }
- } else {
- return null;
- }
-}
-
-export async function getResourcePriority(
- api: ApiPromise,
- collectionId: number,
- nftId: number,
- resourceId: number,
-): Promise<number> {
- return (await api.rpc.rmrk.nftResourcePriority(collectionId, nftId, resourceId))
- .unwrap().toNumber();
-}
-
-export async function getThemeNames(api: ApiPromise, baseId: number): Promise<string[]> {
- return (await api.rpc.rmrk.themeNames(baseId))
- .map((name) => name.toUtf8());
-}
-
-export function getTheme(
- api: ApiPromise,
- baseId: number,
- themeName: string,
- keys: string[] | null = null,
-): Promise<Option<Theme>> {
- return api.rpc.rmrk.themes(baseId, themeName, keys);
-}
-
-export async function getResources(
- api: ApiPromise,
- collectionId: number,
- nftId: number,
-): Promise<Resource[]> {
- return (await api.rpc.rmrk.nftResources(collectionId, nftId)).toArray();
-}
tests/src/.outdated/rmrk/util/helpers.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/util/helpers.ts
+++ /dev/null
@@ -1,249 +0,0 @@
-import {ApiPromise} from '@polkadot/api';
-import {
- RmrkTraitsNftAccountIdOrCollectionNftTuple as NftOwner,
- RmrkTraitsPropertyPropertyInfo as Property,
- RmrkTraitsResourceResourceInfo as ResourceInfo,
-} from '@polkadot/types/lookup';
-import type {EventRecord} from '@polkadot/types/interfaces';
-import type {GenericEventData} from '@polkadot/types';
-import privateKey from '../../substrate/privateKey';
-import {NftIdTuple, getChildren, getOwnedNfts, getCollectionProperties, getNftProperties, getResources} from './fetch';
-import chaiAsPromised from 'chai-as-promised';
-import chai from 'chai';
-import {getApiConnection} from '../../substrate/substrate-api';
-import {Context} from 'mocha';
-
-chai.use(chaiAsPromised);
-const expect = chai.expect;
-
-interface TxResult<T> {
- success: boolean;
- successData: T | null;
-}
-
-export enum Pallets {
- Inflation = 'inflation',
- RmrkCore = 'rmrkcore',
- RmrkEquip = 'rmrkequip',
- ReFungible = 'refungible',
- Fungible = 'fungible',
- NFT = 'nonfungible',
- Scheduler = 'scheduler',
- AppPromotion = 'apppromotion',
-}
-
-let modulesNames: any;
-export function getModuleNames(api: ApiPromise): string[] {
- if (typeof modulesNames === 'undefined')
- modulesNames = api.runtimeMetadata.asLatest.pallets.map(m => m.name.toString().toLowerCase());
- return modulesNames;
-}
-
-export async function missingRequiredPallets(requiredPallets: string[]): Promise<string[]> {
- const api = await getApiConnection();
- const pallets = getModuleNames(api);
- await api.disconnect();
-
- return requiredPallets.filter(p => !pallets.includes(p));
-}
-
-export async function requirePallets(mocha: Context, requiredPallets: string[]) {
- const missingPallets = await missingRequiredPallets(requiredPallets);
-
- if (missingPallets.length > 0) {
- const skippingTestMsg = `\tSkipping test "${mocha.test?.title}".`;
- const missingPalletsMsg = `\tThe following pallets are missing:\n\t- ${missingPallets.join('\n\t- ')}`;
- const skipMsg = `${skippingTestMsg}\n${missingPalletsMsg}`;
-
- console.error('\x1b[38:5:208m%s\x1b[0m', skipMsg);
-
- mocha.skip();
- }
-}
-
-export function makeNftOwner(api: ApiPromise, owner: string | NftIdTuple): NftOwner {
- const isNftSending = (typeof owner !== 'string');
-
- if (isNftSending) {
- return api.createType('RmrkTraitsNftAccountIdOrCollectionNftTuple', {
- 'CollectionAndNftTuple': owner,
- });
- } else {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- return api.createType('RmrkTraitsNftAccountIdOrCollectionNftTuple', {
- AccountId: privateKey(owner, Number(ss58Format)).address,
- });
- }
-}
-
-export async function isNftOwnedBy(
- api: ApiPromise,
- owner: string | NftIdTuple,
- collectionId: number,
- nftId: number,
-): Promise<boolean> {
- if (typeof owner === 'string') {
- return (await getOwnedNfts(api, owner, collectionId))
- .find(ownedNftId => {
- return ownedNftId === nftId;
- }) !== undefined;
- } else {
- return (await getChildren(api, owner[0], owner[1]))
- .find(child => {
- return collectionId === child.collectionId.toNumber()
- && nftId === child.nftId.toNumber();
- }) !== undefined;
- }
-}
-
-export function isPropertyExists(
- key: string,
- value: string,
- props: Property[],
-): boolean {
- let isPropFound = false;
- for (let i = 0; i < props.length && !isPropFound; i++) {
- const fetchedProp = props[i];
-
- isPropFound = fetchedProp.key.eq(key)
- && fetchedProp.value.eq(value);
- }
-
- return isPropFound;
-}
-
-export async function isCollectionPropertyExists(
- api: ApiPromise,
- collectionId: number,
- key: string,
- value: string,
-): Promise<boolean> {
- const fetchedProps = await getCollectionProperties(api, collectionId);
- return isPropertyExists(key, value, fetchedProps);
-}
-
-export async function isNftPropertyExists(
- api: ApiPromise,
- collectionId: number,
- nftId: number,
- key: string,
- value: string,
-): Promise<boolean> {
- const fetchedProps = await getNftProperties(api, collectionId, nftId);
- return isPropertyExists(key, value, fetchedProps);
-}
-
-export async function isNftChildOfAnother(
- api: ApiPromise,
- collectionId: number,
- nftId: number,
- parentNft: NftIdTuple,
-): Promise<boolean> {
- return (await getChildren(api, parentNft[0], parentNft[1]))
- .find((childNft) => {
- return childNft.collectionId.toNumber() === collectionId
- && childNft.nftId.toNumber() === nftId;
- }) !== undefined;
-}
-
-export function isTxResultSuccess(events: EventRecord[]): boolean {
- let success = false;
-
- events.forEach(({event: {method}}) => {
- if (method == 'ExtrinsicSuccess') {
- success = true;
- }
- });
-
- return success;
-}
-
-export async function expectTxFailure(expectedError: RegExp, promise: Promise<any>) {
- await expect(promise).to.be.rejectedWith(expectedError);
-}
-
-export function extractTxResult<T>(
- events: EventRecord[],
- expectSection: string,
- expectMethod: string,
- extractAction: (data: any) => T,
-): TxResult<T> {
- let success = false;
- let successData = null;
- events.forEach(({event: {data, method, section}}) => {
- if (method == 'ExtrinsicSuccess') {
- success = true;
- } else if ((expectSection == section) && (expectMethod == method)) {
- successData = extractAction(data);
- }
- });
- const result: TxResult<T> = {
- success,
- successData,
- };
- return result;
-}
-
-export function extractRmrkCoreTxResult<T>(
- events: EventRecord[],
- expectMethod: string,
- extractAction: (data: GenericEventData) => T,
-): TxResult<T> {
- return extractTxResult(events, 'rmrkCore', expectMethod, extractAction);
-}
-
-export function extractRmrkEquipTxResult<T>(
- events: EventRecord[],
- expectMethod: string,
- extractAction: (data: GenericEventData) => T,
-): TxResult<T> {
- return extractTxResult(events, 'rmrkEquip', expectMethod, extractAction);
-}
-
-export async function findResourceById(
- api: ApiPromise,
- collectionId: number,
- nftId: number,
- resourceId: number,
-): Promise<ResourceInfo> {
- const resources = await getResources(api, collectionId, nftId);
-
- let resource = null;
-
- for (let i = 0; i < resources.length; i++) {
- const res = resources[i];
-
- if (res.id.eq(resourceId)) {
- resource = res;
- break;
- }
- }
-
- return resource!;
-}
-
-export async function getResourceById(
- api: ApiPromise,
- collectionId: number,
- nftId: number,
- resourceId: number,
-): Promise<ResourceInfo> {
- const resource = await findResourceById(
- api,
- collectionId,
- nftId,
- resourceId,
- );
-
- expect(resource !== null, 'Error: resource was not found').to.be.true;
-
- return resource!;
-}
-
-export function checkResourceStatus(
- resource: ResourceInfo,
- expectedStatus: 'pending' | 'added',
-) {
- expect(resource.pending.isTrue, `Error: added resource should be ${expectedStatus}`)
- .to.be.equal(expectedStatus === 'pending');
-}
tests/src/.outdated/rmrk/util/tx.tsdiffbeforeafterboth--- a/tests/src/.outdated/rmrk/util/tx.ts
+++ /dev/null
@@ -1,1132 +0,0 @@
-import {ApiPromise} from '@polkadot/api';
-import {Bytes, Option, u32, Vec} from '@polkadot/types-codec';
-import {
- RmrkTraitsNftAccountIdOrCollectionNftTuple as NftOwner, RmrkTraitsPartEquippableList as EquippableList,
- RmrkTraitsPartPartType as PartType, RmrkTraitsResourceBasicResource as BasicResource,
- RmrkTraitsResourceComposableResource as ComposableResource, RmrkTraitsResourceResourceInfo as ResourceInfo, RmrkTraitsResourceSlotResource as SlotResource, RmrkTraitsTheme as Theme,
-} from '@polkadot/types/lookup';
-import {IKeyringPair} from '@polkadot/types/types';
-import chai from 'chai';
-import chaiAsPromised from 'chai-as-promised';
-import '../../../interfaces/augment-api';
-import privateKey from '../../substrate/privateKey';
-import {executeTransaction} from '../../substrate/substrate-api';
-import {
- getBase,
- getCollection,
- getCollectionsCount,
- getEquippableList,
- getNft,
- getParts,
- getResources,
- getResourcePriority,
- getTheme,
- NftIdTuple,
-} from './fetch';
-import {
- extractRmrkCoreTxResult,
- extractRmrkEquipTxResult, isCollectionPropertyExists, isNftOwnedBy, isNftPropertyExists, isTxResultSuccess, makeNftOwner,
- findResourceById, getResourceById, checkResourceStatus,
-} from './helpers';
-
-chai.use(chaiAsPromised);
-const expect = chai.expect;
-
-export async function createCollection(
- api: ApiPromise,
- issuerUri: string,
- metadata: string,
- max: number | null,
- symbol: string,
-): Promise<number> {
- let collectionId = 0;
-
- const oldCollectionCount = await getCollectionsCount(api);
- const maxOptional = max ? max.toString() : null;
- const ss58Format = (api.registry.getChainProperties())!.toJSON().ss58Format;
- const issuer = privateKey(issuerUri, Number(ss58Format));
- const tx = api.tx.rmrkCore.createCollection(metadata, maxOptional, symbol);
- const events = await executeTransaction(api, issuer, tx);
-
- const collectionResult = extractRmrkCoreTxResult(events, 'CollectionCreated', (data) => {
- return parseInt(data[1].toString(), 10);
- });
- expect(collectionResult.success, 'Error: unable to create a collection').to.be.true;
-
- collectionId = collectionResult.successData!;
-
- const newCollectionCount = await getCollectionsCount(api);
- const collectionOption = await getCollection(api, collectionId);
-
- expect(newCollectionCount).to.be.equal(oldCollectionCount + 1, 'Error: NFT collection count should increase');
- expect(collectionOption.isSome, 'Error: unable to fetch created NFT collection').to.be.true;
-
- const collection = collectionOption.unwrap();
-
- expect(collection.metadata.toUtf8()).to.be.equal(metadata, 'Error: Invalid NFT collection metadata');
- expect(collection.max.isSome).to.be.equal(max !== null, 'Error: Invalid NFT collection max');
-
- if (collection.max.isSome) {
- expect(collection.max.unwrap().toNumber()).to.be.equal(max, 'Error: Invalid NFT collection max');
- }
- expect(collection.symbol.toUtf8()).to.be.equal(symbol, "Error: Invalid NFT collection's symbol");
- expect(collection.nftsCount.toNumber()).to.be.equal(0, "Error: NFT collection shoudn't have any tokens");
- expect(collection.issuer.toString()).to.be.equal(issuer.address, 'Error: Invalid NFT collection issuer');
-
- return collectionId;
-}
-
-export async function changeIssuer(
- api: ApiPromise,
- issuerUri: string,
- collectionId: number,
- newIssuer: string,
-) {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const alice = privateKey(issuerUri, Number(ss58Format));
- const bob = privateKey(newIssuer, Number(ss58Format));
-
- // This is only needed when RMRK uses `uniques` pallet by Parity
- // let tx = api.tx.uniques.setAcceptOwnership(
- // api.createType('Option<u32>', collectionId)
- // );
- // let events = await executeTransaction(api, bob, tx);
- // expect(isTxResultSuccess(events), 'Error: Unable to accept ownership').to.be.true;
-
- const tx = api.tx.rmrkCore.changeCollectionIssuer(collectionId, bob.address);
- const events = await executeTransaction(api, alice, tx);
- const changeIssuerResult = extractRmrkCoreTxResult(events, 'IssuerChanged', (data) => {
- return parseInt(data[2].toString(), 10);
- });
- expect(changeIssuerResult.success, 'Error: Unable to change NFT collection issuer').to.be.true;
- expect(changeIssuerResult.successData!, 'Error: Invalid collection id after changing the issuer')
- .to.be.eq(collectionId);
-
- await getCollection(api, collectionId).then((collectionOption) => {
- const collection = collectionOption.unwrap();
- expect(collection.issuer.toString())
- .to.be.deep.eq(bob.address, 'Error: Invalid NFT collection issuer');
- });
-}
-
-export async function deleteCollection(
- api: ApiPromise,
- issuerUri: string,
- collectionId: string,
-): Promise<number> {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const issuer = privateKey(issuerUri, Number(ss58Format));
- const tx = api.tx.rmrkCore.destroyCollection(collectionId);
- const events = await executeTransaction(api, issuer, tx);
-
- const collectionTxResult = extractRmrkCoreTxResult(
- events,
- 'CollectionDestroy',
- (data) => {
- return parseInt(data[1].toString(), 10);
- },
- );
- expect(collectionTxResult.success, 'Error: Unable to delete NFT collection').to.be.true;
-
- const collection = await getCollection(
- api,
- parseInt(collectionId, 10),
- );
- expect(collection.isEmpty, 'Error: NFT collection should be deleted').to.be.true;
-
- return 0;
-}
-
-export async function negativeDeleteCollection(
- api: ApiPromise,
- issuerUri: string,
- collectionId: string,
-): Promise<number> {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const issuer = privateKey(issuerUri, Number(ss58Format));
- const tx = api.tx.rmrkCore.destroyCollection(collectionId);
- await expect(executeTransaction(api, issuer, tx)).to.be.rejected;
-
- return 0;
-}
-
-export async function setNftProperty(
- api: ApiPromise,
- issuerUri: string,
- collectionId: number,
- nftId: number,
- key: string,
- value: string,
-) {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const issuer = privateKey(issuerUri, Number(ss58Format));
- const nftIdOpt = api.createType('Option<u32>', nftId);
- const tx = api.tx.rmrkCore.setProperty(
- collectionId,
- nftIdOpt,
- key,
- value,
- );
- const events = await executeTransaction(api, issuer, tx);
-
- const propResult = extractRmrkCoreTxResult(events, 'PropertySet', (data) => {
- return {
- collectionId: parseInt(data[0].toString(), 10),
- nftId: data[1] as Option<u32>,
- key: data[2] as Bytes,
- value: data[3] as Bytes,
- };
- });
-
- expect(propResult.success, 'Error: Unable to set NFT property').to.be.true;
- const eventData = propResult.successData!;
- const eventDescription = 'from set NFT property event';
-
- expect(eventData.collectionId, 'Error: Invalid collection ID ' + eventDescription)
- .to.be.equal(collectionId);
-
- expect(eventData.nftId.eq(nftIdOpt), 'Error: Invalid NFT ID ' + eventDescription)
- .to.be.true;
-
- expect(eventData.key.eq(key), 'Error: Invalid property key ' + eventDescription)
- .to.be.true;
-
- expect(eventData.value.eq(value), 'Error: Invalid property value ' + eventDescription)
- .to.be.true;
-
- expect(
- await isNftPropertyExists(api, collectionId, nftId, key, value),
- 'Error: NFT property is not found',
- ).to.be.true;
-}
-
-export async function mintNft(
- api: ApiPromise,
- issuerUri: string,
- ownerUri: string | null,
- collectionId: number,
- metadata: string,
- recipientUri: string | null = null,
- royalty: number | null = null,
- transferable = true,
- resources: {basic?: any, composable?: any, slot?: any}[] | null = null,
-): Promise<number> {
- let nftId = 0;
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const issuer = privateKey(issuerUri, Number(ss58Format));
- const owner = ownerUri ? privateKey(ownerUri, Number(ss58Format)).address : null;
- const recipient = recipientUri ? privateKey(recipientUri, Number(ss58Format)).address : null;
- const royaltyOptional = royalty ? royalty.toString() : null;
-
- const actualOwnerUri = ownerUri ? ownerUri : issuerUri;
- const actualOwnerAddress = ownerUri ? owner : issuer.address;
-
- const collectionOpt = await getCollection(api, collectionId);
-
- const tx = api.tx.rmrkCore.mintNft(
- owner,
- collectionId,
- recipient,
- royaltyOptional,
- metadata,
- transferable,
- resources as any,
- );
-
- const events = await executeTransaction(api, issuer, tx);
- const nftResult = extractRmrkCoreTxResult(events, 'NftMinted', (data) => {
- return parseInt(data[2].toString(), 10);
- });
-
- expect(nftResult.success, 'Error: Unable to mint NFT').to.be.true;
-
- const newCollectionNftsCount = (await getCollection(api, collectionId))
- .unwrap()
- .nftsCount
- .toNumber();
-
- const oldCollectionNftsCount = collectionOpt
- .unwrap()
- .nftsCount.toNumber();
-
- expect(newCollectionNftsCount, 'Error: NFTs count should increase')
- .to.be.equal(oldCollectionNftsCount + 1);
-
- nftId = nftResult.successData!;
-
- const nftOption = await getNft(api, collectionId, nftId);
-
- expect(nftOption.isSome, 'Error: Unable to fetch created NFT').to.be.true;
-
- const nft = nftOption.unwrap();
-
- expect(nft.owner.isAccountId, 'Error: NFT owner should be some user').to.be.true;
- expect(nft.owner.asAccountId.toString()).to.be.equal(actualOwnerAddress, 'Error: Invalid NFT owner');
-
- const isOwnedInUniques = await isNftOwnedBy(api, actualOwnerUri, collectionId, nftId);
- expect(isOwnedInUniques, `Error: created NFT is not actually owned by ${ownerUri}`)
- .to.be.true;
-
- if (recipient === null && royalty === null) {
- expect(nft.royalty.isNone, 'Error: Invalid NFT recipient')
- .to.be.true;
- } else {
- expect(nft.royalty.isSome, 'Error: NFT royalty not found')
- .to.be.true;
-
- const nftRoyalty = nft.royalty.unwrap();
- expect(nftRoyalty.recipient.eq(recipient), 'Error: Invalid NFT recipient')
- .to.be.true;
-
- expect(nftRoyalty.amount.eq(royalty), 'Error: Invalid NFT royalty')
- .to.be.true;
- }
-
- expect(nft.metadata.toUtf8()).to.be.equal(metadata, 'Error: Invalid NFT metadata');
-
- const nftResources = await getResources(api, collectionId, nftId);
- if (resources == null) {
- expect(nftResources, 'Error: Invalid NFT resources').to.be.empty;
- } else {
- expect(nftResources.length).to.be.equal(resources.length);
-
- for (let i = 0; i < resources.length; i++) {
- let successFindingResource = false;
- const resource = resources[i];
- // try to find the matching resource from the query
- for (let j = 0; j < nftResources.length && !successFindingResource; j++) {
- const nftResourceData = nftResources[j].toHuman();
- expect(
- Object.prototype.hasOwnProperty.call(nftResourceData, 'resource'),
- `Error: Corrupted resource data on resource #${i}`,
- ).to.be.true;
- const nftResource = nftResourceData.resource!;
- type NftResourceKey = keyof typeof nftResource;
-
- let typedResource = null;
- let typedNftResource = null;
-
- if (resource.basic && Object.prototype.hasOwnProperty.call(nftResource, 'Basic')) {
- typedResource = resource.basic!;
- typedNftResource = nftResource['Basic' as NftResourceKey]!;
- } else if (resource.composable && Object.prototype.hasOwnProperty.call(nftResource, 'Composable')) {
- typedResource = resource.composable!;
- typedNftResource = nftResource['Composable' as NftResourceKey]! as any;
- if (typedResource.parts != undefined && typedResource.parts.toString() != typedNftResource.parts.toString()
- || typedResource.base != typedNftResource.base && typedResource.base != undefined) {
- continue;
- }
- } else if (resource.slot && Object.prototype.hasOwnProperty.call(nftResource, 'Slot')) {
- typedResource = resource.slot!;
- typedNftResource = nftResource['Slot' as NftResourceKey]! as any;
- if (typedResource.slot != typedNftResource.slot && typedResource.slot != undefined
- || typedResource.base != typedNftResource.base && typedResource.base != undefined) {
- continue;
- }
- } else {
- continue;
- }
-
- if (typedResource.src != typedNftResource.src
- || typedResource.metadata != typedNftResource.metadata
- || typedResource.thumb != typedNftResource.thumb
- || typedResource.license != typedNftResource.license
- ) {
- continue;
- }
-
- // do final checks since this is now established to be the resource we seek
- expect(nftResourceData.pending, `Error: Resource #${i} is pending`).to.be.false;
- expect(nftResourceData.pendingRemoval, `Error: Resource #${i} is pending removal`).to.be.false;
-
- // remove the matching resource from the resources we check
- nftResources.splice(j, 1);
- successFindingResource = true;
- }
-
- expect(successFindingResource, `Error: Couldn't find resource #${i}'s counterpart among the returned`).to.be.true;
- }
- }
-
- return nftId;
-}
-
-export async function sendNft(
- api: ApiPromise,
- expectedStatus: 'pending' | 'sent',
- originalOwnerUri: string,
- collectionId: number,
- nftId: number,
- newOwner: string | NftIdTuple,
-) {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const originalOwner = privateKey(originalOwnerUri, Number(ss58Format));
- const newOwnerObj = makeNftOwner(api, newOwner);
-
- const nftBeforeSendingOpt = await getNft(api, collectionId, nftId);
-
- const tx = api.tx.rmrkCore.send(collectionId, nftId, newOwnerObj);
- const events = await executeTransaction(api, originalOwner, tx);
-
- const sendResult = extractRmrkCoreTxResult(events, 'NFTSent', (data) => {
- return {
- dstOwner: data[1] as NftOwner,
- collectionId: parseInt(data[2].toString(), 10),
- nftId: parseInt(data[3].toString(), 10),
- };
- });
-
- expect(sendResult.success, 'Error: Unable to send NFT').to.be.true;
- const sendData = sendResult.successData!;
-
- expect(sendData.dstOwner.eq(newOwnerObj), 'Error: Invalid target user (from event data)')
- .to.be.true;
-
- expect(sendData.collectionId)
- .to.be.equal(collectionId, 'Error: Invalid collection ID (from event data)');
-
- expect(sendData.nftId).to.be.equal(nftId, 'Error: Invalid NFT ID (from event data)');
-
- expect(nftBeforeSendingOpt.isSome, 'Error: Unable to fetch NFT before sending').to.be.true;
-
- const nftBeforeSending = nftBeforeSendingOpt.unwrap();
-
- const nftAfterSendingOpt = await getNft(api, collectionId, nftId);
-
- expect(nftAfterSendingOpt.isSome, 'Error: Unable to fetch NFT after sending').to.be.true;
-
- const nftAfterSending = nftAfterSendingOpt.unwrap();
-
- const isOwnedByNewOwner = await isNftOwnedBy(api, newOwner, collectionId, nftId);
- const isPending = expectedStatus === 'pending';
-
- expect(
- isOwnedByNewOwner,
- `Error: The NFT should be owned by ${newOwner.toString()}`,
- ).to.be.true;
-
- expect(nftAfterSending.royalty.eq(nftBeforeSending.royalty), 'Error: Invalid NFT royalty after sending')
- .to.be.true;
-
- expect(nftAfterSending.metadata.eq(nftBeforeSending.metadata), 'Error: Invalid NFT metadata after sending')
- .to.be.true;
-
- expect(nftAfterSending.equipped.eq(nftBeforeSending.equipped), 'Error: Invalid NFT equipped status after sending')
- .to.be.true;
-
- expect(nftAfterSending.pending.eq(isPending), 'Error: Invalid NFT pending state')
- .to.be.true;
-}
-
-export async function acceptNft(
- api: ApiPromise,
- issuerUri: string,
- collectionId: number,
- nftId: number,
- newOwner: string | [number, number],
-) {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const issuer = privateKey(issuerUri, Number(ss58Format));
- const newOwnerObj = makeNftOwner(api, newOwner);
-
- const nftBeforeOpt = await getNft(api, collectionId, nftId);
-
- const tx = api.tx.rmrkCore.acceptNft(collectionId, nftId, newOwnerObj);
- const events = await executeTransaction(api, issuer, tx);
-
- const acceptResult = extractRmrkCoreTxResult(events, 'NFTAccepted', (data) => {
- return {
- recipient: data[1] as NftOwner,
- collectionId: parseInt(data[2].toString(), 10),
- nftId: parseInt(data[3].toString(), 10),
- };
- });
-
- expect(acceptResult.success, 'Error: Unable to accept NFT').to.be.true;
- const acceptData = acceptResult.successData!;
-
- expect(acceptData.recipient.eq(newOwnerObj), 'Error: Invalid NFT recipient (from event data)')
- .to.be.true;
-
- expect(acceptData.collectionId)
- .to.be.equal(collectionId, 'Error: Invalid collection ID (from event data)');
-
- expect(acceptData.nftId)
- .to.be.equal(nftId, 'Error: Invalid NFT ID (from event data)');
-
- const nftBefore = nftBeforeOpt.unwrap();
-
- const isPendingBeforeAccept = nftBefore.pending.isTrue;
-
- const nftAfter = (await getNft(api, collectionId, nftId)).unwrap();
- const isPendingAfterAccept = nftAfter.pending.isTrue;
-
- expect(isPendingBeforeAccept, 'Error: NFT should be pending to be accepted')
- .to.be.true;
-
- expect(isPendingAfterAccept, 'Error: NFT should NOT be pending after accept')
- .to.be.false;
-
- const isOwnedInUniques = await isNftOwnedBy(api, newOwner, collectionId, nftId);
- expect(isOwnedInUniques, `Error: created NFT is not actually owned by ${newOwner.toString()}`)
- .to.be.true;
-}
-
-export async function rejectNft(
- api: ApiPromise,
- issuerUri: string,
- collectionId: number,
- nftId: number,
-) {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const issuer = privateKey(issuerUri, Number(ss58Format));
- const nftBeforeOpt = await getNft(api, collectionId, nftId);
-
- const tx = api.tx.rmrkCore.rejectNft(collectionId, nftId);
- const events = await executeTransaction(api, issuer, tx);
- const rejectResult = extractRmrkCoreTxResult(events, 'NFTRejected', (data) => {
- return {
- collectionId: parseInt(data[1].toString(), 10),
- nftId: parseInt(data[2].toString(), 10),
- };
- });
-
- const rejectData = rejectResult.successData!;
-
- expect(rejectData.collectionId)
- .to.be.equal(collectionId, 'Error: Invalid collection ID (from event data)');
-
- expect(rejectData.nftId)
- .to.be.equal(nftId, 'Error: Invalid NFT ID (from event data)');
-
- const nftBefore = nftBeforeOpt.unwrap();
-
- const isPendingBeforeReject = nftBefore.pending.isTrue;
-
- const nftAfter = await getNft(api, collectionId, nftId);
-
- expect(isPendingBeforeReject, 'Error: NFT should be pending to be rejected')
- .to.be.true;
-
- expect(nftAfter.isNone, 'Error: NFT should be burned after reject')
- .to.be.true;
-}
-
-export async function createBase(
- api: ApiPromise,
- issuerUri: string,
- baseType: string,
- symbol: string,
- parts: object[],
-): Promise<number> {
- let baseId = 0;
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const issuer = privateKey(issuerUri, Number(ss58Format));
-
- const partTypes = api.createType('Vec<RmrkTraitsPartPartType>', parts) as Vec<PartType>;
-
- const tx = api.tx.rmrkEquip.createBase(baseType, symbol, partTypes);
- const events = await executeTransaction(api, issuer, tx);
-
- const baseResult = extractRmrkEquipTxResult(events, 'BaseCreated', (data) => {
- return parseInt(data[1].toString(), 10);
- });
-
- expect(baseResult.success, 'Error: Unable to create Base')
- .to.be.true;
-
- baseId = baseResult.successData!;
- const baseOptional = await getBase(api, baseId);
-
- expect(baseOptional.isSome, 'Error: Unable to fetch created Base')
- .to.be.true;
-
- const base = baseOptional.unwrap();
- const baseParts = await getParts(api, baseId);
-
- expect(base.issuer.toString()).to.be.equal(issuer.address, 'Error: Invalid Base issuer');
- expect(base.baseType.toUtf8()).to.be.equal(baseType, 'Error: Invalid Base type');
- expect(base.symbol.toUtf8()).to.be.equal(symbol, 'Error: Invalid Base symbol');
- expect(partTypes.eq(baseParts), 'Error: Received invalid base parts').to.be.true;
-
- return baseId;
-}
-
-export async function setResourcePriorities(
- api: ApiPromise,
- issuerUri: string,
- collectionId: number,
- nftId: number,
- priorities: number[],
-) {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const issuer = privateKey(issuerUri, Number(ss58Format));
-
- const prioritiesVec = api.createType('Vec<u32>', priorities);
- const tx = api.tx.rmrkCore.setPriority(collectionId, nftId, prioritiesVec);
- const events = await executeTransaction(api, issuer, tx);
-
- const prioResult = extractRmrkCoreTxResult(events, 'PrioritySet', (data) => {
- return {
- collectionId: parseInt(data[0].toString(), 10),
- nftId: parseInt(data[1].toString(), 10),
- };
- });
-
- expect(prioResult.success, 'Error: Unable to set resource priorities').to.be.true;
- const eventData = prioResult.successData!;
-
- expect(eventData.collectionId)
- .to.be.equal(collectionId, 'Error: Invalid collection ID (set priorities event data)');
-
- expect(eventData.nftId).to.be.equal(nftId, 'Error: Invalid NFT ID (set priorities event data');
-
- for (let i = 0; i < priorities.length; i++) {
- const resourceId = priorities[i];
-
- const fetchedPrio = await getResourcePriority(api, collectionId, nftId, resourceId);
- expect(fetchedPrio).to.be.equal(i, 'Error: Invalid priorities are set');
- }
-
-}
-
-export async function setEquippableList(
- api: ApiPromise,
- issuerUri: string,
- baseId: number,
- slotId: number,
- equippableList: 'All' | 'Empty' | { 'Custom': number[] },
-) {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const issuer = privateKey(issuerUri, Number(ss58Format));
- const equippable = api.createType('RmrkTraitsPartEquippableList', equippableList) as EquippableList;
-
- const tx = api.tx.rmrkEquip.equippable(baseId, slotId, equippable);
- const events = await executeTransaction(api, issuer, tx);
-
- const equipListResult = extractRmrkEquipTxResult(events, 'EquippablesUpdated', (data) => {
- return {
- baseId: parseInt(data[0].toString(), 10),
- slotId: parseInt(data[1].toString(), 10),
- };
- });
-
- expect(equipListResult.success, 'Error: unable to update equippable list').to.be.true;
- const updateEvent = equipListResult.successData!;
-
- expect(updateEvent.baseId)
- .to.be.equal(baseId, 'Error: invalid base ID from update equippable event');
-
- expect(updateEvent.slotId)
- .to.be.equal(slotId, 'Error: invalid base ID from update equippable event');
-
- const fetchedEquippableList = await getEquippableList(api, baseId, slotId);
-
- expect(fetchedEquippableList, 'Error: unable to fetch equippable list').to.be.not.null;
- if (fetchedEquippableList) {
- expect(fetchedEquippableList)
- .to.be.deep.equal(equippableList, 'Error: invalid equippable list was set');
- }
-}
-
-export async function addTheme(
- api: ApiPromise,
- issuerUri: string,
- baseId: number,
- themeObj: object,
- filterKeys: string[] | null = null,
-) {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const issuer = privateKey(issuerUri, Number(ss58Format));
- const theme = api.createType('RmrkTraitsTheme', themeObj) as Theme;
-
- const tx = api.tx.rmrkEquip.themeAdd(baseId, theme);
- const events = await executeTransaction(api, issuer, tx);
-
- expect(isTxResultSuccess(events), 'Error: Unable to add Theme').to.be.true;
-
- const fetchedThemeOpt = await getTheme(api, baseId, theme.name.toUtf8(), null);
-
- expect(fetchedThemeOpt.isSome, 'Error: Unable to fetch theme').to.be.true;
-
- const fetchedTheme = fetchedThemeOpt.unwrap();
-
- expect(theme.name.eq(fetchedTheme.name), 'Error: Invalid theme name').to.be.true;
-
- for (let i = 0; i < theme.properties.length; i++) {
- const property = theme.properties[i];
- const propertyKey = property.key.toUtf8();
-
- const propertyFoundCount = fetchedTheme.properties.filter((fetchedProp) => property.key.eq(fetchedProp.key)).length;
-
- expect(propertyFoundCount > 1, `Error: Too many properties with key ${propertyKey} found`)
- .to.be.false;
-
- if (filterKeys) {
- const isFiltered = fetchedTheme.properties.find((fetchedProp) => fetchedProp.key.eq(property.key)) === undefined;
-
- if (isFiltered) {
- expect(propertyFoundCount === 0, `Error: Unexpected filtered key ${propertyKey}`)
- .to.be.true;
- continue;
- }
- }
-
- expect(propertyFoundCount === 1, `Error: The property with key ${propertyKey} is not found`)
- .to.be.true;
- }
-}
-
-export async function lockCollection(
- api: ApiPromise,
- issuerUri: string,
- collectionId: number,
- max = 0,
-) {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const issuer = privateKey(issuerUri, Number(ss58Format));
- const tx = api.tx.rmrkCore.lockCollection(collectionId);
- const events = await executeTransaction(api, issuer, tx);
- const lockResult = extractRmrkCoreTxResult(events, 'CollectionLocked', (data) => {
- return parseInt(data[1].toString(), 10);
- });
- expect(lockResult.success, 'Error: Unable to lock a collection').to.be.true;
- expect(lockResult.successData!, 'Error: Invalid collection was locked')
- .to.be.eq(collectionId);
-
- await getCollection(api, collectionId).then((collectionOption) => {
- const collection = collectionOption.unwrap();
- expect(collection.max.unwrap().toNumber()).to.be.equal(max);
- });
-}
-
-export async function setPropertyCollection(
- api: ApiPromise,
- issuerUri: string,
- collectionId: number,
- key: string,
- value: string,
-) {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const alice = privateKey(issuerUri, Number(ss58Format));
-
- const tx = api.tx.rmrkCore.setProperty(collectionId, null, key, value);
- const events = await executeTransaction(api, alice, tx);
- const propResult = extractRmrkCoreTxResult(events, 'PropertySet', (data) => {
- return {
- collectionId: parseInt(data[0].toString(), 10),
- nftId: data[1] as Option<u32>,
- key: data[2] as Bytes,
- value: data[3] as Bytes,
- };
- });
-
- expect(propResult.success, 'Error: Unable to set collection property').to.be.true;
- const eventData = propResult.successData!;
- const eventDescription = 'from set collection property event';
-
- expect(eventData.collectionId, 'Error: Invalid collection ID ' + eventDescription)
- .to.be.equal(collectionId);
-
- expect(eventData.nftId.eq(null), 'Error: Unexpected NFT ID ' + eventDescription)
- .to.be.true;
-
- expect(eventData.key.eq(key), 'Error: Invalid property key ' + eventDescription)
- .to.be.true;
-
- expect(eventData.value.eq(value), 'Error: Invalid property value ' + eventDescription)
- .to.be.true;
-
- expect(await isCollectionPropertyExists(api, collectionId, key, value))
- .to.be.true;
-}
-
-export async function burnNft(
- api: ApiPromise,
- issuerUri: string,
- collectionId: number,
- nftId: number,
-) {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const issuer = privateKey(issuerUri, Number(ss58Format));
- const maxBurns = 10;
- const tx = api.tx.rmrkCore.burnNft(collectionId, nftId, maxBurns);
- const events = await executeTransaction(api, issuer, tx);
- const burnResult = extractRmrkCoreTxResult(events, 'NFTBurned', (data) => {
- return parseInt(data[1].toString(), 10);
- });
-
- expect(burnResult.success, 'Error: Unable to burn an NFT').to.be.true;
- expect(burnResult.successData!, 'Error: Invalid NFT was burned')
- .to.be.eq(nftId);
-
- const nftBurned = await getNft(api, collectionId, nftId);
- expect(nftBurned.isSome).to.be.false;
-}
-
-export async function acceptNftResource(
- api: ApiPromise,
- issuerUri: string,
- collectionId: number,
- nftId: number,
- resourceId: number,
-) {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const issuer = privateKey(issuerUri, Number(ss58Format));
-
- const tx = api.tx.rmrkCore.acceptResource(
- collectionId,
- nftId,
- resourceId,
- );
-
- const events = await executeTransaction(api, issuer, tx);
- const acceptResult = extractRmrkCoreTxResult(events, 'ResourceAccepted', (data) => {
- return {
- nftId: parseInt(data[0].toString(), 10),
- resourceId: parseInt(data[1].toString(), 10),
- };
- });
-
- expect(acceptResult.success, 'Error: Unable to accept a resource').to.be.true;
- expect(acceptResult.successData!.nftId, 'Error: Invalid NFT ID while accepting a resource')
- .to.be.eq(nftId);
- expect(acceptResult.successData!.resourceId, 'Error: Invalid resource ID while accepting a resource')
- .to.be.eq(resourceId);
-
- const resource = await getResourceById(api, collectionId, nftId, resourceId);
- checkResourceStatus(resource, 'added');
-}
-
-async function executeResourceCreation(
- api: ApiPromise,
- issuer: IKeyringPair,
- tx: any,
- collectionId: number,
- nftId: number,
- expectedStatus: 'pending' | 'added',
-): Promise<ResourceInfo> {
- const events = await executeTransaction(api, issuer, tx);
-
- const resourceResult = extractRmrkCoreTxResult(events, 'ResourceAdded', (data) => {
- return parseInt(data[1].toString(), 10);
- });
- expect(resourceResult.success, 'Error: Unable to add resource').to.be.true;
- const resourceId = resourceResult.successData!;
-
- const resource = await getResourceById(api, collectionId, nftId, resourceId);
- checkResourceStatus(resource, expectedStatus);
-
- return resource;
-}
-
-export async function addNftBasicResource(
- api: ApiPromise,
- issuerUri: string,
- expectedStatus: 'pending' | 'added',
- collectionId: number,
- nftId: number,
- src: string | null,
- metadata: string | null,
- license: string | null,
- thumb: string | null,
-): Promise<number> {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const issuer = privateKey(issuerUri, Number(ss58Format));
-
- const basicResource = api.createType('RmrkTraitsResourceBasicResource', {
- src: src,
- metadata: metadata,
- license: license,
- thumb: thumb,
- }) as BasicResource;
-
- const tx = api.tx.rmrkCore.addBasicResource(
- collectionId,
- nftId,
- basicResource,
- );
-
- const resource = await executeResourceCreation(api, issuer, tx, collectionId, nftId, expectedStatus);
-
- // FIXME A workaround. It seems it is a PolkadotJS bug.
- // All of the following are `false`.
- //
- // console.log('>>> basic:', resource.resource.isBasic);
- // console.log('>>> composable:', resource.resource.isComposable);
- // console.log('>>> slot:', resource.resource.isSlot);
- const resourceJson = resource.resource.toHuman() as any;
-
- expect(Object.prototype.hasOwnProperty.call(resourceJson, 'Basic'), 'Error: Expected basic resource type')
- .to.be.true;
-
- const recvBasicRes = resourceJson['Basic'];
-
- expect(recvBasicRes.src, 'Error: Invalid basic resource src')
- .to.be.eq(src);
- expect(recvBasicRes.metadata, 'Error: basic first resource metadata')
- .to.be.eq(metadata);
- expect(recvBasicRes.license, 'Error: basic first resource license')
- .to.be.eq(license);
- expect(recvBasicRes.thumb, 'Error: basic first resource thumb')
- .to.be.eq(thumb);
-
- return resource.id.toNumber();
-}
-
-export async function addNftComposableResource(
- api: ApiPromise,
- issuerUri: string,
- expectedStatus: 'pending' | 'added',
- collectionId: number,
- nftId: number,
- parts: number[],
- baseId: number,
- src: string | null,
- metadata: string | null,
- license: string | null,
- thumb: string | null,
-): Promise<number> {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const issuer = privateKey(issuerUri, Number(ss58Format));
-
- const composableResource = api.createType('RmrkTraitsResourceComposableResource', {
- parts: parts, // api.createType('Vec<u32>', parts),
- base: baseId,
- src: src,
- metadata: metadata,
- license: license,
- thumb: thumb,
- }) as ComposableResource;
-
- const tx = api.tx.rmrkCore.addComposableResource(
- collectionId,
- nftId,
- composableResource,
- );
-
- const resource = await executeResourceCreation(api, issuer, tx, collectionId, nftId, expectedStatus);
-
- // FIXME A workaround. It seems it is a PolkadotJS bug.
- // All of the following are `false`.
- //
- // console.log('>>> basic:', resource.resource.isBasic);
- // console.log('>>> composable:', resource.resource.isComposable);
- // console.log('>>> slot:', resource.resource.isSlot);
- const resourceJson = resource.resource.toHuman() as any;
-
- expect(Object.prototype.hasOwnProperty.call(resourceJson, 'Composable'), 'Error: Expected composable resource type')
- .to.be.true;
-
- const recvComposableRes = resourceJson['Composable'];
-
- expect(recvComposableRes.parts.toString(), 'Error: Invalid composable resource parts')
- .to.be.eq(parts.toString());
- expect(recvComposableRes.base, 'Error: Invalid composable resource base id')
- .to.be.eq(baseId.toString());
- expect(recvComposableRes.src, 'Error: Invalid composable resource src')
- .to.be.eq(src);
- expect(recvComposableRes.metadata, 'Error: Invalid composable resource metadata')
- .to.be.eq(metadata);
- expect(recvComposableRes.license, 'Error: Invalid composable resource license')
- .to.be.eq(license);
- expect(recvComposableRes.thumb, 'Error: Invalid composable resource thumb')
- .to.be.eq(thumb);
-
- return resource.id.toNumber();
-}
-
-export async function addNftSlotResource(
- api: ApiPromise,
- issuerUri: string,
- expectedStatus: 'pending' | 'added',
- collectionId: number,
- nftId: number,
- baseId: number,
- slotId: number,
- src: string | null,
- metadata: string | null,
- license: string | null,
- thumb: string | null,
-): Promise<number> {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const issuer = privateKey(issuerUri, Number(ss58Format));
-
- const slotResource = api.createType('RmrkTraitsResourceSlotResource', {
- base: baseId,
- src: src,
- metadata,
- slot: slotId,
- license: license,
- thumb: thumb,
- }) as SlotResource;
-
- const tx = api.tx.rmrkCore.addSlotResource(
- collectionId,
- nftId,
- slotResource,
- );
-
- const resource = await executeResourceCreation(api, issuer, tx, collectionId, nftId, expectedStatus);
-
- // FIXME A workaround. It seems it is a PolkadotJS bug.
- // All of the following are `false`.
- //
- // console.log('>>> basic:', resource.resource.isBasic);
- // console.log('>>> composable:', resource.resource.isComposable);
- // console.log('>>> slot:', resource.resource.isSlot);
- const resourceJson = resource.resource.toHuman() as any;
-
- expect(Object.prototype.hasOwnProperty.call(resourceJson, 'Slot'), 'Error: Expected slot resource type')
- .to.be.true;
-
- const recvSlotRes = resourceJson['Slot'];
-
- expect(recvSlotRes.base, 'Error: Invalid slot resource base id')
- .to.be.eq(baseId.toString());
- expect(recvSlotRes.slot, 'Error: Invalid slot resource slot id')
- .to.be.eq(slotId.toString());
- expect(recvSlotRes.src, 'Error: Invalid slot resource src')
- .to.be.eq(src);
- expect(recvSlotRes.metadata, 'Error: Invalid slot resource metadata')
- .to.be.eq(metadata);
- expect(recvSlotRes.license, 'Error: Invalid slot resource license')
- .to.be.eq(license);
- expect(recvSlotRes.thumb, 'Error: Invalid slot resource thumb')
- .to.be.eq(thumb);
-
- return resource.id.toNumber();
-}
-
-export async function equipNft(
- api: ApiPromise,
- issuerUri: string,
- item: NftIdTuple,
- equipper: NftIdTuple,
- resource: number,
- base: number,
- slot: number,
-) {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const issuer = privateKey(issuerUri, Number(ss58Format));
- const tx = api.tx.rmrkEquip.equip(item, equipper, resource, base, slot);
- const events = await executeTransaction(api, issuer, tx);
- const equipResult = extractRmrkEquipTxResult(events, 'SlotEquipped', (data) => {
- return {
- item_collection: parseInt(data[0].toString(), 10),
- item_nft: parseInt(data[1].toString(), 10),
- base_id: parseInt(data[2].toString(), 10),
- slot_id: parseInt(data[3].toString(), 10),
- };
- });
- expect(equipResult.success, 'Error: Unable to equip an item').to.be.true;
- expect(equipResult.successData!.item_collection, 'Error: Invalid item collection id')
- .to.be.eq(item[0]);
- expect(equipResult.successData!.item_nft, 'Error: Invalid item NFT id')
- .to.be.eq(item[1]);
- expect(equipResult.successData!.base_id, 'Error: Invalid base id')
- .to.be.eq(base);
- expect(equipResult.successData!.slot_id, 'Error: Invalid slot id')
- .to.be.eq(slot);
-}
-
-export async function unequipNft(
- api: ApiPromise,
- issuerUri: string,
- item: any,
- equipper: any,
- resource: number,
- base: number,
- slot: number,
-) {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const issuer = privateKey(issuerUri, Number(ss58Format));
- const tx = api.tx.rmrkEquip.equip(item, equipper, resource, base, slot);
- const events = await executeTransaction(api, issuer, tx);
-
- const unEquipResult = extractRmrkEquipTxResult(
- events,
- 'SlotUnequipped',
- (data) => {
- return {
- item_collection: parseInt(data[0].toString(), 10),
- item_nft: parseInt(data[1].toString(), 10),
- base_id: parseInt(data[2].toString(), 10),
- slot_id: parseInt(data[3].toString(), 10),
- };
- },
- );
-
- expect(unEquipResult.success, 'Error: Unable to unequip an item').to.be.true;
- expect(unEquipResult.successData!.item_collection, 'Error: Invalid item collection id')
- .to.be.eq(item[0]);
- expect(unEquipResult.successData!.item_nft, 'Error: Invalid item NFT id')
- .to.be.eq(item[1]);
- expect(unEquipResult.successData!.base_id, 'Error: Invalid base id')
- .to.be.eq(base);
- expect(unEquipResult.successData!.slot_id, 'Error: Invalid slot id')
- .to.be.eq(slot);
-}
-
-export async function removeNftResource(
- api: ApiPromise,
- expectedStatus: 'pending' | 'removed',
- issuerUri: string,
- collectionId: number,
- nftId: number,
- resourceId: number,
-) {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const issuer = privateKey(issuerUri, Number(ss58Format));
-
- const tx = api.tx.rmrkCore.removeResource(collectionId, nftId, resourceId);
- const events = await executeTransaction(api, issuer, tx);
- const removeResult = extractRmrkCoreTxResult(events, 'ResourceRemoval', (data) => {
- return {
- nftId: parseInt(data[0].toString(), 10),
- resourceId: parseInt(data[1].toString(), 10),
- };
- });
- expect(removeResult.success, 'Error: Unable to remove a resource').to.be.true;
- expect(removeResult.successData!.nftId, 'Error: Invalid NFT Id while removing a resource')
- .to.be.eq(nftId);
- expect(removeResult.successData!.resourceId, 'Error: Invalid resource Id while removing a resource')
- .to.be.eq(resourceId);
-
- const afterDeleting = await findResourceById(api, collectionId, nftId, resourceId);
-
- if (expectedStatus === 'pending') {
- expect(afterDeleting).not.to.be.null;
- expect(afterDeleting?.pendingRemoval.isTrue).to.be.equal(true);
- } else {
- expect(afterDeleting).to.be.null;
- }
-}
-
-export async function acceptResourceRemoval(
- api: ApiPromise,
- issuerUri: string,
- collectionId: number,
- nftId: number,
- resourceId: number,
-) {
- const ss58Format = api.registry.getChainProperties()!.toJSON().ss58Format;
- const issuer = privateKey(issuerUri, Number(ss58Format));
-
- const tx = api.tx.rmrkCore.acceptResourceRemoval(collectionId, nftId, resourceId);
- const events = await executeTransaction(api, issuer, tx);
- const acceptResult = extractRmrkCoreTxResult(events, 'ResourceRemovalAccepted', (data) => {
- return {
- nftId: parseInt(data[0].toString(), 10),
- resourceId: parseInt(data[1].toString(), 10),
- };
- });
- expect(acceptResult.success, 'Error: Unable to accept a resource').to.be.true;
- expect(acceptResult.successData!.nftId, 'Error: Invalid NFT Id while accepting a resource')
- .to.be.eq(nftId);
- expect(acceptResult.successData!.resourceId, 'Error: Invalid resource Id while accepting a resource')
- .to.be.eq(resourceId);
-
- const afterDeleting = await findResourceById(api, collectionId, nftId, resourceId);
- expect(afterDeleting, 'Error: resource deleting failed').to.be.null;
-}
tests/src/.outdated/substrate/substrate-api.tsdiffbeforeafterboth--- a/tests/src/.outdated/substrate/substrate-api.ts
+++ b/tests/src/.outdated/substrate/substrate-api.ts
@@ -53,7 +53,6 @@
rpc: {
unique: defs.unique.rpc,
appPromotion: defs.appPromotion.rpc,
- rmrk: defs.rmrk.rpc,
eth: {
feeHistory: {
description: 'Dummy',
tests/src/interfaces/definitions.tsdiffbeforeafterboth--- a/tests/src/interfaces/definitions.ts
+++ b/tests/src/interfaces/definitions.ts
@@ -16,6 +16,5 @@
export {default as unique} from './unique/definitions';
export {default as appPromotion} from './appPromotion/definitions';
-export {default as rmrk} from './rmrk/definitions';
export {default as povinfo} from './povinfo/definitions';
export {default as default} from './default/definitions';
tests/src/interfaces/rmrk/definitions.tsdiffbeforeafterboth--- a/tests/src/interfaces/rmrk/definitions.ts
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright 2019-2022 Unique Network (Gibraltar) Ltd.
-// This file is part of Unique Network.
-
-// Unique Network is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// Unique Network is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
-
-type RpcParam = {
- name: string;
- type: string;
- isOptional?: true;
-};
-
-const atParam = {name: 'at', type: 'Hash', isOptional: true};
-const fn = (description: string, params: RpcParam[], type: string) => ({
- description,
- params: [...params, atParam],
- type,
-});
-
-export default {
- types: {},
- rpc: {
- lastCollectionIdx: fn('Get the latest created collection id', [], 'u32'),
- collectionById: fn('Get collection by id', [{name: 'id', type: 'u32'}], 'Option<RmrkTraitsCollectionCollectionInfo>'),
- nftById: fn(
- 'Get NFT by collection id and NFT id',
- [
- {name: 'collectionId', type: 'u32'},
- {name: 'nftId', type: 'u32'},
- ],
- 'Option<RmrkTraitsNftNftInfo>',
- ),
- accountTokens: fn(
- 'Get tokens owned by an account in a collection',
- [
- {name: 'accountId', type: 'AccountId32'},
- {name: 'collectionId', type: 'u32'},
- ],
- 'Vec<u32>',
- ),
- nftChildren: fn(
- 'Get NFT children',
- [
- {name: 'collectionId', type: 'u32'},
- {name: 'nftId', type: 'u32'},
- ],
- 'Vec<RmrkTraitsNftNftChild>',
- ),
- collectionProperties: fn(
- 'Get collection properties',
- [
- {name: 'collectionId', type: 'u32'},
- {name: 'filterKeys', type: 'Vec<String>', isOptional: true},
- ],
- 'Vec<RmrkTraitsPropertyPropertyInfo>',
- ),
- nftProperties: fn(
- 'Get NFT properties',
- [
- {name: 'collectionId', type: 'u32'},
- {name: 'nftId', type: 'u32'},
- {name: 'filterKeys', type: 'Vec<String>', isOptional: true},
- ],
- 'Vec<RmrkTraitsPropertyPropertyInfo>',
- ),
- nftResources: fn(
- 'Get NFT resources',
- [
- {name: 'collectionId', type: 'u32'},
- {name: 'nftId', type: 'u32'},
- ],
- 'Vec<RmrkTraitsResourceResourceInfo>',
- ),
- nftResourcePriority: fn(
- 'Get NFT resource priorities',
- [
- {name: 'collectionId', type: 'u32'},
- {name: 'nftId', type: 'u32'},
- {name: 'resourceId', type: 'u32'},
- ],
- 'Option<u32>',
- ),
- base: fn(
- 'Get base info',
- [{name: 'baseId', type: 'u32'}],
- 'Option<RmrkTraitsBaseBaseInfo>',
- ),
- baseParts: fn(
- 'Get all Base\'s parts',
- [{name: 'baseId', type: 'u32'}],
- 'Vec<RmrkTraitsPartPartType>',
- ),
- themeNames: fn(
- 'Get Base\'s theme names',
- [{name: 'baseId', type: 'u32'}],
- 'Vec<Bytes>',
- ),
- themes: fn(
- 'Get Theme\'s keys values',
- [
- {name: 'baseId', type: 'u32'},
- {name: 'themeName', type: 'String'},
- {name: 'keys', type: 'Option<Vec<String>>'},
- ],
- 'Option<RmrkTraitsTheme>',
- ),
- },
-};
tests/src/interfaces/rmrk/index.tsdiffbeforeafterboth--- a/tests/src/interfaces/rmrk/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-// Auto-generated via `yarn polkadot-types-from-defs`, do not edit
-/* eslint-disable */
-
-export * from './types';
tests/src/interfaces/rmrk/types.tsdiffbeforeafterboth--- a/tests/src/interfaces/rmrk/types.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-// Auto-generated via `yarn polkadot-types-from-defs`, do not edit
-/* eslint-disable */
-
-export type PHANTOM_RMRK = 'rmrk';
tests/src/pallet-presence.test.tsdiffbeforeafterboth--- a/tests/src/pallet-presence.test.ts
+++ b/tests/src/pallet-presence.test.ts
@@ -64,7 +64,6 @@
const refungible = 'refungible';
const foreignAssets = 'foreignassets';
- const _rmrkPallets = ['rmrkcore', 'rmrkequip'];
const appPromotion = 'apppromotion';
const collatorSelection = ['authorship', 'session', 'collatorselection', 'identity'];
const testUtils = 'testutils';
tests/src/util/index.tsdiffbeforeafterboth--- a/tests/src/util/index.ts
+++ b/tests/src/util/index.ts
@@ -106,8 +106,6 @@
export enum Pallets {
Inflation = 'inflation',
- RmrkCore = 'rmrkcore',
- RmrkEquip = 'rmrkequip',
ReFungible = 'refungible',
Fungible = 'fungible',
NFT = 'nonfungible',
tests/src/util/playgrounds/unique.dev.tsdiffbeforeafterboth--- a/tests/src/util/playgrounds/unique.dev.ts
+++ b/tests/src/util/playgrounds/unique.dev.ts
@@ -106,7 +106,6 @@
unique: defs.unique.rpc,
appPromotion: defs.appPromotion.rpc,
povinfo: defs.povinfo.rpc,
- rmrk: defs.rmrk.rpc,
eth: {
feeHistory: {
description: 'Dummy',