From 4186437dc1bcb83cf14bbe9926021545e284ef69 Mon Sep 17 00:00:00 2001 From: Daniel Shiposha Date: Wed, 25 May 2022 20:15:40 +0000 Subject: [PATCH] feat: add rmrk proxy create_base --- --- a/Cargo.lock +++ b/Cargo.lock @@ -5513,6 +5513,7 @@ "pallet-randomness-collective-flip", "pallet-refungible", "pallet-rmrk-core", + "pallet-rmrk-equip", "pallet-structure", "pallet-sudo", "pallet-template-transaction-payment", @@ -6533,6 +6534,25 @@ ] [[package]] +name = "pallet-rmrk-equip" +version = "0.1.0" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-common", + "pallet-evm", + "pallet-nonfungible", + "pallet-rmrk-core", + "parity-scale-codec 3.1.2", + "scale-info", + "sp-core", + "sp-runtime", + "sp-std", + "up-data-structs", +] + +[[package]] name = "pallet-scheduler" version = "4.0.0-dev" source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.21#563f4820d8f36d256ada7ea3fef46b2e94c4cd5a" --- a/pallets/proxy-rmrk-core/Cargo.toml +++ b/pallets/proxy-rmrk-core/Cargo.toml @@ -18,10 +18,7 @@ sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.21" } pallet-common = { default-features = false, path = '../common' } pallet-nonfungible = { default-features = false, path = "../../pallets/nonfungible" } -# pallet-structure = { default-features = false, path = '../structure' } up-data-structs = { default-features = false, path = '../../primitives/data-structs' } -# evm-coder = { default-features = false, path = '../../crates/evm-coder' } -# pallet-evm-coder-substrate = { default-features = false, path = '../evm-coder-substrate' } pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.21-logs" } frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.21" } scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } @@ -37,9 +34,6 @@ "pallet-common/std", "pallet-nonfungible/std", "pallet-evm/std", - # "pallet-structure/std", - # "evm-coder/std", - # "pallet-evm-coder-substrate/std", 'frame-benchmarking/std', ] runtime-benchmarks = [ --- a/pallets/proxy-rmrk-core/src/lib.rs +++ b/pallets/proxy-rmrk-core/src/lib.rs @@ -254,8 +254,8 @@ }); let nft_id = Self::create_nft( - sender, - cross_owner, + &sender, + &cross_owner, collection_id.into(), CollectionType::Regular, NftType::Regular, @@ -302,9 +302,9 @@ } impl Pallet { - fn create_nft( - sender: T::CrossAccountId, - owner: T::CrossAccountId, + pub fn create_nft( + sender: &T::CrossAccountId, + owner: &T::CrossAccountId, collection_id: CollectionId, collection_type: CollectionType, nft_type: NftType, @@ -320,14 +320,14 @@ .try_into() .map_err(|_| >::NftTypeEncodeError)?, properties: BoundedVec::default(), - owner, + owner: owner.clone(), }; let budget = budget::Value::new(2); >::create_item( &collection, - &sender, + sender, data, &budget, ).map_err(Self::map_common_err_to_proxy)?; --- a/pallets/proxy-rmrk-core/src/property.rs +++ b/pallets/proxy-rmrk-core/src/property.rs @@ -19,7 +19,7 @@ Thumb, EquippedNft, BaseType, - // // RmrkPartId(/* Id type? */) + ExternalPartId, EquippableList, ZIndex, ThemeName, @@ -62,8 +62,7 @@ Self::Thumb => key!("thumb"), Self::EquippedNft => key!("equipped-nft"), Self::BaseType => key!("base-type"), - // RmrkResourceId(/* Id type? */) - // RmrkPartId(/* Id type? */) + Self::ExternalPartId => key!("ext-part-id"), Self::EquippableList => key!("equippable-list"), Self::ZIndex => key!("z-index"), Self::ThemeName => key!("theme-name"), --- /dev/null +++ b/pallets/proxy-rmrk-equip/Cargo.toml @@ -0,0 +1,45 @@ +[package] +name = "pallet-rmrk-equip" +version = "0.1.0" +license = "GPLv3" +edition = "2021" + +[dependencies.codec] +default-features = false +features = ['derive'] +package = 'parity-scale-codec' +version = '3.1.2' + +[dependencies] +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.21" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.21" } +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.21" } +sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.21" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.21" } +pallet-common = { default-features = false, path = '../common' } +pallet-nonfungible = { default-features = false, path = "../../pallets/nonfungible" } +up-data-structs = { default-features = false, path = '../../primitives/data-structs' } +pallet-evm = { default-features = false, git = "https://github.com/uniquenetwork/frontier", branch = "unique-polkadot-v0.9.21-logs" } +frame-benchmarking = { default-features = false, optional = true, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.21" } +scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } +pallet-rmrk-core = { default-features = false, path = "../proxy-rmrk-core" } + +[features] +default = ["std"] +std = [ + "frame-support/std", + "frame-system/std", + "sp-runtime/std", + "sp-std/std", + "up-data-structs/std", + "pallet-common/std", + "pallet-nonfungible/std", + "pallet-rmrk-core/std", + "pallet-evm/std", + 'frame-benchmarking/std', +] +runtime-benchmarks = [ + 'frame-benchmarking', + 'frame-support/runtime-benchmarks', + 'frame-system/runtime-benchmarks', +] --- /dev/null +++ b/pallets/proxy-rmrk-equip/src/lib.rs @@ -0,0 +1,173 @@ +// 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 . + +#![cfg_attr(not(feature = "std"), no_std)] + +use frame_support::{pallet_prelude::*, transactional, 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, CollectionHandle}; +use pallet_rmrk_core::{Pallet as PalletCore, rmrk_property, misc::*}; +use pallet_nonfungible::{Pallet as PalletNft}; +use pallet_evm::account::CrossAccountId; + +pub use pallet::*; + +#[frame_support::pallet] +pub mod pallet { + use super::*; + + #[pallet::config] + pub trait Config: frame_system::Config + + pallet_rmrk_core::Config { + type Event: From> + IsType<::Event>; + } + + #[pallet::storage] + #[pallet::getter(fn internal_part_id)] + pub type InernalPartId = StorageDoubleMap< + _, + Twox64Concat, + CollectionId, + Twox64Concat, + RmrkPartId, + TokenId + >; + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + BaseCreated { + issuer: T::AccountId, + base_id: RmrkBaseId, + }, + } + + #[pallet::error] + pub enum Error { + NoAvailableBaseId, + } + + #[pallet::call] + impl Pallet { + #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))] + #[transactional] + pub fn create_base( + origin: OriginFor, + base_type: RmrkString, + symbol: RmrkString, + parts: BoundedVec, + ) -> 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(|_| >::CollectionTokenPrefixLimitExceeded)?, + ..Default::default() + }; + + let collection_id_res = >::init_collection(sender.clone(), data); + + if let Err(DispatchError::Arithmetic(_)) = &collection_id_res { + return Err(>::NoAvailableBaseId.into()); + } + + let collection_id = collection_id_res?; + + let collection = >::get_nft_collection(collection_id)?.into_inner(); + + >::set_scoped_collection_properties( + &collection, + PropertyScope::Rmrk, + [ + rmrk_property!(Config=T, CollectionType: CollectionType::Base)?, + rmrk_property!(Config=T, BaseType: base_type)?, + ].into_iter() + )?; + + for part in parts { + let part_id = part.id(); + let part_token_id = Self::create_part( + &cross_sender, + &collection, + part + )?; + + >::insert(collection_id, part_id, part_token_id); + + >::set_scoped_token_property( + &collection, + part_token_id, + PropertyScope::Rmrk, + rmrk_property!(Config=T, ExternalPartId: part_id)? + )?; + } + + Self::deposit_event(Event::BaseCreated { issuer: sender, base_id: collection_id.0 }); + + Ok(()) + } + } +} + +impl Pallet { + fn create_part( + sender: &T::CrossAccountId, + collection: &CollectionHandle, + part: RmrkPartType + ) -> Result { + let owner = sender; + + 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 = >::create_nft( + sender, + owner, + collection.id, + CollectionType::Base, + nft_type, + [ + rmrk_property!(Config=T, Src: src)?, + rmrk_property!(Config=T, ZIndex: z_index)? + ].into_iter() + )?; + + if let RmrkPartType::SlotPart(part) = part { + >::set_scoped_token_property( + collection, + token_id, + PropertyScope::Rmrk, + rmrk_property!(Config=T, EquippableList: part.equippable)? + )?; + } + + Ok(token_id) + } +} --- a/primitives/data-structs/src/rmrk.rs +++ b/primitives/data-structs/src/rmrk.rs @@ -416,6 +416,29 @@ SlotPart(SlotPart), } +impl PartType { + 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 + } + } +} + #[cfg_attr(feature = "std", derive(Eq, Serialize))] #[derive(Encode, Decode, Debug, TypeInfo, Clone, PartialEq)] #[cfg_attr( --- a/runtime/common/src/runtime_apis.rs +++ b/runtime/common/src/runtime_apis.rs @@ -347,27 +347,27 @@ fn base_parts(base_id: RmrkBaseId) -> Result, DispatchError> { use frame_support::BoundedVec; - use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, RmrkNft, RmrkDecode}}; + use pallet_proxy_rmrk_core::{RmrkProperty, misc::{CollectionType, NftType, RmrkNft, RmrkDecode}}; let collection_id = CollectionId(base_id); if RmrkCore::ensure_collection_type(collection_id, CollectionType::Base).is_err() { return Ok(Vec::new()); } - let parts = (dispatch_unique_runtime!(collection_id.collection_tokens()) as Result, DispatchError>)? - .iter() + let parts = (dispatch_unique_runtime!(collection_id.collection_tokens()))? + .into_iter() .filter_map(|token_id| { - let nft_type = RmrkCore::get_nft_type(collection_id, *token_id).unwrap(); + let nft_type = RmrkCore::get_nft_type(collection_id, token_id).ok()?; match nft_type { - FixedPart => Some(RmrkPartType::FixedPart(RmrkFixedPart { - id: token_id.0, - src: RmrkCore::get_nft_property(collection_id, *token_id, RmrkProperty::Src).unwrap().decode_or_default(), - z: RmrkCore::get_nft_property(collection_id, *token_id, RmrkProperty::ZIndex).unwrap().decode_or_default(), + NftType::FixedPart => Some(RmrkPartType::FixedPart(RmrkFixedPart { + id: RmrkCore::get_nft_property(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?.decode_or_default(), + src: RmrkCore::get_nft_property(collection_id, token_id, RmrkProperty::Src).ok()?.decode_or_default(), + z: RmrkCore::get_nft_property(collection_id, token_id, RmrkProperty::ZIndex).ok()?.decode_or_default(), })), - SlotPart => Some(RmrkPartType::SlotPart(RmrkSlotPart { - id: token_id.0, - src: RmrkCore::get_nft_property(collection_id, *token_id, RmrkProperty::Src).unwrap().decode_or_default(), - z: RmrkCore::get_nft_property(collection_id, *token_id, RmrkProperty::ZIndex).unwrap().decode_or_default(), - equippable: RmrkCore::get_nft_property(collection_id, *token_id, RmrkProperty::EquippableList).unwrap().decode_or_default(), + NftType::SlotPart => Some(RmrkPartType::SlotPart(RmrkSlotPart { + id: RmrkCore::get_nft_property(collection_id, token_id, RmrkProperty::ExternalPartId).ok()?.decode_or_default(), + src: RmrkCore::get_nft_property(collection_id, token_id, RmrkProperty::Src).ok()?.decode_or_default(), + z: RmrkCore::get_nft_property(collection_id, token_id, RmrkProperty::ZIndex).ok()?.decode_or_default(), + equippable: RmrkCore::get_nft_property(collection_id, token_id, RmrkProperty::EquippableList).ok()?.decode_or_default(), })), _ => None } --- a/runtime/opal/Cargo.toml +++ b/runtime/opal/Cargo.toml @@ -91,6 +91,7 @@ 'pallet-refungible/std', 'pallet-nonfungible/std', 'pallet-proxy-rmrk-core/std', + 'pallet-proxy-rmrk-equip/std', 'pallet-unique/std', 'pallet-unq-scheduler/std', 'pallet-charge-transaction/std', @@ -410,6 +411,7 @@ pallet-refungible = { default-features = false, path = "../../pallets/refungible" } 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" } pallet-unq-scheduler = { path = '../../pallets/scheduler', default-features = false } # pallet-contract-helpers = { path = '../pallets/contract-helpers', default-features = false, version = '0.1.0' } pallet-charge-transaction = { git = "https://github.com/uniquenetwork/pallet-sponsoring", branch = "polkadot-v0.9.21", package = "pallet-template-transaction-payment", default-features = false, version = "3.0.0" } --- a/runtime/opal/src/lib.rs +++ b/runtime/opal/src/lib.rs @@ -906,6 +906,10 @@ type Event = Event; } +impl pallet_proxy_rmrk_equip::Config for Runtime { + type Event = Event; +} + impl pallet_unique::Config for Runtime { type Event = Event; type WeightInfo = pallet_unique::weights::SubstrateWeight; @@ -1019,6 +1023,7 @@ Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69, Structure: pallet_structure::{Pallet, Call, Storage, Event} = 70, RmrkCore: pallet_proxy_rmrk_core::{Pallet, Call, Storage, Event} = 71, + RmrkEquip: pallet_proxy_rmrk_equip::{Pallet, Call, Storage, Event} = 72, // Frontier EVM: pallet_evm::{Pallet, Config, Call, Storage, Event} = 100, --- a/runtime/quartz/src/lib.rs +++ b/runtime/quartz/src/lib.rs @@ -880,6 +880,14 @@ type WeightInfo = pallet_nonfungible::weights::SubstrateWeight; } +impl pallet_proxy_rmrk_core::Config for Runtime { + type Event = Event; +} + +impl pallet_proxy_rmrk_equip::Config for Runtime { + type Event = Event; +} + impl pallet_unique::Config for Runtime { type Event = Event; type WeightInfo = pallet_unique::weights::SubstrateWeight; @@ -992,6 +1000,7 @@ Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69, Structure: pallet_structure::{Pallet, Call, Storage, Event} = 70, RmrkCore: pallet_proxy_rmrk_core::{Pallet, Call, Storage, Event} = 71, + RmrkEquip: pallet_proxy_rmrk_equip::{Pallet, Call, Storage, Event} = 72, // Frontier EVM: pallet_evm::{Pallet, Config, Call, Storage, Event} = 100, --- a/runtime/unique/src/lib.rs +++ b/runtime/unique/src/lib.rs @@ -884,6 +884,14 @@ type WeightInfo = pallet_nonfungible::weights::SubstrateWeight; } +impl pallet_proxy_rmrk_core::Config for Runtime { + type Event = Event; +} + +impl pallet_proxy_rmrk_equip::Config for Runtime { + type Event = Event; +} + impl pallet_unique::Config for Runtime { type Event = Event; type WeightInfo = pallet_unique::weights::SubstrateWeight; @@ -997,6 +1005,7 @@ Nonfungible: pallet_nonfungible::{Pallet, Storage} = 69, Structure: pallet_structure::{Pallet, Call, Storage, Event} = 70, RmrkCore: pallet_proxy_rmrk_core::{Pallet, Call, Storage, Event} = 71, + RmrkEquip: pallet_proxy_rmrk_equip::{Pallet, Call, Storage, Event} = 72, // Frontier EVM: pallet_evm::{Pallet, Config, Call, Storage, Event} = 100, -- gitstuff