From b2e36ee9b1717966194c212b60e350eb45e5d0f4 Mon Sep 17 00:00:00 2001 From: Erick Casanova Date: Thu, 3 Nov 2022 19:04:29 -0600 Subject: [PATCH 1/4] update metadata for NFTs and collections to not be optionals, also update change the pallet name from gated-marketplace to afloat --- Cargo.lock | 46 ++++----- Cargo.toml | 2 +- .../{gated-marketplace => afloat}/Cargo.toml | 4 +- .../{gated-marketplace => afloat}/README.md | 0 .../src/functions.rs | 93 ++++++++++++------- .../{gated-marketplace => afloat}/src/lib.rs | 18 ++++ .../{gated-marketplace => afloat}/src/mock.rs | 2 + .../src/tests.rs | 0 .../src/types.rs | 0 pallets/fruniques/src/functions.rs | 48 +++++----- pallets/fruniques/src/lib.rs | 13 ++- pallets/fruniques/src/mock.rs | 3 + pallets/fruniques/src/types.rs | 2 +- parachain-runtime/Cargo.toml | 8 +- parachain-runtime/src/lib.rs | 8 +- runtime/Cargo.toml | 4 +- runtime/src/lib.rs | 8 +- 17 files changed, 156 insertions(+), 103 deletions(-) rename pallets/{gated-marketplace => afloat}/Cargo.toml (97%) rename pallets/{gated-marketplace => afloat}/README.md (100%) rename pallets/{gated-marketplace => afloat}/src/functions.rs (95%) rename pallets/{gated-marketplace => afloat}/src/lib.rs (96%) rename pallets/{gated-marketplace => afloat}/src/mock.rs (98%) rename pallets/{gated-marketplace => afloat}/src/tests.rs (100%) rename pallets/{gated-marketplace => afloat}/src/types.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index bd22f41e..95f8d63f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3006,6 +3006,7 @@ dependencies = [ "frame-try-runtime", "hex-literal", "log", + "pallet-afloat", "pallet-alliance", "pallet-asset-tx-payment", "pallet-assets", @@ -3023,7 +3024,6 @@ dependencies = [ "pallet-democracy", "pallet-elections-phragmen", "pallet-fruniques", - "pallet-gated-marketplace", "pallet-gilt", "pallet-identity", "pallet-im-online", @@ -3090,6 +3090,7 @@ dependencies = [ "frame-system-rpc-runtime-api", "hex-literal", "log", + "pallet-afloat", "pallet-assets", "pallet-aura", "pallet-balances", @@ -3098,7 +3099,6 @@ dependencies = [ "pallet-collective", "pallet-confidential-docs", "pallet-fruniques", - "pallet-gated-marketplace", "pallet-grandpa", "pallet-identity", "pallet-indices", @@ -5111,6 +5111,27 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "pallet-afloat" +version = "4.0.0-dev" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "pallet-balances", + "pallet-fruniques", + "pallet-rbac", + "pallet-timestamp", + "pallet-uniques", + "parity-scale-codec", + "scale-info", + "serde", + "sp-core", + "sp-io", + "sp-runtime", +] + [[package]] name = "pallet-alliance" version = "4.0.0-dev" @@ -5532,27 +5553,6 @@ dependencies = [ "sp-runtime", ] -[[package]] -name = "pallet-gated-marketplace" -version = "4.0.0-dev" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "log", - "pallet-balances", - "pallet-fruniques", - "pallet-rbac", - "pallet-timestamp", - "pallet-uniques", - "parity-scale-codec", - "scale-info", - "serde", - "sp-core", - "sp-io", - "sp-runtime", -] - [[package]] name = "pallet-gilt" version = "4.0.0-dev" diff --git a/Cargo.toml b/Cargo.toml index 4d0da7a0..15d0320b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ members = [ 'pallets/confidential-docs', 'pallets/rbac', 'pallets/fruniques', - 'pallets/gated-marketplace', + 'pallets/afloat', 'parachain-runtime', 'runtime', ] diff --git a/pallets/gated-marketplace/Cargo.toml b/pallets/afloat/Cargo.toml similarity index 97% rename from pallets/gated-marketplace/Cargo.toml rename to pallets/afloat/Cargo.toml index 683a70b3..abb19346 100644 --- a/pallets/gated-marketplace/Cargo.toml +++ b/pallets/afloat/Cargo.toml @@ -1,7 +1,7 @@ [package] -name = "pallet-gated-marketplace" +name = "pallet-afloat" version = "4.0.0-dev" -description = "" +description = "Pallet to create marketplaces" authors = ["Hashed Pallet { let _appraiser_role_id = T::Rbac::create_and_set_roles(pallet_id.clone(), [MarketplaceRole::Appraiser.to_vec()].to_vec())?; // redemption specialist role and permissions let _redemption_role_id = T::Rbac::create_and_set_roles(pallet_id, [MarketplaceRole::RedemptionSpecialist.to_vec()].to_vec())?; - + Self::deposit_event(Event::MarketplaceSetupCompleted); Ok(()) } @@ -70,9 +70,32 @@ impl Pallet { Ok(()) } + pub fn do_invite(authority: T::AccountId, marketplace_id: [u8;32], new_user: T::AccountId, fields : Fields, custodian_fields: Option>) -> DispatchResult { + ensure!(>::contains_key(marketplace_id), Error::::MarketplaceNotFound); + // The user only can apply once by marketplace + ensure!(!>::contains_key(new_user.clone(), marketplace_id), Error::::AlreadyApplied); + + // ensure the origin is owner or admin + Self::is_authorized(authority.clone(), &marketplace_id, Permission::Enroll)?; + + let (custodian, fields) = + Self::set_up_application(fields,custodian_fields); + + let application = Application::{ + status: ApplicationStatus::default(), + fields, + feedback: BoundedVec::::default(), + }; + + Self::do_apply(new_user.clone(), custodian, marketplace_id, application)?; + + Self::do_enroll(authority, marketplace_id, AccountOrApplication::Account(new_user), true, BoundedVec::::try_from(b"User enrolled by the marketplace admin".to_vec()).unwrap())?; + + Ok(()) + } + pub fn do_enroll(authority: T::AccountId, marketplace_id: [u8;32], account_or_application: AccountOrApplication, approved: bool, feedback: BoundedVec,)->DispatchResult{ // ensure the origin is owner or admin - //Self::can_enroll(authority, marketplace_id)?; Self::is_authorized(authority, &marketplace_id,Permission::Enroll)?; let next_status = match approved{ true => ApplicationStatus::Approved, @@ -139,7 +162,7 @@ impl Pallet { // Admis cannot be deleted between them, only the owner can ensure!(!Self::is_admin(authority, marketplace_id), Error::::CannotDeleteAdmin); - + Self::remove_from_market_lists(account.clone(), authority_type, marketplace_id)?; }, _ =>{ @@ -148,7 +171,7 @@ impl Pallet { } } - + Self::deposit_event(Event::AuthorityRemoved(account, authority_type)); Ok(()) } @@ -200,7 +223,7 @@ impl Pallet { //create an offer_id let offer_id = (marketplace_id, authority.clone(), collection_id, timestamp, timestamp2).using_encoded(blake2_256); - //create offer structure + //create offer structure let offer_data = OfferData:: { marketplace_id, collection_id, @@ -216,7 +239,7 @@ impl Pallet { //ensure there is no a previous sell offer for this item Self::can_this_item_receive_sell_orders(collection_id, item_id, marketplace_id)?; - + //insert in OffersByItem >::try_mutate(collection_id, item_id, |offers| { offers.try_push(offer_id) @@ -305,7 +328,7 @@ impl Pallet { >::try_mutate(marketplace_id, |offers| { offers.try_push(offer_id) }).map_err(|_| Error::::OfferStorageError)?; - + Self::deposit_event(Event::OfferStored(collection_id, item_id)); Ok(()) } @@ -321,14 +344,14 @@ impl Pallet { let owner_item = pallet_uniques::Pallet::::owner(offer_data.collection_id, offer_data.item_id).ok_or(Error::::OwnerNotFound)?; //ensure owner is not the same as the buyer - ensure!(owner_item != buyer, Error::::CannotTakeOffer); + ensure!(owner_item != buyer, Error::::CannotTakeOffer); //ensure the offer_id exists in OffersByItem Self::does_exist_offer_id_for_this_item(offer_data.collection_id, offer_data.item_id, offer_id)?; //ensure the offer is open and available ensure!(offer_data.status == OfferStatus::Open, Error::::OfferIsNotAvailable); - + //TODO: Use free_balance instead of total_balance //Get the buyer's balance let total_amount_buyer = T::Currency::total_balance(&buyer); @@ -347,7 +370,7 @@ impl Pallet { //remove all the offers associated with the item Self::delete_all_offers_for_this_item(offer_data.collection_id, offer_data.item_id)?; - + Self::deposit_event(Event::OfferWasAccepted(offer_id, buyer)); Ok(()) } @@ -400,7 +423,7 @@ impl Pallet { pub fn do_remove_offer(authority: T::AccountId, offer_id: [u8;32]) -> DispatchResult { //ensure the offer_id exists ensure!(>::contains_key(offer_id), Error::::OfferNotFound); - + //get offer data let offer_data = >::get(offer_id).ok_or(Error::::OfferNotFound)?; Self::is_authorized(authority.clone(), &offer_data.marketplace_id,Permission::RemoveOffer)?; @@ -437,19 +460,19 @@ impl Pallet { offers.remove(offer_index); Ok(()) }).map_err(|_:Error::| Error::::OfferNotFound)?; - + Self::deposit_event(Event::OfferRemoved(offer_id, offer_data.marketplace_id)); - + Ok(()) } - + /*---- Helper functions ----*/ pub fn set_up_application( fields : Fields, - custodian_fields: Option> + custodian_fields: Option> )-> (Option, BoundedVec ){ let mut f: Vec= fields.iter().map(|tuple|{ ApplicationField{ @@ -473,7 +496,7 @@ impl Pallet { T::Rbac::assign_role_to_user(authority, Self::pallet_id(), &marketplace_id, role.id())?; - + Ok(()) } @@ -506,7 +529,7 @@ impl Pallet { fn remove_from_market_lists(account: T::AccountId, author_type: MarketplaceRole , marketplace_id : [u8;32])->DispatchResult{ - T::Rbac::remove_role_from_user(account, Self::pallet_id(), + T::Rbac::remove_role_from_user(account, Self::pallet_id(), &marketplace_id, author_type.id())?; Ok(()) @@ -546,7 +569,7 @@ impl Pallet { fn is_authorized( authority: T::AccountId, marketplace_id: &[u8;32], permission: Permission ) -> DispatchResult{ T::Rbac::is_authorized( authority, - Self::pallet_id(), + Self::pallet_id(), marketplace_id, &permission.id(), ) @@ -556,12 +579,12 @@ impl Pallet { ///Lets us know if the selected user is an admin. /// It returns true if the user is an admin, false otherwise. fn is_admin(account: T::AccountId, marketplace_id: [u8;32]) -> bool{ - T::Rbac::has_role(account, Self::pallet_id(), + T::Rbac::has_role(account, Self::pallet_id(), &marketplace_id, [MarketplaceRole::Admin.id()].to_vec()).is_ok() } - /// Let us know if the selected account has the selected authority type. + /// Let us know if the selected account has the selected authority type. /// It returns true if the account has the authority type, false otherwise // fn does_exist_authority(account: T::AccountId, marketplace_id: [u8;32], authority_type: MarketplaceRole) -> bool{ // let roles = match >::try_get(account, marketplace_id){ @@ -572,22 +595,22 @@ impl Pallet { // roles.iter().any(|authority| authority == &authority_type) // } - /// Let us know if there's an owner for the selected marketplace. + /// Let us know if there's an owner for the selected marketplace. /// It returns true if there's an owner, false otherwise fn owner_exist(marketplace_id: [u8;32]) -> bool { // let owners = match >::try_get( marketplace_id, MarketplaceAuthority::Owner){ // Ok(owners) => owners, // Err(_) => return false, // }; - - //owners.len() == 1 - T::Rbac::get_role_users_len(Self::pallet_id(), + + //owners.len() == 1 + T::Rbac::get_role_users_len(Self::pallet_id(), &marketplace_id, &MarketplaceRole::Owner.id()) == 1 } /// Let us update the marketplace's label. /// It returns ok if the update was successful, error otherwise. - fn update_label(marketplace_id : [u8;32], new_label: BoundedVec) -> DispatchResult { + fn update_label(marketplace_id : [u8;32], new_label: BoundedVec) -> DispatchResult { >::try_mutate(marketplace_id, |marketplace|{ let market = marketplace.as_mut().ok_or(Error::::MarketplaceNotFound)?; market.label = new_label; @@ -595,18 +618,18 @@ impl Pallet { }) } - /// Let us delete the selected marketplace + /// Let us delete the selected marketplace /// and remove all of its associated authorities from all the storage sources. /// If returns ok if the deletion was successful, error otherwise. /// Errors only could happen if the storage sources are corrupted. fn remove_selected_marketplace(marketplace_id: [u8;32]) -> DispatchResult { //TODO: evaluate use iter_key_prefix ->instead iter() - //Before to remove the marketplace, we need to remove all its associated authorities + //Before to remove the marketplace, we need to remove all its associated authorities // as well as the applicants/applications. //First we need to get the list of all the authorities for the marketplace. let mut applications = Vec::new(); - + // remove from Applications lists for ele in >::iter() { if ele.1 == marketplace_id { @@ -621,7 +644,7 @@ impl Pallet { // remove from ApplicationsByAccount list >::iter().for_each(|(_k1, _k2, _k3)|{ >::remove(_k1, marketplace_id); - }); + }); // remove from ApplicantsByMarketplace list let _ = >::clear_prefix(marketplace_id,1000, None); @@ -642,17 +665,17 @@ impl Pallet { /// Let us check the curent status of the selected application. /// If the status is rejected, we can safely remove its data from the storage sources - /// so the user can apply again. + /// so the user can apply again. /// It doesn't affect any other storage source/workflow. pub fn is_application_in_rejected_status(account: T::AccountId, marketplace_id: [u8;32]) -> DispatchResult{ let application_id = >::try_get(account.clone(), marketplace_id) .map_err(|_| Error::::ApplicationIdNotFound)?; - + let application = >::try_get(application_id) .map_err(|_| Error::::ApplicationNotFound)?; match application.status { - ApplicationStatus::Pending => return Err(Error::::ApplicationStatusStillPending.into()), + ApplicationStatus::Pending => return Err(Error::::ApplicationStatusStillPending.into()), ApplicationStatus::Approved => return Err(Error::::ApplicationHasAlreadyBeenApproved.into()), ApplicationStatus::Rejected => { //If status is Rejected, we need to delete the previous application from all the storage sources. @@ -695,7 +718,7 @@ impl Pallet { fn update_offers_status(buyer: T::AccountId, collection_id: T::CollectionId, item_id: T::ItemId, marketplace_id: [u8;32]) -> DispatchResult{ let offer_ids = >::try_get(collection_id, item_id).map_err(|_| Error::::OfferNotFound)?; - + for offer_id in offer_ids { >::try_mutate::<_,_,DispatchError,_>(offer_id, |offer|{ let offer = offer.as_mut().ok_or(Error::::OfferNotFound)?; @@ -742,7 +765,7 @@ impl Pallet { let offer_info = >::get(offer).ok_or(Error::::OfferNotFound)?; //ensure the offer_type is SellOrder, because this vector also contains buy offers. if offer_info.marketplace_id == marketplace_id && offer_info.offer_type == OfferType::SellOrder { - return Ok(()) + return Ok(()) } } @@ -786,4 +809,4 @@ impl Pallet { ) } -} \ No newline at end of file +} diff --git a/pallets/gated-marketplace/src/lib.rs b/pallets/afloat/src/lib.rs similarity index 96% rename from pallets/gated-marketplace/src/lib.rs rename to pallets/afloat/src/lib.rs index f74b2f5a..725ca5de 100644 --- a/pallets/gated-marketplace/src/lib.rs +++ b/pallets/afloat/src/lib.rs @@ -422,6 +422,24 @@ pub mod pallet { Self::do_enroll(who, marketplace_id, account_or_application, approved, feedback) } + /// Invite a user to a marketplace. + /// + /// The admin of the marketplace can invite a user to the marketplace. + /// ### Parameters: + /// - `origin`: The admin of the marketplace. + /// - `marketplace_id`: The id of the marketplace where we want to invite a user. + /// - `account`: The account to be invited. + /// + /// ### Considerations: + /// - You can only invite users to a marketplace where you are the admin. + #[transactional] + #[pallet::weight(10_000 + T::DbWeight::get().writes(1))] + pub fn invite(origin: OriginFor, marketplace_id: [u8;32], account: T::AccountId, fields : Fields, custodian_fields: Option>) -> DispatchResult { + let who = ensure_signed(origin)?; + + Self::do_invite(who, marketplace_id, account, fields, custodian_fields) + } + /// Add an Authority type /// /// This extrinsic adds an authority type for the selected account diff --git a/pallets/gated-marketplace/src/mock.rs b/pallets/afloat/src/mock.rs similarity index 98% rename from pallets/gated-marketplace/src/mock.rs rename to pallets/afloat/src/mock.rs index f22786e9..f93abb24 100644 --- a/pallets/gated-marketplace/src/mock.rs +++ b/pallets/afloat/src/mock.rs @@ -94,12 +94,14 @@ impl pallet_gated_marketplace::Config for Test { } parameter_types! { pub const ChildMaxLen: u32 = 10; + pub const LimitBoundedVec: u8 = 1; } impl pallet_fruniques::Config for Test { type Event = Event; type RemoveOrigin = EnsureRoot; type ChildMaxLen = ChildMaxLen; + type LimitBoundedVec = LimitBoundedVec; } parameter_types! { diff --git a/pallets/gated-marketplace/src/tests.rs b/pallets/afloat/src/tests.rs similarity index 100% rename from pallets/gated-marketplace/src/tests.rs rename to pallets/afloat/src/tests.rs diff --git a/pallets/gated-marketplace/src/types.rs b/pallets/afloat/src/types.rs similarity index 100% rename from pallets/gated-marketplace/src/types.rs rename to pallets/afloat/src/types.rs diff --git a/pallets/fruniques/src/functions.rs b/pallets/fruniques/src/functions.rs index 40a0040d..eb1eddd1 100644 --- a/pallets/fruniques/src/functions.rs +++ b/pallets/fruniques/src/functions.rs @@ -1,7 +1,7 @@ use super::*; -use frame_system::pallet_prelude::*; use crate::types::*; +use frame_system::pallet_prelude::*; use frame_support::traits::tokens::nonfungibles::Inspect; use scale_info::prelude::string::String; @@ -9,6 +9,7 @@ use scale_info::prelude::string::String; use pallet_rbac::types::*; use frame_support::pallet_prelude::*; +use frame_support::traits::EnsureOriginWithArg; use sp_runtime::{sp_std::vec::Vec, Permill}; impl Pallet { @@ -139,29 +140,26 @@ impl Pallet { Ok(()) } - /// Helper function to create a new collection /// Creates a collection and updates its metadata if needed. pub fn do_create_collection( origin: OriginFor, class_id: T::CollectionId, - metadata: Option>, - admin: ::Source, + metadata: CollectionDescription, + admin: T::AccountId, ) -> DispatchResult { - pallet_uniques::Pallet::::create( - origin.clone(), - class_id, - admin, + let owner = T::CreateOrigin::ensure_origin(origin.clone(), &class_id)?; + + pallet_uniques::Pallet::::do_create_collection( + class_id.clone(), + owner.clone(), + admin.clone(), + T::CollectionDeposit::get(), + false, + pallet_uniques::Event::Created { collection: class_id, creator: admin, owner }, )?; - if let Some(metadata) = metadata { - pallet_uniques::Pallet::::set_collection_metadata( - origin, - class_id, - metadata, - false - )?; - } + pallet_uniques::Pallet::::set_collection_metadata(origin, class_id, metadata, false)?; Ok(()) } @@ -200,15 +198,18 @@ impl Pallet { collection: T::CollectionId, item: T::ItemId, owner: ::Source, + metadata: CollectionDescription, attributes: Option, BoundedVec)>>, ) -> DispatchResult { + ensure!(Self::collection_exists(&collection), >::CollectionNotFound); + pallet_uniques::Pallet::::mint(origin.clone(), collection, item, owner)?; - ensure!(Self::collection_exists(&collection), >::CollectionNotFound); - pallet_uniques::Pallet::::mint( + pallet_uniques::Pallet::::set_metadata( origin.clone(), collection, item, - owner + metadata, + false, )?; if let Some(attributes) = attributes { @@ -226,10 +227,7 @@ impl Pallet { Ok(()) } - pub fn pallet_id()->IdOrVec{ - IdOrVec::Vec( - Self::module_name().as_bytes().to_vec() - ) - } - + pub fn pallet_id() -> IdOrVec { + IdOrVec::Vec(Self::module_name().as_bytes().to_vec()) + } } diff --git a/pallets/fruniques/src/lib.rs b/pallets/fruniques/src/lib.rs index 5943d87a..531497f6 100644 --- a/pallets/fruniques/src/lib.rs +++ b/pallets/fruniques/src/lib.rs @@ -31,6 +31,9 @@ pub mod pallet { /// Maximum number of children a Frunique can have #[pallet::constant] type ChildMaxLen: Get; + /// Solution to fix issue with an optional BoundedVec + #[pallet::constant] + type LimitBoundedVec: Get; } #[pallet::pallet] @@ -152,11 +155,11 @@ pub mod pallet { /// /// ## Parameters /// - `origin`: The origin of the transaction. - /// - `Metadata`: The title of the collection. + /// - `metadata`: The title of the collection. #[pallet::weight(10_000 + T::DbWeight::get().writes(1))] pub fn create_collection( origin: OriginFor, - metadata: Option>, + metadata: CollectionDescription, ) -> DispatchResult { let admin: T::AccountId = ensure_signed(origin.clone())?; @@ -166,7 +169,7 @@ pub mod pallet { origin, new_collection_id, metadata, - Self::account_id_to_lookup_source(&admin), + admin.clone(), )?; Self::deposit_event(Event::FruniqueCollectionCreated(admin, new_collection_id)); @@ -230,12 +233,14 @@ pub mod pallet { /// - `origin` must be signed by the owner of the frunique. /// - `class_id` must be a valid class of the asset class. /// - `parent_info` Optional value needed for the NFT division. + /// - `metadata` Title of the nft. /// - `attributes` An array of attributes (key, value) to be added to the NFT. #[pallet::weight(10_000 + T::DbWeight::get().writes(4))] pub fn spawn( origin: OriginFor, class_id: CollectionId, parent_info: Option, + metadata: CollectionDescription, attributes: Option, BoundedVec)>>, ) -> DispatchResult { ensure!(Self::collection_exists(&class_id), >::CollectionNotFound); @@ -264,7 +269,7 @@ pub mod pallet { >::insert(class_id, instance_id, Some(child_info)); } - Self::do_spawn(origin.clone(), class_id, instance_id, account_id, attributes)?; + Self::do_spawn(origin.clone(), class_id, instance_id, account_id, metadata, attributes)?; Self::deposit_event(Event::FruniqueCreated( owner.clone(), diff --git a/pallets/fruniques/src/mock.rs b/pallets/fruniques/src/mock.rs index 76cbfdb8..2b61d62b 100644 --- a/pallets/fruniques/src/mock.rs +++ b/pallets/fruniques/src/mock.rs @@ -27,7 +27,9 @@ construct_runtime!( parameter_types! { pub const BlockHashCount: u64 = 250; pub const ChildMaxLen: u32 = 10; + pub const LimitBoundedVec: u8 = 1; } + impl frame_system::Config for Test { type BaseCallFilter = frame_support::traits::Everything; type BlockWeights = (); @@ -59,6 +61,7 @@ impl pallet_fruniques::Config for Test { type Event = Event; type RemoveOrigin = EnsureRoot; type ChildMaxLen = ChildMaxLen; + type LimitBoundedVec = LimitBoundedVec; } parameter_types! { diff --git a/pallets/fruniques/src/types.rs b/pallets/fruniques/src/types.rs index 0c9d7754..d8ef186a 100644 --- a/pallets/fruniques/src/types.rs +++ b/pallets/fruniques/src/types.rs @@ -16,7 +16,7 @@ pub type StringLimit = BoundedVec::StringLi pub type CollectionId = u32; pub type ItemId = u32; -pub type CollectionDescription = BoundedVec::StringLimit>; +pub type CollectionDescription = StringLimit; // (ParentId, Hierarchical, Percentage) pub type HierarchicalInfo = (ItemId, bool, u8); diff --git a/parachain-runtime/Cargo.toml b/parachain-runtime/Cargo.toml index 72ce0fc6..68ddea47 100644 --- a/parachain-runtime/Cargo.toml +++ b/parachain-runtime/Cargo.toml @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"] substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } [dependencies] -# General +# General codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } hex-literal = { version = "0.3.4", optional = true } log = { version = "0.4", default-features = false } @@ -46,7 +46,7 @@ frame-try-runtime = { git = "https://github.com/paritytech/substrate", default-f # Local Pallets pallet-bitcoin-vaults = { path = "../pallets/bitcoin-vaults", default-features = false } pallet-fruniques = { path = "../pallets/fruniques", default-features = false } -pallet-gated-marketplace = { path = "../pallets/gated-marketplace", default-features = false } +pallet-afloat = { path = "../pallets/afloat", default-features = false } pallet-rbac = { path = "../pallets/rbac", default-features = false } pallet-confidential-docs = { path = "../pallets/confidential-docs", default-features = false } @@ -143,7 +143,7 @@ std = [ "pallet-bitcoin-vaults/std", "pallet-confidential-docs/std", "pallet-fruniques/std", - "pallet-gated-marketplace/std", + "pallet-afloat/std", "pallet-rbac/std", # Prebuilt Pallets @@ -188,7 +188,7 @@ std = [ "pallet-vesting/std", "pallet-whitelist/std", "pallet-xcm/std", - + "parachain-info/std", "polkadot-parachain/std", "polkadot-runtime-common/std", diff --git a/parachain-runtime/src/lib.rs b/parachain-runtime/src/lib.rs index b4113974..987400f4 100644 --- a/parachain-runtime/src/lib.rs +++ b/parachain-runtime/src/lib.rs @@ -478,7 +478,7 @@ impl InstanceFilter for ProxyType { ), ProxyType::Marketplaces => matches!( c, - Call::GatedMarketplace(..) + Call::Afloat(..) ), } } @@ -946,6 +946,7 @@ parameter_types! { pub const KeyLimit: u32 = 32; pub const ValueLimit: u32 = 256; pub const ChildMaxLen: u32 = 25; + pub const LimitBoundedVec: u8 = 1; } impl pallet_uniques::Config for Runtime { @@ -973,6 +974,7 @@ impl pallet_fruniques::Config for Runtime { type Event = Event; type RemoveOrigin = RootOrThreeFifthsOfCouncil; type ChildMaxLen = ChildMaxLen; + type LimitBoundedVec = LimitBoundedVec; } parameter_types! { @@ -989,7 +991,7 @@ parameter_types! { pub const MaxOffersPerMarket: u32 = 100; } -impl pallet_gated_marketplace::Config for Runtime { +impl pallet_afloat::Config for Runtime { type Event = Event; type MaxAuthsPerMarket = MaxAuthsPerMarket; type MaxRolesPerAuth = MaxRolesPerAuth; @@ -1088,7 +1090,7 @@ construct_runtime!( BitcoinVaults: pallet_bitcoin_vaults::{Pallet, Call, Storage, Event, ValidateUnsigned} = 151, Uniques: pallet_uniques::{Pallet, Call, Storage, Event} = 152, Fruniques: pallet_fruniques::{Pallet, Call, Storage, Event} = 153, - GatedMarketplace: pallet_gated_marketplace::{Pallet, Call, Storage, Event} = 154, + Afloat: pallet_afloat::{Pallet, Call, Storage, Event} = 154, RBAC: pallet_rbac::{Pallet, Call, Storage, Event} = 155, ConfidentialDocs: pallet_confidential_docs::{Pallet, Call, Storage, Event} = 156, } diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 56215643..bd896554 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -64,7 +64,7 @@ hex-literal = { version = "0.3.4", optional = true } pallet-template = { default-features = false, path = "../pallets/template" } pallet-fruniques = { version = "0.1.0-dev", default-features = false, path = "../pallets/fruniques" } pallet-bitcoin-vaults = { default-features = false, path = "../pallets/bitcoin-vaults" } -pallet-gated-marketplace = { default-features = false, path = "../pallets/gated-marketplace" } +pallet-afloat = { default-features = false, path = "../pallets/afloat" } pallet-rbac = { default-features = false, path = "../pallets/rbac" } pallet-confidential-docs = { default-features = false, path = "../pallets/confidential-docs" } pallet-proxy-financial = { default-features = false, path = "../pallets/proxy-financial" } @@ -104,7 +104,7 @@ std = [ "pallet-uniques/std", "pallet-node-authorization/std", "pallet-bitcoin-vaults/std", - "pallet-gated-marketplace/std", + "pallet-afloat/std", "pallet-rbac/std", "pallet-confidential-docs/std", "pallet-proxy-financial/std", diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 2611885d..f8da79ed 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -519,7 +519,8 @@ parameter_types! { pub const ItemDeposit: Balance = 1 * DOLLARS; pub const KeyLimit: u32 = 32; pub const ValueLimit: u32 = 256; - pub const ChildMaxLen: u32 = 25; + pub const ChildMaxLen: u32 = 100; + pub const LimitBoundedVec: u8 = 1; } impl pallet_uniques::Config for Runtime { @@ -551,6 +552,7 @@ impl pallet_fruniques::Config for Runtime { >; type ChildMaxLen = ChildMaxLen; + type LimitBoundedVec = LimitBoundedVec; } @@ -620,7 +622,7 @@ parameter_types! { pub const MaxMarketsPerItem: u32 = 10; pub const MaxOffersPerMarket: u32 = 100; } -impl pallet_gated_marketplace::Config for Runtime { +impl pallet_afloat::Config for Runtime { type Event = Event; type MaxAuthsPerMarket = MaxAuthsPerMarket; type MaxRolesPerAuth = MaxRolesPerAuth; @@ -797,7 +799,7 @@ construct_runtime!( Bounties: pallet_bounties, Uniques: pallet_uniques, Fruniques: pallet_fruniques, - GatedMarketplace: pallet_gated_marketplace, + Afloat: pallet_afloat, Assets: pallet_assets, BitcoinVaults: pallet_bitcoin_vaults, RBAC: pallet_rbac, From 6a3d5055d500a35089549773967a819132ce3a1b Mon Sep 17 00:00:00 2001 From: Erick Casanova Date: Fri, 4 Nov 2022 09:12:31 -0600 Subject: [PATCH 2/4] update tests for fruniques changes --- pallets/fruniques/src/tests.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/pallets/fruniques/src/tests.rs b/pallets/fruniques/src/tests.rs index 73067849..5fee4927 100644 --- a/pallets/fruniques/src/tests.rs +++ b/pallets/fruniques/src/tests.rs @@ -53,7 +53,7 @@ fn dummy_empty_attributes() -> Vec<(BoundedVec, BoundedVec::CollectionNotFound); + assert_noop!(Fruniques::spawn(Origin::signed(1), 0, None, dummy_description(), None), Error::::CollectionNotFound); // Create a collection - assert_ok!(Fruniques::create_collection(Origin::signed(1), Some(dummy_description()))); + assert_ok!(Fruniques::create_collection(Origin::signed(1), dummy_description())); // The first item can not be a child - assert_noop!(Fruniques::spawn(Origin::signed(1), 0, Some((0, false, 10)), None), Error::::ParentNotFound); + assert_noop!(Fruniques::spawn(Origin::signed(1), 0, Some((0, false, 10)), dummy_description(), None), Error::::ParentNotFound); // A NFT can be created with empty data - assert_ok!(Fruniques::spawn(Origin::signed(1), 0, None, None)); + assert_ok!(Fruniques::spawn(Origin::signed(1), 0, None, dummy_description(), None)); // A NFT can be created with attributes - assert_ok!(Fruniques::spawn(Origin::signed(1), 0, None, Some(dummy_attributes()))); + assert_ok!(Fruniques::spawn(Origin::signed(1), 0, None, dummy_description(), Some(dummy_attributes()))); // A NFT can be hierarchical - assert_ok!(Fruniques::spawn(Origin::signed(1), 0, Some((0, false, 10)), None)); + assert_ok!(Fruniques::spawn(Origin::signed(1), 0, Some((0, false, 10)), dummy_description(), None)); // The parent must exist - assert_noop!(Fruniques::spawn(Origin::signed(1), 0, Some((100, false, 10)), None), Error::::ParentNotFound); + assert_noop!(Fruniques::spawn(Origin::signed(1), 0, Some((100, false, 10)), dummy_description(), None), Error::::ParentNotFound); }) } @@ -86,14 +86,14 @@ fn spawn_extrinsic_works() { fn set_attributes_works() { ExtBuilder::default().build().execute_with(|| { // A collection must be created before spawning an NFT - assert_noop!(Fruniques::spawn(Origin::signed(1), 0, None, None), Error::::CollectionNotFound); + assert_noop!(Fruniques::spawn(Origin::signed(1), 0, None, dummy_description(), None), Error::::CollectionNotFound); // Create a collection - assert_ok!(Fruniques::create_collection(Origin::signed(1), Some(dummy_description()))); + assert_ok!(Fruniques::create_collection(Origin::signed(1), dummy_description())); // Attributes can be added only to existing NFTs assert_noop!(Fruniques::set_attributes(Origin::signed(1), 0, 0, dummy_attributes()), Error::::FruniqueNotFound); // A NFT can be created with empty data - assert_ok!(Fruniques::spawn(Origin::signed(1), 0, None, None)); + assert_ok!(Fruniques::spawn(Origin::signed(1), 0, None, dummy_description(), None)); // Attributes can not be empty assert_noop!(Fruniques::set_attributes(Origin::signed(1), 0, 0, dummy_empty_attributes()), Error::::AttributesEmpty); From 1441e9ea47303c9a816c1b94f6fd098764da006c Mon Sep 17 00:00:00 2001 From: Erick Casanova Date: Fri, 4 Nov 2022 10:34:51 -0600 Subject: [PATCH 3/4] changes to the clean to make it more redeable --- pallets/fruniques/src/functions.rs | 12 ++++++------ pallets/fruniques/src/lib.rs | 21 ++++++++++----------- pallets/fruniques/src/tests.rs | 1 - 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/pallets/fruniques/src/functions.rs b/pallets/fruniques/src/functions.rs index eb1eddd1..4e4c001b 100644 --- a/pallets/fruniques/src/functions.rs +++ b/pallets/fruniques/src/functions.rs @@ -54,7 +54,7 @@ impl Pallet { pub fn get_nft_attribute( class_id: &T::CollectionId, instance_id: &T::ItemId, - key: &Vec, + key: &[u8], ) -> AttributeValue { if let Some(a) = pallet_uniques::Pallet::::attribute(class_id, instance_id, key) { return BoundedVec::::try_from(a) @@ -151,7 +151,7 @@ impl Pallet { let owner = T::CreateOrigin::ensure_origin(origin.clone(), &class_id)?; pallet_uniques::Pallet::::do_create_collection( - class_id.clone(), + class_id, owner.clone(), admin.clone(), T::CollectionDeposit::get(), @@ -172,9 +172,9 @@ impl Pallet { numeric_value: Option, admin: ::Source, ) -> DispatchResult { - pallet_uniques::Pallet::::create(origin.clone(), class_id.clone(), admin.clone())?; + pallet_uniques::Pallet::::create(origin.clone(), class_id, admin.clone())?; - Self::mint(origin.clone(), &class_id, instance_id.clone(), admin.clone())?; + Self::mint(origin.clone(), &class_id, instance_id, admin)?; if let Some(n) = numeric_value { let num_value_key = BoundedVec::::try_from(r#"num_value"#.encode()) @@ -182,7 +182,7 @@ impl Pallet { let num_value = BoundedVec::::try_from(n.encode()) .expect("Error on encoding the numeric value to BoundedVec"); pallet_uniques::Pallet::::set_attribute( - origin.clone(), + origin, class_id, Some(instance_id), num_value_key, @@ -199,7 +199,7 @@ impl Pallet { item: T::ItemId, owner: ::Source, metadata: CollectionDescription, - attributes: Option, BoundedVec)>>, + attributes: Option>, ) -> DispatchResult { ensure!(Self::collection_exists(&collection), >::CollectionNotFound); pallet_uniques::Pallet::::mint(origin.clone(), collection, item, owner)?; diff --git a/pallets/fruniques/src/lib.rs b/pallets/fruniques/src/lib.rs index 531497f6..96991fbd 100644 --- a/pallets/fruniques/src/lib.rs +++ b/pallets/fruniques/src/lib.rs @@ -18,9 +18,8 @@ pub mod types; pub mod pallet { use super::*; use crate::types::*; - use frame_support::{pallet_prelude::*, transactional, BoundedVec}; + use frame_support::{pallet_prelude::*, transactional}; use frame_system::pallet_prelude::*; - use scale_info::prelude::vec::Vec; /// Configure the pallet by specifying the parameters and types on which it depends. #[pallet::config] pub trait Config: frame_system::Config + pallet_uniques::Config { @@ -163,7 +162,7 @@ pub mod pallet { ) -> DispatchResult { let admin: T::AccountId = ensure_signed(origin.clone())?; - let new_collection_id: u32 = Self::next_collection().try_into().unwrap(); + let new_collection_id: u32 = Self::next_collection(); Self::do_create_collection( origin, @@ -205,7 +204,7 @@ pub mod pallet { origin: OriginFor, class_id: T::CollectionId, instance_id: T::ItemId, - attributes: Vec<(BoundedVec, BoundedVec)>, + attributes: Attributes, ) -> DispatchResult { ensure!(Self::item_exists(&class_id, &instance_id), >::FruniqueNotFound); @@ -220,7 +219,7 @@ pub mod pallet { Self::set_attribute( origin.clone(), &class_id.clone(), - Self::u32_to_instance_id(instance_id.clone()), + Self::u32_to_instance_id(instance_id), attribute.0.clone(), attribute.1.clone(), )?; @@ -241,7 +240,7 @@ pub mod pallet { class_id: CollectionId, parent_info: Option, metadata: CollectionDescription, - attributes: Option, BoundedVec)>>, + attributes: Option>, ) -> DispatchResult { ensure!(Self::collection_exists(&class_id), >::CollectionNotFound); @@ -269,7 +268,7 @@ pub mod pallet { >::insert(class_id, instance_id, Some(child_info)); } - Self::do_spawn(origin.clone(), class_id, instance_id, account_id, metadata, attributes)?; + Self::do_spawn(origin, class_id, instance_id, account_id, metadata, attributes)?; Self::deposit_event(Event::FruniqueCreated( owner.clone(), @@ -296,7 +295,7 @@ pub mod pallet { class_id: T::CollectionId, instance_id: Option, ) -> DispatchResult { - T::RemoveOrigin::ensure_origin(origin.clone())?; + T::RemoveOrigin::ensure_origin(origin)?; if let Some(instance_id) = instance_id { ensure!(!Self::item_exists(&class_id, &instance_id), >::FruniqueAlreadyExists); @@ -325,7 +324,7 @@ pub mod pallet { witness: pallet_uniques::DestroyWitness, maybe_check_owner: Option, ) -> DispatchResult { - T::RemoveOrigin::ensure_origin(origin.clone())?; + T::RemoveOrigin::ensure_origin(origin)?; ensure!(Self::collection_exists(&class_id), >::CollectionNotFound); pallet_uniques::Pallet::::do_destroy_collection( @@ -350,8 +349,8 @@ pub mod pallet { #[pallet::weight(10_000 + T::DbWeight::get().writes(1))] pub fn kill_storage(origin: OriginFor) -> DispatchResult { T::RemoveOrigin::ensure_origin(origin.clone())?; - let _ = >::put(0); - let _ = >::put(0); + >::put(0); + >::put(0); let _ = >::clear(1000, None); let _ = >::clear(1000, None); let _ = >::clear(1000, None); diff --git a/pallets/fruniques/src/tests.rs b/pallets/fruniques/src/tests.rs index 5fee4927..a201bd1c 100644 --- a/pallets/fruniques/src/tests.rs +++ b/pallets/fruniques/src/tests.rs @@ -81,7 +81,6 @@ fn spawn_extrinsic_works() { }) } - #[test] fn set_attributes_works() { ExtBuilder::default().build().execute_with(|| { From 6580134c3fa6dd43b9245ffaec43b114317757e9 Mon Sep 17 00:00:00 2001 From: Erick Casanova Date: Fri, 4 Nov 2022 11:29:32 -0600 Subject: [PATCH 4/4] Release 123 --- runtime/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index f8da79ed..8bdf27f4 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -106,7 +106,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 100 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 122, + spec_version: 123, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1,