From bc4154028a22be2d8cf9b5a4aab897a184ceb230 Mon Sep 17 00:00:00 2001 From: Bruno Galvao Date: Wed, 1 May 2024 22:12:14 +0900 Subject: [PATCH] test: create an NFT collection (#85) --- pop-api/examples/nfts/lib.rs | 62 ++++++++++++++++------ pop-api/src/v0/nfts.rs | 4 +- runtime/devnet/src/extensions.rs | 89 ++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 17 deletions(-) diff --git a/pop-api/examples/nfts/lib.rs b/pop-api/examples/nfts/lib.rs index 02fbf986..e9d97a99 100755 --- a/pop-api/examples/nfts/lib.rs +++ b/pop-api/examples/nfts/lib.rs @@ -1,46 +1,70 @@ #![cfg_attr(not(feature = "std"), no_std, no_main)] -use pop_api::nfts; +use pop_api::nfts::*; #[derive(Debug, Copy, Clone, PartialEq, Eq, scale::Encode, scale::Decode)] #[cfg_attr(feature = "std", derive(scale_info::TypeInfo))] pub enum ContractError { InvalidCollection, ItemAlreadyExists, - NftsError(nfts::Error), + NftsError(Error), NotOwner, } -impl From for ContractError { - fn from(value: nfts::Error) -> Self { +impl From for ContractError { + fn from(value: Error) -> Self { ContractError::NftsError(value) } } #[ink::contract(env = pop_api::Environment)] -mod pop_api_extension_demo { - use super::ContractError; +mod pop_api_nfts { + use super::*; #[ink(storage)] #[derive(Default)] - pub struct PopApiExtensionDemo; + pub struct Nfts; - impl PopApiExtensionDemo { + impl Nfts { #[ink(constructor, payable)] pub fn new() -> Self { - ink::env::debug_println!("Contract::new"); + ink::env::debug_println!("Nfts::new"); Default::default() } #[ink(message)] - pub fn mint_through_runtime( + pub fn create_nft_collection( &self ) -> Result<(), ContractError>{ + ink::env::debug_println!("Nfts::create_nft_collection: collection creation started."); + let admin = Self::env().caller(); + let item_settings = ItemSettings(BitFlags::from(ItemSetting::Transferable)); + + let mint_settings = MintSettings { + mint_type: MintType::Issuer, + price: Some(0), + start_block: Some(0), + end_block: Some(0), + default_item_settings: item_settings, + }; + + let config = CollectionConfig { + settings: CollectionSettings(BitFlags::from(CollectionSetting::TransferableItems)), + max_supply: None, + mint_settings, + }; + pop_api::nfts::create(admin, config)?; + ink::env::debug_println!("Nfts::create_nft_collection: collection created successfully."); + Ok(()) + } + + #[ink(message)] + pub fn mint_nft( &mut self, collection_id: u32, item_id: u32, receiver: AccountId, ) -> Result<(), ContractError> { ink::env::debug_println!( - "Contract::mint_through_runtime: collection_id: {:?} item_id {:?} receiver: {:?}", + "Nfts::mint_through_runtime: collection_id: {:?} item_id {:?} receiver: {:?}", collection_id, item_id, receiver @@ -53,13 +77,13 @@ mod pop_api_extension_demo { // mint api pop_api::nfts::mint(collection_id, item_id, receiver)?; - ink::env::debug_println!("Contract::mint_through_runtime: item minted successfully"); + ink::env::debug_println!("Nfts::mint_through_runtime: item minted successfully"); // check owner match pop_api::nfts::owner(collection_id, item_id)? { Some(owner) if owner == receiver => { ink::env::debug_println!( - "Contract::mint_through_runtime success: minted item belongs to receiver" + "Nfts::mint_through_runtime success: minted item belongs to receiver" ); }, _ => { @@ -67,7 +91,15 @@ mod pop_api_extension_demo { }, } - ink::env::debug_println!("Contract::mint_through_runtime end"); + ink::env::debug_println!("Nfts::mint_through_runtime end"); + Ok(()) + } + + #[ink(message)] + pub fn read_collection(&self, collection_id: u32) -> Result<(), ContractError> { + ink::env::debug_println!("Nfts::read_collection: collection_id: {:?}", collection_id); + let collection = pop_api::nfts::collection(collection_id)?; + ink::env::debug_println!("Nfts::read_collection: collection: {:?}", collection); Ok(()) } } @@ -78,7 +110,7 @@ mod pop_api_extension_demo { #[ink::test] fn default_works() { - PopApiExtensionDemo::new(); + Nfts::new(); } } } diff --git a/pop-api/src/v0/nfts.rs b/pop-api/src/v0/nfts.rs index 55569f2e..3db08cd1 100644 --- a/pop-api/src/v0/nfts.rs +++ b/pop-api/src/v0/nfts.rs @@ -681,7 +681,7 @@ mod types { primitives::{CollectionId, ItemId}, Balance, BlockNumber, }; - use enumflags2::{bitflags, BitFlags}; + pub use enumflags2::{bitflags, BitFlags}; use scale::{Decode, EncodeLike, MaxEncodedLen}; use scale_info::{build::Fields, meta_type, prelude::vec, Path, Type, TypeInfo, TypeParameter}; @@ -807,7 +807,7 @@ mod types { pub default_item_settings: ItemSettings, } - /// Mint type. Can the NFT be create by anyone, or only the creator of the collection, + /// Mint type. Can the NFT be created by anyone, or only the creator of the collection, /// or only by wallets that already hold an NFT from a certain collection? /// The ownership of a privately minted NFT is still publicly visible. #[derive(Encode)] diff --git a/runtime/devnet/src/extensions.rs b/runtime/devnet/src/extensions.rs index 59c636b2..89c070ee 100644 --- a/runtime/devnet/src/extensions.rs +++ b/runtime/devnet/src/extensions.rs @@ -474,6 +474,95 @@ mod tests { }); } + // Create a test for tesing create_nft_collection + #[test] + #[ignore] + fn dispatch_nfts_create_nft_collection() { + new_test_ext().execute_with(|| { + let _ = env_logger::try_init(); + + let (wasm_binary, _) = load_wasm_module::( + "../../pop-api/examples/nfts/target/ink/pop_api_nft_example.wasm", + ) + .unwrap(); + + let init_value = 100 * UNIT; + + let result = Contracts::bare_instantiate( + ALICE, + init_value, + GAS_LIMIT, + None, + Code::Upload(wasm_binary), + function_selector("new"), + vec![], + DEBUG_OUTPUT, + pallet_contracts::CollectEvents::Skip, + ) + .result + .unwrap(); + + assert!(!result.result.did_revert(), "deploying contract reverted {:?}", result); + + let addr = result.account_id; + + let function = function_selector("create_nft_collection"); + + let params = [function].concat(); + + let result = Contracts::bare_call( + ALICE, + addr.clone(), + 0, + Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), + None, + params, + DEBUG_OUTPUT, + pallet_contracts::CollectEvents::Skip, + pallet_contracts::Determinism::Enforced, + ); + + if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { + log::debug!( + "Contract debug buffer - {:?}", + String::from_utf8(result.debug_message.clone()) + ); + log::debug!("result: {:?}", result); + } + + // check that the nft collection was created + assert_eq!(Nfts::collection_owner(0), Some(addr.clone().into())); + + // test reading the collection + let function = function_selector("read_collection"); + + let params = [function, 0.encode()].concat(); + + let result = Contracts::bare_call( + ALICE, + addr.clone(), + 0, + Weight::from_parts(100_000_000_000, 3 * 1024 * 1024), + None, + params, + DEBUG_OUTPUT, + pallet_contracts::CollectEvents::Skip, + pallet_contracts::Determinism::Enforced, + ); + + if DEBUG_OUTPUT == pallet_contracts::DebugInfo::UnsafeDebug { + log::debug!( + "Contract debug buffer - {:?}", + String::from_utf8(result.debug_message.clone()) + ); + log::debug!("result: {:?}", result); + } + + // assert that the collection was read successfully + assert_eq!(result.result.clone().unwrap().data, vec![1, 1]); + }); + } + #[test] #[ignore] fn dispatch_nfts_mint_from_contract_works() {