difftreelog
Merge pull request #368 from UniqueNetwork/feature/CORE-386_1
in: master
Feature/core 386 1
27 files changed
pallets/common/src/erc.rsdiffbeforeafterboth--- a/pallets/common/src/erc.rs
+++ b/pallets/common/src/erc.rs
@@ -22,7 +22,9 @@
pub use pallet_evm::{PrecompileOutput, PrecompileResult, PrecompileHandle, account::CrossAccountId};
use pallet_evm_coder_substrate::dispatch_to_evm;
use sp_std::vec::Vec;
-use up_data_structs::{Property, SponsoringRateLimit, OwnerRestrictedSet, AccessMode};
+use up_data_structs::{
+ Property, SponsoringRateLimit, OwnerRestrictedSet, AccessMode, CollectionPermissions,
+};
use alloc::format;
use crate::{Pallet, CollectionHandle, Config, CollectionProperties};
@@ -47,10 +49,15 @@
#[solidity_interface(name = "Collection")]
impl<T: Config> CollectionHandle<T>
-// where
-// T::AccountId: From<H256>
+where
+ T::AccountId: From<[u8; 32]>,
{
- fn set_collection_property(&mut self, caller: caller, key: string, value: bytes) -> Result<()> {
+ fn set_collection_property(
+ &mut self,
+ caller: caller,
+ key: string,
+ value: bytes,
+ ) -> Result<void> {
let caller = T::CrossAccountId::from_eth(caller);
let key = <Vec<u8>>::from(key)
.try_into()
@@ -83,7 +90,7 @@
}
fn set_collection_sponsor(&mut self, caller: caller, sponsor: address) -> Result<void> {
- check_is_owner(caller, self)?;
+ check_is_owner_or_admin(caller, self)?;
let sponsor = T::CrossAccountId::from_eth(sponsor);
self.set_sponsor(sponsor.as_sub().clone())
@@ -97,14 +104,14 @@
.confirm_sponsorship(caller.as_sub())
.map_err(dispatch_to_evm::<T>)?
{
- return Err(Error::Revert("Caller is not set as sponsor".into()));
+ return Err("caller is not set as sponsor".into());
}
save(self)
}
#[solidity(rename_selector = "setCollectionLimit")]
fn set_int_limit(&mut self, caller: caller, limit: string, value: uint32) -> Result<void> {
- check_is_owner(caller, self)?;
+ check_is_owner_or_admin(caller, self)?;
let mut limits = self.limits.clone();
match limit.as_str() {
@@ -128,7 +135,7 @@
}
_ => {
return Err(Error::Revert(format!(
- "Unknown integer limit \"{}\"",
+ "unknown integer limit \"{}\"",
limit
)))
}
@@ -140,7 +147,7 @@
#[solidity(rename_selector = "setCollectionLimit")]
fn set_bool_limit(&mut self, caller: caller, limit: string, value: bool) -> Result<void> {
- check_is_owner(caller, self)?;
+ check_is_owner_or_admin(caller, self)?;
let mut limits = self.limits.clone();
match limit.as_str() {
@@ -155,7 +162,7 @@
}
_ => {
return Err(Error::Revert(format!(
- "Unknown boolean limit \"{}\"",
+ "unknown boolean limit \"{}\"",
limit
)))
}
@@ -169,52 +176,48 @@
Ok(crate::eth::collection_id_to_address(self.id))
}
- // fn add_admin_substrate(&self, caller: caller, new_admin: uint256) -> Result<void> {
- // let mut new_admin_h256 = H256::default();
- // new_admin.to_little_endian(&mut new_admin_h256.0);
- // let account_id = T::AccountId::from(new_admin_h256);
- // let caller = T::CrossAccountId::from_eth(caller);
- // let new_admin = T::CrossAccountId::from_sub(account_id);
- // <Pallet<T>>::toggle_admin(&self, &caller, &new_admin, true)
- // .map_err(dispatch_to_evm::<T>)?;
- // Ok(())
- // }
+ fn add_collection_admin_substrate(&self, caller: caller, new_admin: uint256) -> Result<void> {
+ let caller = T::CrossAccountId::from_eth(caller);
+ let mut new_admin_arr: [u8; 32] = Default::default();
+ new_admin.to_big_endian(&mut new_admin_arr);
+ let account_id = T::AccountId::from(new_admin_arr);
+ let new_admin = T::CrossAccountId::from_sub(account_id);
+ <Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;
+ Ok(())
+ }
- // fn remove_admin_substrate(&self, caller: caller, new_admin: uint256) -> Result<void> {
- // let mut new_admin_h256 = H256::default();
- // new_admin.to_little_endian(&mut new_admin_h256.0);
- // let account_id = T::AccountId::from(new_admin_h256);
- // let caller = T::CrossAccountId::from_eth(caller);
- // let new_admin = T::CrossAccountId::from_sub(account_id);
- // <Pallet<T>>::toggle_admin(&self, &caller, &new_admin, false)
- // .map_err(dispatch_to_evm::<T>)?;
- // Ok(())
- // }
+ fn remove_collection_admin_substrate(
+ &self,
+ caller: caller,
+ new_admin: uint256,
+ ) -> Result<void> {
+ let caller = T::CrossAccountId::from_eth(caller);
+ let mut new_admin_arr: [u8; 32] = Default::default();
+ new_admin.to_big_endian(&mut new_admin_arr);
+ let account_id = T::AccountId::from(new_admin_arr);
+ let new_admin = T::CrossAccountId::from_sub(account_id);
+ <Pallet<T>>::toggle_admin(self, &caller, &new_admin, false)
+ .map_err(dispatch_to_evm::<T>)?;
+ Ok(())
+ }
fn add_collection_admin(&self, caller: caller, new_admin: address) -> Result<void> {
let caller = T::CrossAccountId::from_eth(caller);
- self.check_is_owner_or_admin(&caller)
- .map_err(dispatch_to_evm::<T>)?;
let new_admin = T::CrossAccountId::from_eth(new_admin);
- <Pallet<T>>::toggle_admin(&self, &caller, &new_admin, true)
- .map_err(dispatch_to_evm::<T>)?;
+ <Pallet<T>>::toggle_admin(self, &caller, &new_admin, true).map_err(dispatch_to_evm::<T>)?;
Ok(())
}
fn remove_collection_admin(&self, caller: caller, admin: address) -> Result<void> {
let caller = T::CrossAccountId::from_eth(caller);
- self.check_is_owner_or_admin(&caller)
- .map_err(dispatch_to_evm::<T>)?;
let admin = T::CrossAccountId::from_eth(admin);
- <Pallet<T>>::toggle_admin(&self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;
+ <Pallet<T>>::toggle_admin(self, &caller, &admin, false).map_err(dispatch_to_evm::<T>)?;
Ok(())
}
#[solidity(rename_selector = "setCollectionNesting")]
fn set_nesting_bool(&mut self, caller: caller, enable: bool) -> Result<void> {
- let caller = T::CrossAccountId::from_eth(caller);
- self.check_is_owner_or_admin(&caller)
- .map_err(dispatch_to_evm::<T>)?;
+ check_is_owner_or_admin(caller, self)?;
let mut permissions = self.collection.permissions.clone();
let mut nesting = permissions.nesting().clone();
@@ -240,11 +243,9 @@
collections: Vec<address>,
) -> Result<void> {
if collections.is_empty() {
- return Err("No addresses provided".into());
+ return Err("no addresses provided".into());
}
- let caller = T::CrossAccountId::from_eth(caller);
- self.check_is_owner_or_admin(&caller)
- .map_err(dispatch_to_evm::<T>)?;
+ check_is_owner_or_admin(caller, self)?;
let mut permissions = self.collection.permissions.clone();
match enable {
@@ -280,27 +281,34 @@
}
fn set_collection_access(&mut self, caller: caller, mode: uint8) -> Result<void> {
- let caller = T::CrossAccountId::from_eth(caller);
- self.check_is_owner_or_admin(&caller)
- .map_err(dispatch_to_evm::<T>)?;
- self.collection.permissions.access = Some(match mode {
- 0 => AccessMode::Normal,
- 1 => AccessMode::AllowList,
- _ => return Err("Not supported access mode".into()),
- });
- save(self)?;
- Ok(())
+ check_is_owner_or_admin(caller, self)?;
+ let permissions = CollectionPermissions {
+ access: Some(match mode {
+ 0 => AccessMode::Normal,
+ 1 => AccessMode::AllowList,
+ _ => return Err("not supported access mode".into()),
+ }),
+ ..Default::default()
+ };
+ self.collection.permissions = <Pallet<T>>::clamp_permissions(
+ self.collection.mode.clone(),
+ &self.collection.permissions,
+ permissions,
+ )
+ .map_err(dispatch_to_evm::<T>)?;
+
+ save(self)
}
fn add_to_collection_allow_list(&self, caller: caller, user: address) -> Result<void> {
- let caller = check_is_owner_or_admin(caller, self)?;
+ let caller = T::CrossAccountId::from_eth(caller);
let user = T::CrossAccountId::from_eth(user);
<Pallet<T>>::toggle_allowlist(self, &caller, &user, true).map_err(dispatch_to_evm::<T>)?;
Ok(())
}
fn remove_from_collection_allow_list(&self, caller: caller, user: address) -> Result<void> {
- let caller = check_is_owner_or_admin(caller, self)?;
+ let caller = T::CrossAccountId::from_eth(caller);
let user = T::CrossAccountId::from_eth(user);
<Pallet<T>>::toggle_allowlist(self, &caller, &user, false).map_err(dispatch_to_evm::<T>)?;
Ok(())
@@ -308,18 +316,19 @@
fn set_collection_mint_mode(&mut self, caller: caller, mode: bool) -> Result<void> {
check_is_owner_or_admin(caller, self)?;
- self.collection.permissions.mint_mode = Some(mode);
- save(self)?;
- Ok(())
- }
-}
+ let permissions = CollectionPermissions {
+ mint_mode: Some(mode),
+ ..Default::default()
+ };
+ self.collection.permissions = <Pallet<T>>::clamp_permissions(
+ self.collection.mode.clone(),
+ &self.collection.permissions,
+ permissions,
+ )
+ .map_err(dispatch_to_evm::<T>)?;
-fn check_is_owner<T: Config>(caller: caller, collection: &CollectionHandle<T>) -> Result<void> {
- let caller = T::CrossAccountId::from_eth(caller);
- collection
- .check_is_owner(&caller)
- .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;
- Ok(())
+ save(self)
+ }
}
fn check_is_owner_or_admin<T: Config>(
pallets/common/src/lib.rsdiffbeforeafterboth--- a/pallets/common/src/lib.rs
+++ b/pallets/common/src/lib.rs
@@ -148,7 +148,7 @@
.saturating_mul(writes),
))
}
- pub fn save(self) -> Result<(), DispatchError> {
+ pub fn save(self) -> DispatchResult {
<CollectionById<T>>::insert(self.id, self.collection);
Ok(())
}
pallets/fungible/src/erc.rsdiffbeforeafterboth--- a/pallets/fungible/src/erc.rs
+++ b/pallets/fungible/src/erc.rs
@@ -152,12 +152,15 @@
via("CollectionHandle<T>", common_mut, Collection)
)
)]
-impl<T: Config> FungibleHandle<T> {}
+impl<T: Config> FungibleHandle<T> where T::AccountId: From<[u8; 32]> {}
generate_stubgen!(gen_impl, UniqueFungibleCall<()>, true);
generate_stubgen!(gen_iface, UniqueFungibleCall<()>, false);
-impl<T: Config> CommonEvmHandler for FungibleHandle<T> {
+impl<T: Config> CommonEvmHandler for FungibleHandle<T>
+where
+ T::AccountId: From<[u8; 32]>,
+{
const CODE: &'static [u8] = include_bytes!("./stubs/UniqueFungible.raw");
fn call(self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {
pallets/nonfungible/src/erc.rsdiffbeforeafterboth--- a/pallets/nonfungible/src/erc.rs
+++ b/pallets/nonfungible/src/erc.rs
@@ -583,13 +583,16 @@
TokenProperties,
)
)]
-impl<T: Config> NonfungibleHandle<T> {}
+impl<T: Config> NonfungibleHandle<T> where T::AccountId: From<[u8; 32]> {}
// Not a tests, but code generators
generate_stubgen!(gen_impl, UniqueNFTCall<()>, true);
generate_stubgen!(gen_iface, UniqueNFTCall<()>, false);
-impl<T: Config> CommonEvmHandler for NonfungibleHandle<T> {
+impl<T: Config> CommonEvmHandler for NonfungibleHandle<T>
+where
+ T::AccountId: From<[u8; 32]>,
+{
const CODE: &'static [u8] = include_bytes!("./stubs/UniqueNFT.raw");
fn call(self, handle: &mut impl PrecompileHandle) -> Option<PrecompileResult> {
pallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterbothbinary blob — no preview
pallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth--- a/pallets/nonfungible/src/stubs/UniqueNFT.sol
+++ b/pallets/nonfungible/src/stubs/UniqueNFT.sol
@@ -297,7 +297,40 @@
}
}
-// Selector: 6aea9834
+// Selector: 780e9d63
+contract ERC721Enumerable is Dummy, ERC165 {
+ // Selector: tokenByIndex(uint256) 4f6ccce7
+ function tokenByIndex(uint256 index) public view returns (uint256) {
+ require(false, stub_error);
+ index;
+ dummy;
+ return 0;
+ }
+
+ // Not implemented
+ //
+ // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59
+ function tokenOfOwnerByIndex(address owner, uint256 index)
+ public
+ view
+ returns (uint256)
+ {
+ require(false, stub_error);
+ owner;
+ index;
+ dummy;
+ return 0;
+ }
+
+ // Selector: totalSupply() 18160ddd
+ function totalSupply() public view returns (uint256) {
+ require(false, stub_error);
+ dummy;
+ return 0;
+ }
+}
+
+// Selector: 7d9262e6
contract Collection is Dummy, ERC165 {
// Selector: setCollectionProperty(string,bytes) 2f073f66
function setCollectionProperty(string memory key, bytes memory value)
@@ -366,6 +399,20 @@
return 0x0000000000000000000000000000000000000000;
}
+ // Selector: addCollectionAdminSubstrate(uint256) 5730062b
+ function addCollectionAdminSubstrate(uint256 newAdmin) public view {
+ require(false, stub_error);
+ newAdmin;
+ dummy;
+ }
+
+ // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9
+ function removeCollectionAdminSubstrate(uint256 newAdmin) public view {
+ require(false, stub_error);
+ newAdmin;
+ dummy;
+ }
+
// Selector: addCollectionAdmin(address) 92e462c7
function addCollectionAdmin(address newAdmin) public view {
require(false, stub_error);
@@ -423,39 +470,6 @@
require(false, stub_error);
mode;
dummy = 0;
- }
-}
-
-// Selector: 780e9d63
-contract ERC721Enumerable is Dummy, ERC165 {
- // Selector: tokenByIndex(uint256) 4f6ccce7
- function tokenByIndex(uint256 index) public view returns (uint256) {
- require(false, stub_error);
- index;
- dummy;
- return 0;
- }
-
- // Not implemented
- //
- // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59
- function tokenOfOwnerByIndex(address owner, uint256 index)
- public
- view
- returns (uint256)
- {
- require(false, stub_error);
- owner;
- index;
- dummy;
- return 0;
- }
-
- // Selector: totalSupply() 18160ddd
- function totalSupply() public view returns (uint256) {
- require(false, stub_error);
- dummy;
- return 0;
}
}
pallets/unique/src/lib.rsdiffbeforeafterboth--- a/pallets/unique/src/lib.rs
+++ b/pallets/unique/src/lib.rs
@@ -491,7 +491,7 @@
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
- target_collection.check_is_owner(&sender)?;
+ target_collection.check_is_owner_or_admin(&sender)?;
target_collection.check_is_internal()?;
target_collection.set_sponsor(new_sponsor.clone())?;
@@ -867,7 +867,7 @@
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
target_collection.check_is_internal()?;
- target_collection.check_is_owner(&sender)?;
+ target_collection.check_is_owner_or_admin(&sender)?;
let old_limit = &target_collection.limits;
target_collection.limits = <PalletCommon<T>>::clamp_limits(target_collection.mode.clone(), &old_limit, new_limit)?;
@@ -889,7 +889,7 @@
let sender = T::CrossAccountId::from_sub(ensure_signed(origin)?);
let mut target_collection = <CollectionHandle<T>>::try_get(collection_id)?;
target_collection.check_is_internal()?;
- target_collection.check_is_owner(&sender)?;
+ target_collection.check_is_owner_or_admin(&sender)?;
let old_limit = &target_collection.permissions;
target_collection.permissions = <PalletCommon<T>>::clamp_permissions(target_collection.mode.clone(), &old_limit, new_limit)?;
primitives/data-structs/src/lib.rsdiffbeforeafterboth--- a/primitives/data-structs/src/lib.rs
+++ b/primitives/data-structs/src/lib.rs
@@ -812,7 +812,7 @@
for byte in key.as_slice().iter() {
let byte = *byte;
- if !byte.is_ascii_alphanumeric() && byte != b'_' && byte != b'-' {
+ if !byte.is_ascii_alphanumeric() && byte != b'_' && byte != b'-' && byte != b'.' {
return Err(PropertiesError::InvalidCharacterInPropertyKey);
}
}
runtime/common/src/dispatch.rsdiffbeforeafterboth--- a/runtime/common/src/dispatch.rs
+++ b/runtime/common/src/dispatch.rs
@@ -112,6 +112,7 @@
+ pallet_fungible::Config
+ pallet_nonfungible::Config
+ pallet_refungible::Config,
+ T::AccountId: From<[u8; 32]>,
{
fn is_reserved(target: &H160) -> bool {
map_eth_to_id(target).is_some()
runtime/tests/src/tests.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// Tests to be written here18use crate::{Test, TestCrossAccountId, CollectionCreationPrice, Origin, Unique, new_test_ext};19use up_data_structs::{20 COLLECTION_NUMBER_LIMIT, CollectionId, CreateItemData, CreateFungibleData, CreateNftData,21 CreateReFungibleData, MAX_DECIMAL_POINTS, COLLECTION_ADMINS_LIMIT, TokenId,22 MAX_TOKEN_OWNERSHIP, CreateCollectionData, CollectionMode, AccessMode, CollectionPermissions,23 PropertyKeyPermission, PropertyPermission, Property, CollectionPropertiesVec,24 CollectionPropertiesPermissionsVec, TokenChild,25};26use frame_support::{assert_noop, assert_ok, assert_err};27use sp_std::convert::TryInto;28use pallet_evm::account::CrossAccountId;29use pallet_common::Error as CommonError;30use pallet_unique::Error as UniqueError;3132fn add_balance(user: u64, value: u64) {33 const DONOR_USER: u64 = 999;34 assert_ok!(<pallet_balances::Pallet<Test>>::set_balance(35 Origin::root(),36 DONOR_USER,37 value,38 039 ));40 assert_ok!(<pallet_balances::Pallet<Test>>::force_transfer(41 Origin::root(),42 DONOR_USER,43 user,44 value45 ));46}4748fn default_nft_data() -> CreateNftData {49 CreateNftData {50 properties: vec![Property {51 key: b"test-prop".to_vec().try_into().unwrap(),52 value: b"test-nft-prop".to_vec().try_into().unwrap(),53 }]54 .try_into()55 .unwrap(),56 }57}5859fn default_fungible_data() -> CreateFungibleData {60 CreateFungibleData { value: 5 }61}6263fn default_re_fungible_data() -> CreateReFungibleData {64 CreateReFungibleData {65 const_data: vec![1, 2, 3].try_into().unwrap(),66 pieces: 1023,67 }68}6970fn create_test_collection_for_owner(71 mode: &CollectionMode,72 owner: u64,73 id: CollectionId,74) -> CollectionId {75 add_balance(owner, CollectionCreationPrice::get() as u64 + 1);7677 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();78 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();79 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();80 let token_property_permissions: CollectionPropertiesPermissionsVec =81 vec![PropertyKeyPermission {82 key: b"test-prop".to_vec().try_into().unwrap(),83 permission: PropertyPermission {84 mutable: true,85 collection_admin: false,86 token_owner: true,87 },88 }]89 .try_into()90 .unwrap();91 let properties: CollectionPropertiesVec = vec![Property {92 key: b"test-collection-prop".to_vec().try_into().unwrap(),93 value: b"test-collection-value".to_vec().try_into().unwrap(),94 }]95 .try_into()96 .unwrap();9798 let data: CreateCollectionData<u64> = CreateCollectionData {99 name: col_name1.try_into().unwrap(),100 description: col_desc1.try_into().unwrap(),101 token_prefix: token_prefix1.try_into().unwrap(),102 mode: mode.clone(),103 token_property_permissions: token_property_permissions.clone(),104 properties: properties.clone(),105 ..Default::default()106 };107108 let origin1 = Origin::signed(owner);109 assert_ok!(Unique::create_collection_ex(origin1, data));110111 let saved_col_name: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();112 let saved_description: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();113 let saved_prefix: Vec<u8> = b"token_prefix1\0".to_vec();114 assert_eq!(115 <pallet_common::CollectionById<Test>>::get(id)116 .unwrap()117 .owner,118 owner119 );120 assert_eq!(121 <pallet_common::CollectionById<Test>>::get(id).unwrap().name,122 saved_col_name123 );124 assert_eq!(125 <pallet_common::CollectionById<Test>>::get(id).unwrap().mode,126 *mode127 );128 assert_eq!(129 <pallet_common::CollectionById<Test>>::get(id)130 .unwrap()131 .description,132 saved_description133 );134 assert_eq!(135 <pallet_common::CollectionById<Test>>::get(id)136 .unwrap()137 .token_prefix,138 saved_prefix139 );140 assert_eq!(141 get_collection_property_permissions(id).as_slice(),142 token_property_permissions.as_slice()143 );144 assert_eq!(145 get_collection_properties(id).as_slice(),146 properties.as_slice()147 );148 id149}150151fn get_collection_property_permissions(collection_id: CollectionId) -> Vec<PropertyKeyPermission> {152 <pallet_common::Pallet<Test>>::property_permissions(collection_id)153 .into_iter()154 .map(|(key, permission)| PropertyKeyPermission { key, permission })155 .collect()156}157158fn get_collection_properties(collection_id: CollectionId) -> Vec<Property> {159 <pallet_common::Pallet<Test>>::collection_properties(collection_id)160 .into_iter()161 .map(|(key, value)| Property { key, value })162 .collect()163}164165fn get_token_properties(collection_id: CollectionId, token_id: TokenId) -> Vec<Property> {166 <pallet_nonfungible::Pallet<Test>>::token_properties((collection_id, token_id))167 .into_iter()168 .map(|(key, value)| Property { key, value })169 .collect()170}171172fn create_test_collection(mode: &CollectionMode, id: CollectionId) -> CollectionId {173 create_test_collection_for_owner(&mode, 1, id)174}175176fn create_test_item(collection_id: CollectionId, data: &CreateItemData) {177 let origin1 = Origin::signed(1);178 assert_ok!(Unique::create_item(179 origin1,180 collection_id,181 account(1),182 data.clone()183 ));184}185186fn account(sub: u64) -> TestCrossAccountId {187 TestCrossAccountId::from_sub(sub)188}189190// Use cases tests region191// #region192193#[test]194fn check_not_sufficient_founds() {195 new_test_ext().execute_with(|| {196 let acc: u64 = 1;197 <pallet_balances::Pallet<Test>>::set_balance(Origin::root(), acc, 0, 0).unwrap();198199 let name: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();200 let description: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();201 let token_prefix: Vec<u8> = b"token_prefix1\0".to_vec();202203 let data: CreateCollectionData<<Test as frame_system::Config>::AccountId> =204 CreateCollectionData {205 name: name.try_into().unwrap(),206 description: description.try_into().unwrap(),207 token_prefix: token_prefix.try_into().unwrap(),208 mode: CollectionMode::NFT,209 ..Default::default()210 };211212 let result = Unique::create_collection_ex(Origin::signed(acc), data);213 assert_err!(result, <CommonError<Test>>::NotSufficientFounds);214 });215}216217#[test]218fn create_fungible_collection_fails_with_large_decimal_numbers() {219 new_test_ext().execute_with(|| {220 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();221 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();222 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();223224 let data: CreateCollectionData<u64> = CreateCollectionData {225 name: col_name1.try_into().unwrap(),226 description: col_desc1.try_into().unwrap(),227 token_prefix: token_prefix1.try_into().unwrap(),228 mode: CollectionMode::Fungible(MAX_DECIMAL_POINTS + 1),229 ..Default::default()230 };231232 let origin1 = Origin::signed(1);233 assert_noop!(234 Unique::create_collection_ex(origin1, data),235 UniqueError::<Test>::CollectionDecimalPointLimitExceeded236 );237 });238}239240#[test]241fn create_nft_item() {242 new_test_ext().execute_with(|| {243 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));244245 let data = default_nft_data();246 create_test_item(collection_id, &data.clone().into());247248 assert_eq!(249 get_token_properties(collection_id, TokenId(1)).as_slice(),250 data.properties.as_slice(),251 );252 });253}254255// Use cases tests region256// #region257#[test]258fn create_nft_multiple_items() {259 new_test_ext().execute_with(|| {260 create_test_collection(&CollectionMode::NFT, CollectionId(1));261262 let origin1 = Origin::signed(1);263264 let items_data = vec![default_nft_data(), default_nft_data(), default_nft_data()];265266 assert_ok!(Unique::create_multiple_items(267 origin1,268 CollectionId(1),269 account(1),270 items_data271 .clone()272 .into_iter()273 .map(|d| { d.into() })274 .collect()275 ));276 for (index, data) in items_data.into_iter().enumerate() {277 assert_eq!(278 get_token_properties(CollectionId(1), TokenId(index as u32 + 1)).as_slice(),279 data.properties.as_slice()280 );281 }282 });283}284285#[test]286fn create_refungible_item() {287 new_test_ext().execute_with(|| {288 let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));289290 let data = default_re_fungible_data();291 create_test_item(collection_id, &data.clone().into());292 let item = <pallet_refungible::TokenData<Test>>::get((collection_id, TokenId(1)));293 let balance =294 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1)));295 assert_eq!(item.const_data, data.const_data.into_inner());296 assert_eq!(balance, 1023);297 });298}299300#[test]301fn create_multiple_refungible_items() {302 new_test_ext().execute_with(|| {303 create_test_collection(&CollectionMode::ReFungible, CollectionId(1));304305 let origin1 = Origin::signed(1);306307 let items_data = vec![308 default_re_fungible_data(),309 default_re_fungible_data(),310 default_re_fungible_data(),311 ];312313 assert_ok!(Unique::create_multiple_items(314 origin1,315 CollectionId(1),316 account(1),317 items_data318 .clone()319 .into_iter()320 .map(|d| { d.into() })321 .collect()322 ));323 for (index, data) in items_data.into_iter().enumerate() {324 let item = <pallet_refungible::TokenData<Test>>::get((325 CollectionId(1),326 TokenId((index + 1) as u32),327 ));328 let balance =329 <pallet_refungible::Balance<Test>>::get((CollectionId(1), TokenId(1), account(1)));330 assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());331 assert_eq!(balance, 1023);332 }333 });334}335336#[test]337fn create_fungible_item() {338 new_test_ext().execute_with(|| {339 let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));340341 let data = default_fungible_data();342 create_test_item(collection_id, &data.into());343344 assert_eq!(345 <pallet_fungible::Balance<Test>>::get((collection_id, account(1))),346 5347 );348 });349}350351//#[test]352// fn create_multiple_fungible_items() {353// new_test_ext().execute_with(|| {354// default_limits();355356// create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));357358// let origin1 = Origin::signed(1);359360// let items_data = vec![default_fungible_data(), default_fungible_data(), default_fungible_data()];361362// assert_ok!(Unique::create_multiple_items(363// origin1.clone(),364// 1,365// 1,366// items_data.clone().into_iter().map(|d| { d.into() }).collect()367// ));368369// for (index, _) in items_data.iter().enumerate() {370// assert_eq!(Unique::fungible_item_id(1, (index + 1) as TokenId).value, 5);371// }372// assert_eq!(Unique::balance_count(1, 1), 3000);373// assert_eq!(Unique::address_tokens(1, 1), [1, 2, 3]);374// });375// }376377#[test]378fn transfer_fungible_item() {379 new_test_ext().execute_with(|| {380 let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));381382 let origin1 = Origin::signed(1);383 let origin2 = Origin::signed(2);384385 let data = default_fungible_data();386 create_test_item(collection_id, &data.into());387388 assert_eq!(389 <pallet_fungible::Balance<Test>>::get((CollectionId(1), account(1))),390 5391 );392393 // change owner scenario394 assert_ok!(Unique::transfer(395 origin1,396 account(2),397 CollectionId(1),398 TokenId(0),399 5400 ));401 assert_eq!(402 <pallet_fungible::Balance<Test>>::get((CollectionId(1), account(1))),403 0404 );405406 // split item scenario407 assert_ok!(Unique::transfer(408 origin2.clone(),409 account(3),410 CollectionId(1),411 TokenId(0),412 3413 ));414415 // split item and new owner has account scenario416 assert_ok!(Unique::transfer(417 origin2,418 account(3),419 CollectionId(1),420 TokenId(0),421 1422 ));423 assert_eq!(424 <pallet_fungible::Balance<Test>>::get((CollectionId(1), account(2))),425 1426 );427 assert_eq!(428 <pallet_fungible::Balance<Test>>::get((CollectionId(1), account(3))),429 4430 );431 });432}433434#[test]435fn transfer_refungible_item() {436 new_test_ext().execute_with(|| {437 let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));438439 // Create RFT 1 in 1023 pieces for account 1440 let data = default_re_fungible_data();441 create_test_item(collection_id, &data.clone().into());442 let item = <pallet_refungible::TokenData<Test>>::get((collection_id, TokenId(1)));443 assert_eq!(item.const_data, data.const_data.into_inner());444 assert_eq!(445 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),446 1447 );448 assert_eq!(449 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),450 1023451 );452 assert_eq!(453 <pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),454 true455 );456457 // Account 1 transfers all 1023 pieces of RFT 1 to account 2458 let origin1 = Origin::signed(1);459 let origin2 = Origin::signed(2);460 assert_ok!(Unique::transfer(461 origin1,462 account(2),463 CollectionId(1),464 TokenId(1),465 1023466 ));467 assert_eq!(468 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(2))),469 1023470 );471 assert_eq!(472 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),473 0474 );475 assert_eq!(476 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(2))),477 1478 );479 assert_eq!(480 <pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),481 false482 );483 assert_eq!(484 <pallet_refungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),485 true486 );487488 // Account 2 transfers 500 pieces of RFT 1 to account 3489 assert_ok!(Unique::transfer(490 origin2.clone(),491 account(3),492 CollectionId(1),493 TokenId(1),494 500495 ));496 assert_eq!(497 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(2))),498 523499 );500 assert_eq!(501 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(3))),502 500503 );504 assert_eq!(505 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(2))),506 1507 );508 assert_eq!(509 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(3))),510 1511 );512 assert_eq!(513 <pallet_refungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),514 true515 );516 assert_eq!(517 <pallet_refungible::Owned<Test>>::get((collection_id, account(3), TokenId(1))),518 true519 );520521 // Account 2 transfers 200 more pieces of RFT 1 to account 3 with pre-existing balance522 assert_ok!(Unique::transfer(523 origin2,524 account(3),525 CollectionId(1),526 TokenId(1),527 200528 ));529 assert_eq!(530 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(2))),531 323532 );533 assert_eq!(534 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(3))),535 700536 );537 assert_eq!(538 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(2))),539 1540 );541 assert_eq!(542 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(3))),543 1544 );545 assert_eq!(546 <pallet_refungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),547 true548 );549 assert_eq!(550 <pallet_refungible::Owned<Test>>::get((collection_id, account(3), TokenId(1))),551 true552 );553 });554}555556#[test]557fn transfer_nft_item() {558 new_test_ext().execute_with(|| {559 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));560561 let data = default_nft_data();562 create_test_item(collection_id, &data.into());563 assert_eq!(564 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),565 1566 );567 assert_eq!(568 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),569 true570 );571572 let origin1 = Origin::signed(1);573 // default scenario574 assert_ok!(Unique::transfer(575 origin1,576 account(2),577 CollectionId(1),578 TokenId(1),579 1580 ));581 assert_eq!(582 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),583 0584 );585 assert_eq!(586 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),587 1588 );589 assert_eq!(590 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),591 false592 );593 assert_eq!(594 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),595 true596 );597 });598}599600#[test]601fn transfer_nft_item_wrong_value() {602 new_test_ext().execute_with(|| {603 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));604605 let data = default_nft_data();606 create_test_item(collection_id, &data.into());607 assert_eq!(608 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),609 1610 );611 assert_eq!(612 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),613 true614 );615616 let origin1 = Origin::signed(1);617618 assert_noop!(619 Unique::transfer(origin1, account(2), CollectionId(1), TokenId(1), 2)620 .map_err(|e| e.error),621 <pallet_nonfungible::Error::<Test>>::NonfungibleItemsHaveNoAmount622 );623 });624}625626#[test]627fn transfer_nft_item_zero_value() {628 new_test_ext().execute_with(|| {629 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));630631 let data = default_nft_data();632 create_test_item(collection_id, &data.into());633 assert_eq!(634 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),635 1636 );637 assert_eq!(638 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),639 true640 );641642 let origin1 = Origin::signed(1);643644 // Transferring 0 amount works on NFT...645 assert_ok!(Unique::transfer(646 origin1,647 account(2),648 CollectionId(1),649 TokenId(1),650 0651 ));652 // ... and results in no transfer653 assert_eq!(654 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),655 1656 );657 assert_eq!(658 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),659 true660 );661 });662}663664#[test]665fn nft_approve_and_transfer_from() {666 new_test_ext().execute_with(|| {667 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));668669 let data = default_nft_data();670 create_test_item(collection_id, &data.into());671672 let origin1 = Origin::signed(1);673 let origin2 = Origin::signed(2);674675 assert_eq!(676 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),677 1678 );679 assert_eq!(680 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),681 true682 );683684 // neg transfer_from685 assert_noop!(686 Unique::transfer_from(687 origin2.clone(),688 account(1),689 account(2),690 CollectionId(1),691 TokenId(1),692 1693 )694 .map_err(|e| e.error),695 CommonError::<Test>::ApprovedValueTooLow696 );697698 // do approve699 assert_ok!(Unique::approve(700 origin1,701 account(2),702 CollectionId(1),703 TokenId(1),704 1705 ));706 assert_eq!(707 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),708 account(2)709 );710711 assert_ok!(Unique::transfer_from(712 origin2,713 account(1),714 account(3),715 CollectionId(1),716 TokenId(1),717 1718 ));719 assert!(720 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).is_none()721 );722 });723}724725#[test]726fn nft_approve_and_transfer_from_allow_list() {727 new_test_ext().execute_with(|| {728 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));729730 let origin1 = Origin::signed(1);731 let origin2 = Origin::signed(2);732733 // Create NFT 1 for account 1734 let data = default_nft_data();735 create_test_item(collection_id, &data.clone().into());736 assert_eq!(737 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),738 1739 );740 assert_eq!(741 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),742 true743 );744745 // Allow allow-list users to mint and add accounts 1, 2, and 3 to allow-list746 assert_ok!(Unique::set_collection_permissions(747 origin1.clone(),748 CollectionId(1),749 CollectionPermissions {750 mint_mode: Some(true),751 access: Some(AccessMode::AllowList),752 nesting: None,753 }754 ));755 assert_ok!(Unique::add_to_allow_list(756 origin1.clone(),757 CollectionId(1),758 account(1)759 ));760 assert_ok!(Unique::add_to_allow_list(761 origin1.clone(),762 CollectionId(1),763 account(2)764 ));765 assert_ok!(Unique::add_to_allow_list(766 origin1.clone(),767 CollectionId(1),768 account(3)769 ));770771 // Account 1 approves account 2 for NFT 1772 assert_ok!(Unique::approve(773 origin1.clone(),774 account(2),775 CollectionId(1),776 TokenId(1),777 1778 ));779 assert_eq!(780 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),781 account(2)782 );783784 // Account 2 transfers NFT 1 from account 1 to account 3785 assert_ok!(Unique::transfer_from(786 origin2,787 account(1),788 account(3),789 CollectionId(1),790 TokenId(1),791 1792 ));793 assert!(794 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).is_none()795 );796 });797}798799#[test]800fn refungible_approve_and_transfer_from() {801 new_test_ext().execute_with(|| {802 let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));803804 let origin1 = Origin::signed(1);805 let origin2 = Origin::signed(2);806807 // Create RFT 1 in 1023 pieces for account 1808 let data = default_re_fungible_data();809 create_test_item(collection_id, &data.into());810811 assert_eq!(812 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),813 1814 );815 assert_eq!(816 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),817 1023818 );819 assert_eq!(820 <pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),821 true822 );823824 // Allow public minting, enable allow-list and add accounts 1, 2, 3 to allow-list825 assert_ok!(Unique::set_collection_permissions(826 origin1.clone(),827 CollectionId(1),828 CollectionPermissions {829 mint_mode: Some(true),830 access: Some(AccessMode::AllowList),831 nesting: None,832 }833 ));834 assert_ok!(Unique::add_to_allow_list(835 origin1.clone(),836 CollectionId(1),837 account(1)838 ));839 assert_ok!(Unique::add_to_allow_list(840 origin1.clone(),841 CollectionId(1),842 account(2)843 ));844 assert_ok!(Unique::add_to_allow_list(845 origin1.clone(),846 CollectionId(1),847 account(3)848 ));849850 // Account 1 approves account 2 for 1023 pieces of RFT 1851 assert_ok!(Unique::approve(852 origin1,853 account(2),854 CollectionId(1),855 TokenId(1),856 1023857 ));858 assert_eq!(859 <pallet_refungible::Allowance<Test>>::get((860 CollectionId(1),861 TokenId(1),862 account(1),863 account(2)864 )),865 1023866 );867868 // Account 2 transfers 100 pieces of RFT 1 from account 1 to account 3869 assert_ok!(Unique::transfer_from(870 origin2,871 account(1),872 account(3),873 CollectionId(1),874 TokenId(1),875 100876 ));877 assert_eq!(878 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),879 1880 );881 assert_eq!(882 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(3))),883 1884 );885 assert_eq!(886 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),887 923888 );889 assert_eq!(890 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(3))),891 100892 );893 assert_eq!(894 <pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),895 true896 );897 assert_eq!(898 <pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),899 true900 );901 assert_eq!(902 <pallet_refungible::Allowance<Test>>::get((903 CollectionId(1),904 TokenId(1),905 account(1),906 account(2)907 )),908 923909 );910 });911}912913#[test]914fn fungible_approve_and_transfer_from() {915 new_test_ext().execute_with(|| {916 let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));917918 let data = default_fungible_data();919 create_test_item(collection_id, &data.into());920921 let origin1 = Origin::signed(1);922 let origin2 = Origin::signed(2);923924 assert_ok!(Unique::set_collection_permissions(925 origin1.clone(),926 CollectionId(1),927 CollectionPermissions {928 mint_mode: Some(true),929 access: Some(AccessMode::AllowList),930 nesting: None,931 }932 ));933 assert_ok!(Unique::add_to_allow_list(934 origin1.clone(),935 CollectionId(1),936 account(1)937 ));938 assert_ok!(Unique::add_to_allow_list(939 origin1.clone(),940 CollectionId(1),941 account(2)942 ));943 assert_ok!(Unique::add_to_allow_list(944 origin1.clone(),945 CollectionId(1),946 account(3)947 ));948949 // do approve950 assert_ok!(Unique::approve(951 origin1.clone(),952 account(2),953 CollectionId(1),954 TokenId(0),955 5956 ));957 assert_eq!(958 <pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(2))),959 5960 );961 assert_ok!(Unique::approve(962 origin1,963 account(3),964 CollectionId(1),965 TokenId(0),966 5967 ));968 assert_eq!(969 <pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(2))),970 5971 );972 assert_eq!(973 <pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(3))),974 5975 );976977 assert_ok!(Unique::transfer_from(978 origin2.clone(),979 account(1),980 account(3),981 CollectionId(1),982 TokenId(0),983 4984 ));985986 assert_eq!(987 <pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(2))),988 1989 );990991 assert_noop!(992 Unique::transfer_from(993 origin2,994 account(1),995 account(3),996 CollectionId(1),997 TokenId(0),998 4999 )1000 .map_err(|e| e.error),1001 CommonError::<Test>::ApprovedValueTooLow1002 );1003 });1004}10051006#[test]1007fn change_collection_owner() {1008 new_test_ext().execute_with(|| {1009 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10101011 let origin1 = Origin::signed(1);1012 assert_ok!(Unique::change_collection_owner(origin1, collection_id, 2));1013 assert_eq!(1014 <pallet_common::CollectionById<Test>>::get(collection_id)1015 .unwrap()1016 .owner,1017 21018 );1019 });1020}10211022#[test]1023fn destroy_collection() {1024 new_test_ext().execute_with(|| {1025 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10261027 let origin1 = Origin::signed(1);1028 assert_ok!(Unique::destroy_collection(origin1, collection_id));1029 });1030}10311032#[test]1033fn burn_nft_item() {1034 new_test_ext().execute_with(|| {1035 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10361037 let origin1 = Origin::signed(1);10381039 let data = default_nft_data();1040 create_test_item(collection_id, &data.into());10411042 // check balance (collection with id = 1, user id = 1)1043 assert_eq!(1044 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1045 11046 );10471048 // burn item1049 assert_ok!(Unique::burn_item(1050 origin1.clone(),1051 collection_id,1052 TokenId(1),1053 11054 ));1055 assert_eq!(1056 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1057 01058 );1059 });1060}10611062#[test]1063fn burn_same_nft_item_twice() {1064 new_test_ext().execute_with(|| {1065 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10661067 let origin1 = Origin::signed(1);10681069 let data = default_nft_data();1070 create_test_item(collection_id, &data.into());10711072 // check balance (collection with id = 1, user id = 1)1073 assert_eq!(1074 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1075 11076 );10771078 // burn item1079 assert_ok!(Unique::burn_item(1080 origin1.clone(),1081 collection_id,1082 TokenId(1),1083 11084 ));10851086 // burn item again1087 assert_noop!(1088 Unique::burn_item(origin1, collection_id, TokenId(1), 1).map_err(|e| e.error),1089 CommonError::<Test>::TokenNotFound1090 );10911092 assert_eq!(1093 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1094 01095 );1096 });1097}10981099#[test]1100fn burn_fungible_item() {1101 new_test_ext().execute_with(|| {1102 let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));11031104 let origin1 = Origin::signed(1);1105 assert_ok!(Unique::add_collection_admin(1106 origin1.clone(),1107 collection_id,1108 account(2)1109 ));11101111 let data = default_fungible_data();1112 create_test_item(collection_id, &data.into());11131114 // check balance (collection with id = 1, user id = 1)1115 assert_eq!(1116 <pallet_fungible::Balance<Test>>::get((collection_id, account(1))),1117 51118 );11191120 // burn item1121 assert_ok!(Unique::burn_item(1122 origin1.clone(),1123 CollectionId(1),1124 TokenId(0),1125 51126 ));1127 assert_noop!(1128 Unique::burn_item(origin1, CollectionId(1), TokenId(0), 5).map_err(|e| e.error),1129 CommonError::<Test>::TokenValueTooLow1130 );11311132 assert_eq!(1133 <pallet_fungible::Balance<Test>>::get((collection_id, account(1))),1134 01135 );1136 });1137}11381139#[test]1140fn burn_fungible_item_with_token_id() {1141 new_test_ext().execute_with(|| {1142 let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));11431144 let origin1 = Origin::signed(1);1145 assert_ok!(Unique::add_collection_admin(1146 origin1.clone(),1147 collection_id,1148 account(2)1149 ));11501151 let data = default_fungible_data();1152 create_test_item(collection_id, &data.into());11531154 // check balance (collection with id = 1, user id = 1)1155 assert_eq!(1156 <pallet_fungible::Balance<Test>>::get((collection_id, account(1))),1157 51158 );11591160 // Try to burn item using Token ID1161 assert_noop!(1162 Unique::burn_item(origin1, CollectionId(1), TokenId(1), 5).map_err(|e| e.error),1163 <pallet_fungible::Error::<Test>>::FungibleItemsHaveNoId1164 );1165 });1166}1167#[test]1168fn burn_refungible_item() {1169 new_test_ext().execute_with(|| {1170 let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));1171 let origin1 = Origin::signed(1);11721173 assert_ok!(Unique::set_collection_permissions(1174 origin1.clone(),1175 collection_id,1176 CollectionPermissions {1177 mint_mode: Some(true),1178 access: Some(AccessMode::AllowList),1179 nesting: None,1180 }1181 ));1182 assert_ok!(Unique::add_to_allow_list(1183 origin1.clone(),1184 collection_id,1185 account(1)1186 ));11871188 assert_ok!(Unique::add_collection_admin(1189 origin1.clone(),1190 collection_id,1191 account(2)1192 ));11931194 let data = default_re_fungible_data();1195 create_test_item(collection_id, &data.into());11961197 // check balance (collection with id = 1, user id = 2)1198 assert_eq!(1199 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),1200 11201 );1202 assert_eq!(1203 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),1204 10231205 );12061207 // burn item1208 assert_ok!(Unique::burn_item(1209 origin1.clone(),1210 collection_id,1211 TokenId(1),1212 10231213 ));1214 assert_noop!(1215 Unique::burn_item(origin1, collection_id, TokenId(1), 1023).map_err(|e| e.error),1216 CommonError::<Test>::TokenValueTooLow1217 );12181219 assert_eq!(1220 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),1221 01222 );1223 });1224}12251226#[test]1227fn add_collection_admin() {1228 new_test_ext().execute_with(|| {1229 let collection1_id =1230 create_test_collection_for_owner(&CollectionMode::NFT, 1, CollectionId(1));1231 let origin1 = Origin::signed(1);12321233 // Add collection admins1234 assert_ok!(Unique::add_collection_admin(1235 origin1.clone(),1236 collection1_id,1237 account(2)1238 ));1239 assert_ok!(Unique::add_collection_admin(1240 origin1,1241 collection1_id,1242 account(3)1243 ));12441245 // Owner is not an admin by default1246 assert_eq!(1247 <pallet_common::IsAdmin<Test>>::get((CollectionId(1), account(1))),1248 false1249 );1250 assert!(<pallet_common::IsAdmin<Test>>::get((1251 CollectionId(1),1252 account(2)1253 )));1254 assert!(<pallet_common::IsAdmin<Test>>::get((1255 CollectionId(1),1256 account(3)1257 )));1258 });1259}12601261#[test]1262fn remove_collection_admin() {1263 new_test_ext().execute_with(|| {1264 let collection1_id =1265 create_test_collection_for_owner(&CollectionMode::NFT, 1, CollectionId(1));1266 let origin1 = Origin::signed(1);1267 let origin2 = Origin::signed(2);12681269 // Add collection admins 2 and 31270 assert_ok!(Unique::add_collection_admin(1271 origin1.clone(),1272 collection1_id,1273 account(2)1274 ));1275 assert_ok!(Unique::add_collection_admin(1276 origin1,1277 collection1_id,1278 account(3)1279 ));12801281 assert!(<pallet_common::IsAdmin<Test>>::get((1282 CollectionId(1),1283 account(2)1284 )));1285 assert!(<pallet_common::IsAdmin<Test>>::get((1286 CollectionId(1),1287 account(3)1288 )));12891290 // remove admin 31291 assert_ok!(Unique::remove_collection_admin(1292 origin2,1293 CollectionId(1),1294 account(3)1295 ));12961297 // 2 is still admin, 3 is not an admin anymore1298 assert!(<pallet_common::IsAdmin<Test>>::get((1299 CollectionId(1),1300 account(2)1301 )));1302 assert_eq!(1303 <pallet_common::IsAdmin<Test>>::get((CollectionId(1), account(3))),1304 false1305 );1306 });1307}13081309#[test]1310fn balance_of() {1311 new_test_ext().execute_with(|| {1312 let nft_collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1313 let fungible_collection_id =1314 create_test_collection(&CollectionMode::Fungible(3), CollectionId(2));1315 let re_fungible_collection_id =1316 create_test_collection(&CollectionMode::ReFungible, CollectionId(3));13171318 // check balance before1319 assert_eq!(1320 <pallet_nonfungible::AccountBalance<Test>>::get((nft_collection_id, account(1))),1321 01322 );1323 assert_eq!(1324 <pallet_fungible::Balance<Test>>::get((fungible_collection_id, account(1))),1325 01326 );1327 assert_eq!(1328 <pallet_refungible::AccountBalance<Test>>::get((re_fungible_collection_id, account(1))),1329 01330 );13311332 let nft_data = default_nft_data();1333 create_test_item(nft_collection_id, &nft_data.into());13341335 let fungible_data = default_fungible_data();1336 create_test_item(fungible_collection_id, &fungible_data.into());13371338 let re_fungible_data = default_re_fungible_data();1339 create_test_item(re_fungible_collection_id, &re_fungible_data.into());13401341 // check balance (collection with id = 1, user id = 1)1342 assert_eq!(1343 <pallet_nonfungible::AccountBalance<Test>>::get((nft_collection_id, account(1))),1344 11345 );1346 assert_eq!(1347 <pallet_fungible::Balance<Test>>::get((fungible_collection_id, account(1))),1348 51349 );1350 assert_eq!(1351 <pallet_refungible::AccountBalance<Test>>::get((re_fungible_collection_id, account(1))),1352 11353 );13541355 assert_eq!(1356 <pallet_nonfungible::Owned<Test>>::get((nft_collection_id, account(1), TokenId(1))),1357 true1358 );1359 assert_eq!(1360 <pallet_refungible::Owned<Test>>::get((1361 re_fungible_collection_id,1362 account(1),1363 TokenId(1)1364 )),1365 true1366 );1367 });1368}13691370#[test]1371fn approve() {1372 new_test_ext().execute_with(|| {1373 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));13741375 let data = default_nft_data();1376 create_test_item(collection_id, &data.into());13771378 let origin1 = Origin::signed(1);13791380 // approve1381 assert_ok!(Unique::approve(1382 origin1,1383 account(2),1384 CollectionId(1),1385 TokenId(1),1386 11387 ));1388 assert_eq!(1389 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1390 account(2)1391 );1392 });1393}13941395#[test]1396fn transfer_from() {1397 new_test_ext().execute_with(|| {1398 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1399 let origin1 = Origin::signed(1);1400 let origin2 = Origin::signed(2);14011402 let data = default_nft_data();1403 create_test_item(collection_id, &data.into());14041405 // approve1406 assert_ok!(Unique::approve(1407 origin1.clone(),1408 account(2),1409 CollectionId(1),1410 TokenId(1),1411 11412 ));1413 assert_eq!(1414 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1415 account(2)1416 );14171418 assert_ok!(Unique::set_collection_permissions(1419 origin1.clone(),1420 CollectionId(1),1421 CollectionPermissions {1422 mint_mode: Some(true),1423 access: Some(AccessMode::AllowList),1424 nesting: None,1425 }1426 ));1427 assert_ok!(Unique::add_to_allow_list(1428 origin1.clone(),1429 CollectionId(1),1430 account(1)1431 ));1432 assert_ok!(Unique::add_to_allow_list(1433 origin1.clone(),1434 CollectionId(1),1435 account(2)1436 ));1437 assert_ok!(Unique::add_to_allow_list(1438 origin1,1439 CollectionId(1),1440 account(3)1441 ));14421443 assert_ok!(Unique::transfer_from(1444 origin2,1445 account(1),1446 account(2),1447 CollectionId(1),1448 TokenId(1),1449 11450 ));14511452 // after transfer1453 assert_eq!(1454 <pallet_nonfungible::AccountBalance<Test>>::get((CollectionId(1), account(1))),1455 01456 );1457 assert_eq!(1458 <pallet_nonfungible::AccountBalance<Test>>::get((CollectionId(1), account(2))),1459 11460 );1461 });1462}14631464// #endregion14651466// Coverage tests region1467// #region14681469#[test]1470fn owner_can_add_address_to_allow_list() {1471 new_test_ext().execute_with(|| {1472 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));14731474 let origin1 = Origin::signed(1);1475 assert_ok!(Unique::add_to_allow_list(1476 origin1,1477 collection_id,1478 account(2)1479 ));1480 assert!(<pallet_common::Allowlist<Test>>::get((1481 collection_id,1482 account(2)1483 )));1484 });1485}14861487#[test]1488fn admin_can_add_address_to_allow_list() {1489 new_test_ext().execute_with(|| {1490 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1491 let origin1 = Origin::signed(1);1492 let origin2 = Origin::signed(2);14931494 assert_ok!(Unique::add_collection_admin(1495 origin1,1496 collection_id,1497 account(2)1498 ));1499 assert_ok!(Unique::add_to_allow_list(1500 origin2,1501 collection_id,1502 account(3)1503 ));1504 assert!(<pallet_common::Allowlist<Test>>::get((1505 collection_id,1506 account(3)1507 )));1508 });1509}15101511#[test]1512fn nonprivileged_user_cannot_add_address_to_allow_list() {1513 new_test_ext().execute_with(|| {1514 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));15151516 let origin2 = Origin::signed(2);1517 assert_noop!(1518 Unique::add_to_allow_list(origin2, collection_id, account(3)),1519 CommonError::<Test>::NoPermission1520 );1521 });1522}15231524#[test]1525fn nobody_can_add_address_to_allow_list_of_nonexisting_collection() {1526 new_test_ext().execute_with(|| {1527 let origin1 = Origin::signed(1);15281529 assert_noop!(1530 Unique::add_to_allow_list(origin1, CollectionId(1), account(2)),1531 CommonError::<Test>::CollectionNotFound1532 );1533 });1534}15351536#[test]1537fn nobody_can_add_address_to_allow_list_of_deleted_collection() {1538 new_test_ext().execute_with(|| {1539 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));15401541 let origin1 = Origin::signed(1);1542 assert_ok!(Unique::destroy_collection(origin1.clone(), collection_id));1543 assert_noop!(1544 Unique::add_to_allow_list(origin1, collection_id, account(2)),1545 CommonError::<Test>::CollectionNotFound1546 );1547 });1548}15491550// If address is already added to allow list, nothing happens1551#[test]1552fn address_is_already_added_to_allow_list() {1553 new_test_ext().execute_with(|| {1554 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1555 let origin1 = Origin::signed(1);15561557 assert_ok!(Unique::add_to_allow_list(1558 origin1.clone(),1559 collection_id,1560 account(2)1561 ));1562 assert_ok!(Unique::add_to_allow_list(1563 origin1,1564 collection_id,1565 account(2)1566 ));1567 assert!(<pallet_common::Allowlist<Test>>::get((1568 collection_id,1569 account(2)1570 )));1571 });1572}15731574#[test]1575fn owner_can_remove_address_from_allow_list() {1576 new_test_ext().execute_with(|| {1577 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));15781579 let origin1 = Origin::signed(1);1580 assert_ok!(Unique::add_to_allow_list(1581 origin1.clone(),1582 collection_id,1583 account(2)1584 ));1585 assert_ok!(Unique::remove_from_allow_list(1586 origin1,1587 collection_id,1588 account(2)1589 ));1590 assert_eq!(1591 <pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1592 false1593 );1594 });1595}15961597#[test]1598fn admin_can_remove_address_from_allow_list() {1599 new_test_ext().execute_with(|| {1600 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1601 let origin1 = Origin::signed(1);1602 let origin2 = Origin::signed(2);16031604 // Owner adds admin1605 assert_ok!(Unique::add_collection_admin(1606 origin1.clone(),1607 collection_id,1608 account(2)1609 ));16101611 // Owner adds address 3 to allow list1612 assert_ok!(Unique::add_to_allow_list(1613 origin1,1614 collection_id,1615 account(3)1616 ));16171618 // Admin removes address 3 from allow list1619 assert_ok!(Unique::remove_from_allow_list(1620 origin2,1621 collection_id,1622 account(3)1623 ));1624 assert_eq!(1625 <pallet_common::Allowlist<Test>>::get((collection_id, account(3))),1626 false1627 );1628 });1629}16301631#[test]1632fn nonprivileged_user_cannot_remove_address_from_allow_list() {1633 new_test_ext().execute_with(|| {1634 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1635 let origin1 = Origin::signed(1);1636 let origin2 = Origin::signed(2);16371638 assert_ok!(Unique::add_to_allow_list(1639 origin1,1640 collection_id,1641 account(2)1642 ));1643 assert_noop!(1644 Unique::remove_from_allow_list(origin2, collection_id, account(2)),1645 CommonError::<Test>::NoPermission1646 );1647 assert!(<pallet_common::Allowlist<Test>>::get((1648 collection_id,1649 account(2)1650 )));1651 });1652}16531654#[test]1655fn nobody_can_remove_address_from_allow_list_of_nonexisting_collection() {1656 new_test_ext().execute_with(|| {1657 let origin1 = Origin::signed(1);16581659 assert_noop!(1660 Unique::remove_from_allow_list(origin1, CollectionId(1), account(2)),1661 CommonError::<Test>::CollectionNotFound1662 );1663 });1664}16651666#[test]1667fn nobody_can_remove_address_from_allow_list_of_deleted_collection() {1668 new_test_ext().execute_with(|| {1669 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1670 let origin1 = Origin::signed(1);1671 let origin2 = Origin::signed(2);16721673 // Add account 2 to allow list1674 assert_ok!(Unique::add_to_allow_list(1675 origin1.clone(),1676 collection_id,1677 account(2)1678 ));16791680 // Account 2 is in collection allow-list1681 assert!(<pallet_common::Allowlist<Test>>::get((1682 collection_id,1683 account(2)1684 )));16851686 // Destroy collection1687 assert_ok!(Unique::destroy_collection(origin1, collection_id));16881689 // Attempt to remove account 2 from collection allow-list => error1690 assert_noop!(1691 Unique::remove_from_allow_list(origin2, collection_id, account(2)),1692 CommonError::<Test>::CollectionNotFound1693 );16941695 // Account 2 is not found in collection allow-list anyway1696 assert_eq!(1697 <pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1698 false1699 );1700 });1701}17021703// If address is already removed from allow list, nothing happens1704#[test]1705fn address_is_already_removed_from_allow_list() {1706 new_test_ext().execute_with(|| {1707 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1708 let origin1 = Origin::signed(1);17091710 assert_ok!(Unique::add_to_allow_list(1711 origin1.clone(),1712 collection_id,1713 account(2)1714 ));1715 assert_ok!(Unique::remove_from_allow_list(1716 origin1.clone(),1717 collection_id,1718 account(2)1719 ));1720 assert_eq!(1721 <pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1722 false1723 );1724 assert_ok!(Unique::remove_from_allow_list(1725 origin1,1726 collection_id,1727 account(2)1728 ));1729 assert_eq!(1730 <pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1731 false1732 );1733 });1734}17351736// If Public Access mode is set to AllowList, tokens can’t be transferred from a non-allowlisted address with transfer or transferFrom (2 tests)1737#[test]1738fn allow_list_test_1() {1739 new_test_ext().execute_with(|| {1740 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));17411742 let origin1 = Origin::signed(1);17431744 let data = default_nft_data();1745 create_test_item(collection_id, &data.into());17461747 assert_ok!(Unique::set_collection_permissions(1748 origin1.clone(),1749 collection_id,1750 CollectionPermissions {1751 mint_mode: None,1752 access: Some(AccessMode::AllowList),1753 nesting: None,1754 }1755 ));1756 assert_ok!(Unique::add_to_allow_list(1757 origin1.clone(),1758 collection_id,1759 account(2)1760 ));17611762 assert_noop!(1763 Unique::transfer(origin1, account(3), CollectionId(1), TokenId(1), 1)1764 .map_err(|e| e.error),1765 CommonError::<Test>::AddressNotInAllowlist1766 );1767 });1768}17691770#[test]1771fn allow_list_test_2() {1772 new_test_ext().execute_with(|| {1773 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1774 let origin1 = Origin::signed(1);17751776 let data = default_nft_data();1777 create_test_item(collection_id, &data.into());17781779 assert_ok!(Unique::set_collection_permissions(1780 origin1.clone(),1781 collection_id,1782 CollectionPermissions {1783 mint_mode: None,1784 access: Some(AccessMode::AllowList),1785 nesting: None,1786 }1787 ));1788 assert_ok!(Unique::add_to_allow_list(1789 origin1.clone(),1790 collection_id,1791 account(1)1792 ));1793 assert_ok!(Unique::add_to_allow_list(1794 origin1.clone(),1795 collection_id,1796 account(2)1797 ));17981799 // do approve1800 assert_ok!(Unique::approve(1801 origin1.clone(),1802 account(1),1803 collection_id,1804 TokenId(1),1805 11806 ));1807 assert_eq!(1808 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1809 account(1)1810 );18111812 assert_ok!(Unique::remove_from_allow_list(1813 origin1.clone(),1814 collection_id,1815 account(1)1816 ));18171818 assert_noop!(1819 Unique::transfer_from(1820 origin1,1821 account(1),1822 account(3),1823 CollectionId(1),1824 TokenId(1),1825 11826 )1827 .map_err(|e| e.error),1828 CommonError::<Test>::AddressNotInAllowlist1829 );1830 });1831}18321833// If Public Access mode is set to AllowList, tokens can’t be transferred to a non-allowlisted address with transfer or transferFrom (2 tests)1834#[test]1835fn allow_list_test_3() {1836 new_test_ext().execute_with(|| {1837 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));18381839 let origin1 = Origin::signed(1);18401841 let data = default_nft_data();1842 create_test_item(collection_id, &data.into());18431844 assert_ok!(Unique::set_collection_permissions(1845 origin1.clone(),1846 collection_id,1847 CollectionPermissions {1848 mint_mode: None,1849 access: Some(AccessMode::AllowList),1850 nesting: None,1851 }1852 ));1853 assert_ok!(Unique::add_to_allow_list(1854 origin1.clone(),1855 collection_id,1856 account(1)1857 ));18581859 assert_noop!(1860 Unique::transfer(origin1, account(3), collection_id, TokenId(1), 1)1861 .map_err(|e| e.error),1862 CommonError::<Test>::AddressNotInAllowlist1863 );1864 });1865}18661867#[test]1868fn allow_list_test_4() {1869 new_test_ext().execute_with(|| {1870 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));18711872 let origin1 = Origin::signed(1);18731874 let data = default_nft_data();1875 create_test_item(collection_id, &data.into());18761877 assert_ok!(Unique::set_collection_permissions(1878 origin1.clone(),1879 collection_id,1880 CollectionPermissions {1881 mint_mode: None,1882 access: Some(AccessMode::AllowList),1883 nesting: None,1884 }1885 ));1886 assert_ok!(Unique::add_to_allow_list(1887 origin1.clone(),1888 collection_id,1889 account(1)1890 ));1891 assert_ok!(Unique::add_to_allow_list(1892 origin1.clone(),1893 collection_id,1894 account(2)1895 ));18961897 // do approve1898 assert_ok!(Unique::approve(1899 origin1.clone(),1900 account(1),1901 collection_id,1902 TokenId(1),1903 11904 ));1905 assert_eq!(1906 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1907 account(1)1908 );19091910 assert_ok!(Unique::remove_from_allow_list(1911 origin1.clone(),1912 collection_id,1913 account(2)1914 ));19151916 assert_noop!(1917 Unique::transfer_from(1918 origin1,1919 account(1),1920 account(3),1921 collection_id,1922 TokenId(1),1923 11924 )1925 .map_err(|e| e.error),1926 CommonError::<Test>::AddressNotInAllowlist1927 );1928 });1929}19301931// If Public Access mode is set to AllowList, tokens can’t be destroyed by a non-allowlisted address (even if it owned them before enabling AllowList mode)1932#[test]1933fn allow_list_test_5() {1934 new_test_ext().execute_with(|| {1935 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));19361937 let origin1 = Origin::signed(1);19381939 let data = default_nft_data();1940 create_test_item(collection_id, &data.into());19411942 assert_ok!(Unique::set_collection_permissions(1943 origin1.clone(),1944 collection_id,1945 CollectionPermissions {1946 mint_mode: None,1947 access: Some(AccessMode::AllowList),1948 nesting: None,1949 }1950 ));1951 assert_noop!(1952 Unique::burn_item(origin1.clone(), CollectionId(1), TokenId(1), 1).map_err(|e| e.error),1953 CommonError::<Test>::AddressNotInAllowlist1954 );1955 });1956}19571958// If Public Access mode is set to AllowList, token transfers can’t be Approved by a non-allowlisted address (see Approve method).1959#[test]1960fn allow_list_test_6() {1961 new_test_ext().execute_with(|| {1962 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));19631964 let origin1 = Origin::signed(1);19651966 let data = default_nft_data();1967 create_test_item(collection_id, &data.into());19681969 assert_ok!(Unique::set_collection_permissions(1970 origin1.clone(),1971 collection_id,1972 CollectionPermissions {1973 mint_mode: None,1974 access: Some(AccessMode::AllowList),1975 nesting: None,1976 }1977 ));19781979 // do approve1980 assert_noop!(1981 Unique::approve(origin1, account(1), CollectionId(1), TokenId(1), 1)1982 .map_err(|e| e.error),1983 CommonError::<Test>::AddressNotInAllowlist1984 );1985 });1986}19871988// If Public Access mode is set to AllowList, tokens can be transferred from a allowlisted address with transfer or transferFrom (2 tests) and1989// tokens can be transferred from a allowlisted address with transfer or transferFrom (2 tests)1990#[test]1991fn allow_list_test_7() {1992 new_test_ext().execute_with(|| {1993 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));19941995 let data = default_nft_data();1996 create_test_item(collection_id, &data.into());19971998 let origin1 = Origin::signed(1);19992000 assert_ok!(Unique::set_collection_permissions(2001 origin1.clone(),2002 collection_id,2003 CollectionPermissions {2004 mint_mode: None,2005 access: Some(AccessMode::AllowList),2006 nesting: None,2007 }2008 ));2009 assert_ok!(Unique::add_to_allow_list(2010 origin1.clone(),2011 collection_id,2012 account(1)2013 ));2014 assert_ok!(Unique::add_to_allow_list(2015 origin1.clone(),2016 collection_id,2017 account(2)2018 ));20192020 assert_ok!(Unique::transfer(2021 origin1,2022 account(2),2023 CollectionId(1),2024 TokenId(1),2025 12026 ));2027 });2028}20292030#[test]2031fn allow_list_test_8() {2032 new_test_ext().execute_with(|| {2033 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));20342035 // Create NFT for account 12036 let data = default_nft_data();2037 create_test_item(collection_id, &data.into());20382039 let origin1 = Origin::signed(1);20402041 // Toggle Allow List mode and add accounts 1 and 22042 assert_ok!(Unique::set_collection_permissions(2043 origin1.clone(),2044 collection_id,2045 CollectionPermissions {2046 mint_mode: None,2047 access: Some(AccessMode::AllowList),2048 nesting: None,2049 }2050 ));2051 assert_ok!(Unique::add_to_allow_list(2052 origin1.clone(),2053 collection_id,2054 account(1)2055 ));2056 assert_ok!(Unique::add_to_allow_list(2057 origin1.clone(),2058 collection_id,2059 account(2)2060 ));20612062 // Sself-approve account 1 for NFT 12063 assert_ok!(Unique::approve(2064 origin1.clone(),2065 account(1),2066 CollectionId(1),2067 TokenId(1),2068 12069 ));2070 assert_eq!(2071 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),2072 account(1)2073 );20742075 // Transfer from 1 to 22076 assert_ok!(Unique::transfer_from(2077 origin1,2078 account(1),2079 account(2),2080 CollectionId(1),2081 TokenId(1),2082 12083 ));2084 });2085}20862087// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by owner.2088#[test]2089fn allow_list_test_9() {2090 new_test_ext().execute_with(|| {2091 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));2092 let origin1 = Origin::signed(1);20932094 assert_ok!(Unique::set_collection_permissions(2095 origin1.clone(),2096 collection_id,2097 CollectionPermissions {2098 mint_mode: Some(false),2099 access: Some(AccessMode::AllowList),2100 nesting: None,2101 }2102 ));21032104 let data = default_nft_data();2105 create_test_item(collection_id, &data.into());2106 });2107}21082109// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by admin.2110#[test]2111fn allow_list_test_10() {2112 new_test_ext().execute_with(|| {2113 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));21142115 let origin1 = Origin::signed(1);2116 let origin2 = Origin::signed(2);21172118 assert_ok!(Unique::set_collection_permissions(2119 origin1.clone(),2120 collection_id,2121 CollectionPermissions {2122 mint_mode: Some(false),2123 access: Some(AccessMode::AllowList),2124 nesting: None,2125 }2126 ));21272128 assert_ok!(Unique::add_collection_admin(2129 origin1,2130 collection_id,2131 account(2)2132 ));21332134 assert_ok!(Unique::create_item(2135 origin2,2136 collection_id,2137 account(2),2138 default_nft_data().into()2139 ));2140 });2141}21422143// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens cannot be created by non-privileged and allow listed address.2144#[test]2145fn allow_list_test_11() {2146 new_test_ext().execute_with(|| {2147 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));21482149 let origin1 = Origin::signed(1);2150 let origin2 = Origin::signed(2);21512152 assert_ok!(Unique::set_collection_permissions(2153 origin1.clone(),2154 collection_id,2155 CollectionPermissions {2156 mint_mode: Some(false),2157 access: Some(AccessMode::AllowList),2158 nesting: None,2159 }2160 ));2161 assert_ok!(Unique::add_to_allow_list(2162 origin1,2163 collection_id,2164 account(2)2165 ));21662167 assert_noop!(2168 Unique::create_item(2169 origin2,2170 CollectionId(1),2171 account(2),2172 default_nft_data().into()2173 )2174 .map_err(|e| e.error),2175 CommonError::<Test>::PublicMintingNotAllowed2176 );2177 });2178}21792180// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens cannot be created by non-privileged and non-allow listed address.2181#[test]2182fn allow_list_test_12() {2183 new_test_ext().execute_with(|| {2184 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));21852186 let origin1 = Origin::signed(1);2187 let origin2 = Origin::signed(2);21882189 assert_ok!(Unique::set_collection_permissions(2190 origin1.clone(),2191 collection_id,2192 CollectionPermissions {2193 mint_mode: Some(false),2194 access: Some(AccessMode::AllowList),2195 nesting: None,2196 }2197 ));21982199 assert_noop!(2200 Unique::create_item(2201 origin2,2202 CollectionId(1),2203 account(2),2204 default_nft_data().into()2205 )2206 .map_err(|e| e.error),2207 CommonError::<Test>::PublicMintingNotAllowed2208 );2209 });2210}22112212// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by owner.2213#[test]2214fn allow_list_test_13() {2215 new_test_ext().execute_with(|| {2216 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));22172218 let origin1 = Origin::signed(1);22192220 assert_ok!(Unique::set_collection_permissions(2221 origin1.clone(),2222 collection_id,2223 CollectionPermissions {2224 mint_mode: Some(true),2225 access: Some(AccessMode::AllowList),2226 nesting: None,2227 }2228 ));22292230 let data = default_nft_data();2231 create_test_item(collection_id, &data.into());2232 });2233}22342235// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by admin.2236#[test]2237fn allow_list_test_14() {2238 new_test_ext().execute_with(|| {2239 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));22402241 let origin1 = Origin::signed(1);2242 let origin2 = Origin::signed(2);22432244 assert_ok!(Unique::set_collection_permissions(2245 origin1.clone(),2246 collection_id,2247 CollectionPermissions {2248 mint_mode: Some(true),2249 access: Some(AccessMode::AllowList),2250 nesting: None,2251 }2252 ));22532254 assert_ok!(Unique::add_collection_admin(2255 origin1,2256 collection_id,2257 account(2)2258 ));22592260 assert_ok!(Unique::create_item(2261 origin2,2262 collection_id,2263 account(2),2264 default_nft_data().into()2265 ));2266 });2267}22682269// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens cannot be created by non-privileged and non-allow listed address.2270#[test]2271fn allow_list_test_15() {2272 new_test_ext().execute_with(|| {2273 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));22742275 let origin1 = Origin::signed(1);2276 let origin2 = Origin::signed(2);22772278 assert_ok!(Unique::set_collection_permissions(2279 origin1.clone(),2280 collection_id,2281 CollectionPermissions {2282 mint_mode: Some(true),2283 access: Some(AccessMode::AllowList),2284 nesting: None,2285 }2286 ));22872288 assert_noop!(2289 Unique::create_item(2290 origin2,2291 collection_id,2292 account(2),2293 default_nft_data().into()2294 )2295 .map_err(|e| e.error),2296 CommonError::<Test>::AddressNotInAllowlist2297 );2298 });2299}23002301// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by non-privileged and allow listed address.2302#[test]2303fn allow_list_test_16() {2304 new_test_ext().execute_with(|| {2305 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));23062307 let origin1 = Origin::signed(1);2308 let origin2 = Origin::signed(2);23092310 assert_ok!(Unique::set_collection_permissions(2311 origin1.clone(),2312 collection_id,2313 CollectionPermissions {2314 mint_mode: Some(true),2315 access: Some(AccessMode::AllowList),2316 nesting: None,2317 }2318 ));2319 assert_ok!(Unique::add_to_allow_list(2320 origin1,2321 collection_id,2322 account(2)2323 ));23242325 assert_ok!(Unique::create_item(2326 origin2,2327 collection_id,2328 account(2),2329 default_nft_data().into()2330 ));2331 });2332}23332334// Total number of collections. Positive test2335#[test]2336fn total_number_collections_bound() {2337 new_test_ext().execute_with(|| {2338 create_test_collection(&CollectionMode::NFT, CollectionId(1));2339 });2340}23412342#[test]2343fn create_max_collections() {2344 new_test_ext().execute_with(|| {2345 for i in 1..COLLECTION_NUMBER_LIMIT {2346 create_test_collection(&CollectionMode::NFT, CollectionId(i));2347 }2348 });2349}23502351// Total number of collections. Negative test2352#[test]2353fn total_number_collections_bound_neg() {2354 new_test_ext().execute_with(|| {2355 let origin1 = Origin::signed(1);23562357 for i in 1..=COLLECTION_NUMBER_LIMIT {2358 create_test_collection(&CollectionMode::NFT, CollectionId(i));2359 }23602361 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();2362 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();2363 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();23642365 let data: CreateCollectionData<u64> = CreateCollectionData {2366 name: col_name1.try_into().unwrap(),2367 description: col_desc1.try_into().unwrap(),2368 token_prefix: token_prefix1.try_into().unwrap(),2369 mode: CollectionMode::NFT,2370 ..Default::default()2371 };23722373 // 11-th collection in chain. Expects error2374 assert_noop!(2375 Unique::create_collection_ex(origin1, data),2376 CommonError::<Test>::TotalCollectionsLimitExceeded2377 );2378 });2379}23802381// Owned tokens by a single address. Positive test2382#[test]2383fn owned_tokens_bound() {2384 new_test_ext().execute_with(|| {2385 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));23862387 let data = default_nft_data();2388 create_test_item(collection_id, &data.clone().into());2389 create_test_item(collection_id, &data.into());2390 });2391}23922393// Owned tokens by a single address. Negotive test2394#[test]2395fn owned_tokens_bound_neg() {2396 new_test_ext().execute_with(|| {2397 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));23982399 let origin1 = Origin::signed(1);24002401 for _ in 1..=MAX_TOKEN_OWNERSHIP {2402 let data = default_nft_data();2403 create_test_item(collection_id, &data.clone().into());2404 }24052406 let data = default_nft_data();2407 assert_noop!(2408 Unique::create_item(origin1, CollectionId(1), account(1), data.into())2409 .map_err(|e| e.error),2410 CommonError::<Test>::AccountTokenLimitExceeded2411 );2412 });2413}24142415// Number of collection admins. Positive test2416#[test]2417fn collection_admins_bound() {2418 new_test_ext().execute_with(|| {2419 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));24202421 let origin1 = Origin::signed(1);24222423 assert_ok!(Unique::add_collection_admin(2424 origin1.clone(),2425 collection_id,2426 account(2)2427 ));2428 assert_ok!(Unique::add_collection_admin(2429 origin1,2430 collection_id,2431 account(3)2432 ));2433 });2434}24352436// Number of collection admins. Negotive test2437#[test]2438fn collection_admins_bound_neg() {2439 new_test_ext().execute_with(|| {2440 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));24412442 let origin1 = Origin::signed(1);24432444 for i in 0..COLLECTION_ADMINS_LIMIT {2445 assert_ok!(Unique::add_collection_admin(2446 origin1.clone(),2447 collection_id,2448 account((2 + i).into())2449 ));2450 }2451 assert_noop!(2452 Unique::add_collection_admin(2453 origin1,2454 collection_id,2455 account((3 + COLLECTION_ADMINS_LIMIT).into())2456 ),2457 CommonError::<Test>::CollectionAdminCountExceeded2458 );2459 });2460}2461// #endregion24622463#[test]2464fn collection_transfer_flag_works() {2465 new_test_ext().execute_with(|| {2466 let origin1 = Origin::signed(1);24672468 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));2469 assert_ok!(Unique::set_transfers_enabled_flag(2470 origin1,2471 collection_id,2472 true2473 ));24742475 let data = default_nft_data();2476 create_test_item(collection_id, &data.into());2477 assert_eq!(2478 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2479 12480 );2481 assert_eq!(2482 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2483 true2484 );24852486 let origin1 = Origin::signed(1);24872488 // default scenario2489 assert_ok!(Unique::transfer(2490 origin1,2491 account(2),2492 collection_id,2493 TokenId(1),2494 12495 ));2496 assert_eq!(2497 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2498 false2499 );2500 assert_eq!(2501 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),2502 true2503 );2504 assert_eq!(2505 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2506 02507 );2508 assert_eq!(2509 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),2510 12511 );2512 });2513}25142515#[test]2516fn collection_transfer_flag_works_neg() {2517 new_test_ext().execute_with(|| {2518 let origin1 = Origin::signed(1);25192520 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));2521 assert_ok!(Unique::set_transfers_enabled_flag(2522 origin1,2523 collection_id,2524 false2525 ));25262527 let data = default_nft_data();2528 create_test_item(collection_id, &data.into());2529 assert_eq!(2530 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2531 12532 );2533 assert_eq!(2534 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2535 true2536 );25372538 let origin1 = Origin::signed(1);25392540 // default scenario2541 assert_noop!(2542 Unique::transfer(origin1, account(2), CollectionId(1), TokenId(1), 1)2543 .map_err(|e| e.error),2544 CommonError::<Test>::TransferNotAllowed2545 );2546 assert_eq!(2547 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2548 12549 );2550 assert_eq!(2551 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),2552 02553 );2554 assert_eq!(2555 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2556 true2557 );2558 assert_eq!(2559 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),2560 false2561 );2562 });2563}25642565#[test]2566fn collection_sponsoring() {2567 new_test_ext().execute_with(|| {2568 // default_limits();2569 let user1 = 1_u64;2570 let user2 = 777_u64;2571 let origin1 = Origin::signed(user1);2572 let origin2 = Origin::signed(user2);2573 let account2 = account(user2);25742575 let collection_id =2576 create_test_collection_for_owner(&CollectionMode::NFT, user1, CollectionId(1));2577 assert_ok!(Unique::set_collection_sponsor(2578 origin1.clone(),2579 collection_id,2580 user12581 ));2582 assert_ok!(Unique::confirm_sponsorship(origin1.clone(), collection_id));25832584 // Expect error while have no permissions2585 assert!(Unique::create_item(2586 origin2.clone(),2587 collection_id,2588 account2.clone(),2589 default_nft_data().into()2590 )2591 .is_err());25922593 assert_ok!(Unique::set_collection_permissions(2594 origin1.clone(),2595 collection_id,2596 CollectionPermissions {2597 mint_mode: Some(true),2598 access: Some(AccessMode::AllowList),2599 nesting: None,2600 }2601 ));2602 assert_ok!(Unique::add_to_allow_list(2603 origin1.clone(),2604 collection_id,2605 account2.clone()2606 ));26072608 assert_ok!(Unique::create_item(2609 origin2,2610 collection_id,2611 account2,2612 default_nft_data().into()2613 ));2614 });2615}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// Tests to be written here18use crate::{Test, TestCrossAccountId, CollectionCreationPrice, Origin, Unique, new_test_ext};19use up_data_structs::{20 COLLECTION_NUMBER_LIMIT, CollectionId, CreateItemData, CreateFungibleData, CreateNftData,21 CreateReFungibleData, MAX_DECIMAL_POINTS, COLLECTION_ADMINS_LIMIT, TokenId,22 MAX_TOKEN_OWNERSHIP, CreateCollectionData, CollectionMode, AccessMode, CollectionPermissions,23 PropertyKeyPermission, PropertyPermission, Property, CollectionPropertiesVec,24 CollectionPropertiesPermissionsVec, TokenChild,25};26use frame_support::{assert_noop, assert_ok, assert_err};27use sp_std::convert::TryInto;28use pallet_evm::account::CrossAccountId;29use pallet_common::Error as CommonError;30use pallet_unique::Error as UniqueError;3132fn add_balance(user: u64, value: u64) {33 const DONOR_USER: u64 = 999;34 assert_ok!(<pallet_balances::Pallet<Test>>::set_balance(35 Origin::root(),36 DONOR_USER,37 value,38 039 ));40 assert_ok!(<pallet_balances::Pallet<Test>>::force_transfer(41 Origin::root(),42 DONOR_USER,43 user,44 value45 ));46}4748fn default_nft_data() -> CreateNftData {49 CreateNftData {50 properties: vec![Property {51 key: b"test-prop".to_vec().try_into().unwrap(),52 value: b"test-nft-prop".to_vec().try_into().unwrap(),53 }]54 .try_into()55 .unwrap(),56 }57}5859fn default_fungible_data() -> CreateFungibleData {60 CreateFungibleData { value: 5 }61}6263fn default_re_fungible_data() -> CreateReFungibleData {64 CreateReFungibleData {65 const_data: vec![1, 2, 3].try_into().unwrap(),66 pieces: 1023,67 }68}6970fn create_test_collection_for_owner(71 mode: &CollectionMode,72 owner: u64,73 id: CollectionId,74) -> CollectionId {75 add_balance(owner, CollectionCreationPrice::get() as u64 + 1);7677 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();78 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();79 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();80 let token_property_permissions: CollectionPropertiesPermissionsVec =81 vec![PropertyKeyPermission {82 key: b"test-prop".to_vec().try_into().unwrap(),83 permission: PropertyPermission {84 mutable: true,85 collection_admin: false,86 token_owner: true,87 },88 }]89 .try_into()90 .unwrap();91 let properties: CollectionPropertiesVec = vec![Property {92 key: b"test-collection-prop".to_vec().try_into().unwrap(),93 value: b"test-collection-value".to_vec().try_into().unwrap(),94 }]95 .try_into()96 .unwrap();9798 let data: CreateCollectionData<u64> = CreateCollectionData {99 name: col_name1.try_into().unwrap(),100 description: col_desc1.try_into().unwrap(),101 token_prefix: token_prefix1.try_into().unwrap(),102 mode: mode.clone(),103 token_property_permissions: token_property_permissions.clone(),104 properties: properties.clone(),105 ..Default::default()106 };107108 let origin1 = Origin::signed(owner);109 assert_ok!(Unique::create_collection_ex(origin1, data));110111 let saved_col_name: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();112 let saved_description: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();113 let saved_prefix: Vec<u8> = b"token_prefix1\0".to_vec();114 assert_eq!(115 <pallet_common::CollectionById<Test>>::get(id)116 .unwrap()117 .owner,118 owner119 );120 assert_eq!(121 <pallet_common::CollectionById<Test>>::get(id).unwrap().name,122 saved_col_name123 );124 assert_eq!(125 <pallet_common::CollectionById<Test>>::get(id).unwrap().mode,126 *mode127 );128 assert_eq!(129 <pallet_common::CollectionById<Test>>::get(id)130 .unwrap()131 .description,132 saved_description133 );134 assert_eq!(135 <pallet_common::CollectionById<Test>>::get(id)136 .unwrap()137 .token_prefix,138 saved_prefix139 );140 assert_eq!(141 get_collection_property_permissions(id).as_slice(),142 token_property_permissions.as_slice()143 );144 assert_eq!(145 get_collection_properties(id).as_slice(),146 properties.as_slice()147 );148 id149}150151fn get_collection_property_permissions(collection_id: CollectionId) -> Vec<PropertyKeyPermission> {152 <pallet_common::Pallet<Test>>::property_permissions(collection_id)153 .into_iter()154 .map(|(key, permission)| PropertyKeyPermission { key, permission })155 .collect()156}157158fn get_collection_properties(collection_id: CollectionId) -> Vec<Property> {159 <pallet_common::Pallet<Test>>::collection_properties(collection_id)160 .into_iter()161 .map(|(key, value)| Property { key, value })162 .collect()163}164165fn get_token_properties(collection_id: CollectionId, token_id: TokenId) -> Vec<Property> {166 <pallet_nonfungible::Pallet<Test>>::token_properties((collection_id, token_id))167 .into_iter()168 .map(|(key, value)| Property { key, value })169 .collect()170}171172fn create_test_collection(mode: &CollectionMode, id: CollectionId) -> CollectionId {173 create_test_collection_for_owner(&mode, 1, id)174}175176fn create_test_item(collection_id: CollectionId, data: &CreateItemData) {177 let origin1 = Origin::signed(1);178 assert_ok!(Unique::create_item(179 origin1,180 collection_id,181 account(1),182 data.clone()183 ));184}185186fn account(sub: u64) -> TestCrossAccountId {187 TestCrossAccountId::from_sub(sub)188}189190// Use cases tests region191// #region192193#[test]194fn check_not_sufficient_founds() {195 new_test_ext().execute_with(|| {196 let acc: u64 = 1;197 <pallet_balances::Pallet<Test>>::set_balance(Origin::root(), acc, 0, 0).unwrap();198199 let name: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();200 let description: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();201 let token_prefix: Vec<u8> = b"token_prefix1\0".to_vec();202203 let data: CreateCollectionData<<Test as frame_system::Config>::AccountId> =204 CreateCollectionData {205 name: name.try_into().unwrap(),206 description: description.try_into().unwrap(),207 token_prefix: token_prefix.try_into().unwrap(),208 mode: CollectionMode::NFT,209 ..Default::default()210 };211212 let result = Unique::create_collection_ex(Origin::signed(acc), data);213 assert_err!(result, <CommonError<Test>>::NotSufficientFounds);214 });215}216217#[test]218fn create_fungible_collection_fails_with_large_decimal_numbers() {219 new_test_ext().execute_with(|| {220 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();221 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();222 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();223224 let data: CreateCollectionData<u64> = CreateCollectionData {225 name: col_name1.try_into().unwrap(),226 description: col_desc1.try_into().unwrap(),227 token_prefix: token_prefix1.try_into().unwrap(),228 mode: CollectionMode::Fungible(MAX_DECIMAL_POINTS + 1),229 ..Default::default()230 };231232 let origin1 = Origin::signed(1);233 assert_noop!(234 Unique::create_collection_ex(origin1, data),235 UniqueError::<Test>::CollectionDecimalPointLimitExceeded236 );237 });238}239240#[test]241fn create_nft_item() {242 new_test_ext().execute_with(|| {243 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));244245 let data = default_nft_data();246 create_test_item(collection_id, &data.clone().into());247248 assert_eq!(249 get_token_properties(collection_id, TokenId(1)).as_slice(),250 data.properties.as_slice(),251 );252 });253}254255// Use cases tests region256// #region257#[test]258fn create_nft_multiple_items() {259 new_test_ext().execute_with(|| {260 create_test_collection(&CollectionMode::NFT, CollectionId(1));261262 let origin1 = Origin::signed(1);263264 let items_data = vec![default_nft_data(), default_nft_data(), default_nft_data()];265266 assert_ok!(Unique::create_multiple_items(267 origin1,268 CollectionId(1),269 account(1),270 items_data271 .clone()272 .into_iter()273 .map(|d| { d.into() })274 .collect()275 ));276 for (index, data) in items_data.into_iter().enumerate() {277 assert_eq!(278 get_token_properties(CollectionId(1), TokenId(index as u32 + 1)).as_slice(),279 data.properties.as_slice()280 );281 }282 });283}284285#[test]286fn create_refungible_item() {287 new_test_ext().execute_with(|| {288 let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));289290 let data = default_re_fungible_data();291 create_test_item(collection_id, &data.clone().into());292 let item = <pallet_refungible::TokenData<Test>>::get((collection_id, TokenId(1)));293 let balance =294 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1)));295 assert_eq!(item.const_data, data.const_data.into_inner());296 assert_eq!(balance, 1023);297 });298}299300#[test]301fn create_multiple_refungible_items() {302 new_test_ext().execute_with(|| {303 create_test_collection(&CollectionMode::ReFungible, CollectionId(1));304305 let origin1 = Origin::signed(1);306307 let items_data = vec![308 default_re_fungible_data(),309 default_re_fungible_data(),310 default_re_fungible_data(),311 ];312313 assert_ok!(Unique::create_multiple_items(314 origin1,315 CollectionId(1),316 account(1),317 items_data318 .clone()319 .into_iter()320 .map(|d| { d.into() })321 .collect()322 ));323 for (index, data) in items_data.into_iter().enumerate() {324 let item = <pallet_refungible::TokenData<Test>>::get((325 CollectionId(1),326 TokenId((index + 1) as u32),327 ));328 let balance =329 <pallet_refungible::Balance<Test>>::get((CollectionId(1), TokenId(1), account(1)));330 assert_eq!(item.const_data.to_vec(), data.const_data.into_inner());331 assert_eq!(balance, 1023);332 }333 });334}335336#[test]337fn create_fungible_item() {338 new_test_ext().execute_with(|| {339 let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));340341 let data = default_fungible_data();342 create_test_item(collection_id, &data.into());343344 assert_eq!(345 <pallet_fungible::Balance<Test>>::get((collection_id, account(1))),346 5347 );348 });349}350351//#[test]352// fn create_multiple_fungible_items() {353// new_test_ext().execute_with(|| {354// default_limits();355356// create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));357358// let origin1 = Origin::signed(1);359360// let items_data = vec![default_fungible_data(), default_fungible_data(), default_fungible_data()];361362// assert_ok!(Unique::create_multiple_items(363// origin1.clone(),364// 1,365// 1,366// items_data.clone().into_iter().map(|d| { d.into() }).collect()367// ));368369// for (index, _) in items_data.iter().enumerate() {370// assert_eq!(Unique::fungible_item_id(1, (index + 1) as TokenId).value, 5);371// }372// assert_eq!(Unique::balance_count(1, 1), 3000);373// assert_eq!(Unique::address_tokens(1, 1), [1, 2, 3]);374// });375// }376377#[test]378fn transfer_fungible_item() {379 new_test_ext().execute_with(|| {380 let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));381382 let origin1 = Origin::signed(1);383 let origin2 = Origin::signed(2);384385 let data = default_fungible_data();386 create_test_item(collection_id, &data.into());387388 assert_eq!(389 <pallet_fungible::Balance<Test>>::get((CollectionId(1), account(1))),390 5391 );392393 // change owner scenario394 assert_ok!(Unique::transfer(395 origin1,396 account(2),397 CollectionId(1),398 TokenId(0),399 5400 ));401 assert_eq!(402 <pallet_fungible::Balance<Test>>::get((CollectionId(1), account(1))),403 0404 );405406 // split item scenario407 assert_ok!(Unique::transfer(408 origin2.clone(),409 account(3),410 CollectionId(1),411 TokenId(0),412 3413 ));414415 // split item and new owner has account scenario416 assert_ok!(Unique::transfer(417 origin2,418 account(3),419 CollectionId(1),420 TokenId(0),421 1422 ));423 assert_eq!(424 <pallet_fungible::Balance<Test>>::get((CollectionId(1), account(2))),425 1426 );427 assert_eq!(428 <pallet_fungible::Balance<Test>>::get((CollectionId(1), account(3))),429 4430 );431 });432}433434#[test]435fn transfer_refungible_item() {436 new_test_ext().execute_with(|| {437 let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));438439 // Create RFT 1 in 1023 pieces for account 1440 let data = default_re_fungible_data();441 create_test_item(collection_id, &data.clone().into());442 let item = <pallet_refungible::TokenData<Test>>::get((collection_id, TokenId(1)));443 assert_eq!(item.const_data, data.const_data.into_inner());444 assert_eq!(445 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),446 1447 );448 assert_eq!(449 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),450 1023451 );452 assert_eq!(453 <pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),454 true455 );456457 // Account 1 transfers all 1023 pieces of RFT 1 to account 2458 let origin1 = Origin::signed(1);459 let origin2 = Origin::signed(2);460 assert_ok!(Unique::transfer(461 origin1,462 account(2),463 CollectionId(1),464 TokenId(1),465 1023466 ));467 assert_eq!(468 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(2))),469 1023470 );471 assert_eq!(472 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),473 0474 );475 assert_eq!(476 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(2))),477 1478 );479 assert_eq!(480 <pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),481 false482 );483 assert_eq!(484 <pallet_refungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),485 true486 );487488 // Account 2 transfers 500 pieces of RFT 1 to account 3489 assert_ok!(Unique::transfer(490 origin2.clone(),491 account(3),492 CollectionId(1),493 TokenId(1),494 500495 ));496 assert_eq!(497 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(2))),498 523499 );500 assert_eq!(501 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(3))),502 500503 );504 assert_eq!(505 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(2))),506 1507 );508 assert_eq!(509 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(3))),510 1511 );512 assert_eq!(513 <pallet_refungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),514 true515 );516 assert_eq!(517 <pallet_refungible::Owned<Test>>::get((collection_id, account(3), TokenId(1))),518 true519 );520521 // Account 2 transfers 200 more pieces of RFT 1 to account 3 with pre-existing balance522 assert_ok!(Unique::transfer(523 origin2,524 account(3),525 CollectionId(1),526 TokenId(1),527 200528 ));529 assert_eq!(530 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(2))),531 323532 );533 assert_eq!(534 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(3))),535 700536 );537 assert_eq!(538 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(2))),539 1540 );541 assert_eq!(542 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(3))),543 1544 );545 assert_eq!(546 <pallet_refungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),547 true548 );549 assert_eq!(550 <pallet_refungible::Owned<Test>>::get((collection_id, account(3), TokenId(1))),551 true552 );553 });554}555556#[test]557fn transfer_nft_item() {558 new_test_ext().execute_with(|| {559 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));560561 let data = default_nft_data();562 create_test_item(collection_id, &data.into());563 assert_eq!(564 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),565 1566 );567 assert_eq!(568 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),569 true570 );571572 let origin1 = Origin::signed(1);573 // default scenario574 assert_ok!(Unique::transfer(575 origin1,576 account(2),577 CollectionId(1),578 TokenId(1),579 1580 ));581 assert_eq!(582 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),583 0584 );585 assert_eq!(586 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),587 1588 );589 assert_eq!(590 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),591 false592 );593 assert_eq!(594 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),595 true596 );597 });598}599600#[test]601fn transfer_nft_item_wrong_value() {602 new_test_ext().execute_with(|| {603 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));604605 let data = default_nft_data();606 create_test_item(collection_id, &data.into());607 assert_eq!(608 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),609 1610 );611 assert_eq!(612 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),613 true614 );615616 let origin1 = Origin::signed(1);617618 assert_noop!(619 Unique::transfer(origin1, account(2), CollectionId(1), TokenId(1), 2)620 .map_err(|e| e.error),621 <pallet_nonfungible::Error::<Test>>::NonfungibleItemsHaveNoAmount622 );623 });624}625626#[test]627fn transfer_nft_item_zero_value() {628 new_test_ext().execute_with(|| {629 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));630631 let data = default_nft_data();632 create_test_item(collection_id, &data.into());633 assert_eq!(634 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),635 1636 );637 assert_eq!(638 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),639 true640 );641642 let origin1 = Origin::signed(1);643644 // Transferring 0 amount works on NFT...645 assert_ok!(Unique::transfer(646 origin1,647 account(2),648 CollectionId(1),649 TokenId(1),650 0651 ));652 // ... and results in no transfer653 assert_eq!(654 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),655 1656 );657 assert_eq!(658 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),659 true660 );661 });662}663664#[test]665fn nft_approve_and_transfer_from() {666 new_test_ext().execute_with(|| {667 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));668669 let data = default_nft_data();670 create_test_item(collection_id, &data.into());671672 let origin1 = Origin::signed(1);673 let origin2 = Origin::signed(2);674675 assert_eq!(676 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),677 1678 );679 assert_eq!(680 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),681 true682 );683684 // neg transfer_from685 assert_noop!(686 Unique::transfer_from(687 origin2.clone(),688 account(1),689 account(2),690 CollectionId(1),691 TokenId(1),692 1693 )694 .map_err(|e| e.error),695 CommonError::<Test>::ApprovedValueTooLow696 );697698 // do approve699 assert_ok!(Unique::approve(700 origin1,701 account(2),702 CollectionId(1),703 TokenId(1),704 1705 ));706 assert_eq!(707 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),708 account(2)709 );710711 assert_ok!(Unique::transfer_from(712 origin2,713 account(1),714 account(3),715 CollectionId(1),716 TokenId(1),717 1718 ));719 assert!(720 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).is_none()721 );722 });723}724725#[test]726fn nft_approve_and_transfer_from_allow_list() {727 new_test_ext().execute_with(|| {728 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));729730 let origin1 = Origin::signed(1);731 let origin2 = Origin::signed(2);732733 // Create NFT 1 for account 1734 let data = default_nft_data();735 create_test_item(collection_id, &data.clone().into());736 assert_eq!(737 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),738 1739 );740 assert_eq!(741 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),742 true743 );744745 // Allow allow-list users to mint and add accounts 1, 2, and 3 to allow-list746 assert_ok!(Unique::set_collection_permissions(747 origin1.clone(),748 CollectionId(1),749 CollectionPermissions {750 mint_mode: Some(true),751 access: Some(AccessMode::AllowList),752 nesting: None,753 }754 ));755 assert_ok!(Unique::add_to_allow_list(756 origin1.clone(),757 CollectionId(1),758 account(1)759 ));760 assert_ok!(Unique::add_to_allow_list(761 origin1.clone(),762 CollectionId(1),763 account(2)764 ));765 assert_ok!(Unique::add_to_allow_list(766 origin1.clone(),767 CollectionId(1),768 account(3)769 ));770771 // Account 1 approves account 2 for NFT 1772 assert_ok!(Unique::approve(773 origin1.clone(),774 account(2),775 CollectionId(1),776 TokenId(1),777 1778 ));779 assert_eq!(780 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),781 account(2)782 );783784 // Account 2 transfers NFT 1 from account 1 to account 3785 assert_ok!(Unique::transfer_from(786 origin2,787 account(1),788 account(3),789 CollectionId(1),790 TokenId(1),791 1792 ));793 assert!(794 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).is_none()795 );796 });797}798799#[test]800fn refungible_approve_and_transfer_from() {801 new_test_ext().execute_with(|| {802 let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));803804 let origin1 = Origin::signed(1);805 let origin2 = Origin::signed(2);806807 // Create RFT 1 in 1023 pieces for account 1808 let data = default_re_fungible_data();809 create_test_item(collection_id, &data.into());810811 assert_eq!(812 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),813 1814 );815 assert_eq!(816 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),817 1023818 );819 assert_eq!(820 <pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),821 true822 );823824 // Allow public minting, enable allow-list and add accounts 1, 2, 3 to allow-list825 assert_ok!(Unique::set_collection_permissions(826 origin1.clone(),827 CollectionId(1),828 CollectionPermissions {829 mint_mode: Some(true),830 access: Some(AccessMode::AllowList),831 nesting: None,832 }833 ));834 assert_ok!(Unique::add_to_allow_list(835 origin1.clone(),836 CollectionId(1),837 account(1)838 ));839 assert_ok!(Unique::add_to_allow_list(840 origin1.clone(),841 CollectionId(1),842 account(2)843 ));844 assert_ok!(Unique::add_to_allow_list(845 origin1.clone(),846 CollectionId(1),847 account(3)848 ));849850 // Account 1 approves account 2 for 1023 pieces of RFT 1851 assert_ok!(Unique::approve(852 origin1,853 account(2),854 CollectionId(1),855 TokenId(1),856 1023857 ));858 assert_eq!(859 <pallet_refungible::Allowance<Test>>::get((860 CollectionId(1),861 TokenId(1),862 account(1),863 account(2)864 )),865 1023866 );867868 // Account 2 transfers 100 pieces of RFT 1 from account 1 to account 3869 assert_ok!(Unique::transfer_from(870 origin2,871 account(1),872 account(3),873 CollectionId(1),874 TokenId(1),875 100876 ));877 assert_eq!(878 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),879 1880 );881 assert_eq!(882 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(3))),883 1884 );885 assert_eq!(886 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),887 923888 );889 assert_eq!(890 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(3))),891 100892 );893 assert_eq!(894 <pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),895 true896 );897 assert_eq!(898 <pallet_refungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),899 true900 );901 assert_eq!(902 <pallet_refungible::Allowance<Test>>::get((903 CollectionId(1),904 TokenId(1),905 account(1),906 account(2)907 )),908 923909 );910 });911}912913#[test]914fn fungible_approve_and_transfer_from() {915 new_test_ext().execute_with(|| {916 let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));917918 let data = default_fungible_data();919 create_test_item(collection_id, &data.into());920921 let origin1 = Origin::signed(1);922 let origin2 = Origin::signed(2);923924 assert_ok!(Unique::set_collection_permissions(925 origin1.clone(),926 CollectionId(1),927 CollectionPermissions {928 mint_mode: Some(true),929 access: Some(AccessMode::AllowList),930 nesting: None,931 }932 ));933 assert_ok!(Unique::add_to_allow_list(934 origin1.clone(),935 CollectionId(1),936 account(1)937 ));938 assert_ok!(Unique::add_to_allow_list(939 origin1.clone(),940 CollectionId(1),941 account(2)942 ));943 assert_ok!(Unique::add_to_allow_list(944 origin1.clone(),945 CollectionId(1),946 account(3)947 ));948949 // do approve950 assert_ok!(Unique::approve(951 origin1.clone(),952 account(2),953 CollectionId(1),954 TokenId(0),955 5956 ));957 assert_eq!(958 <pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(2))),959 5960 );961 assert_ok!(Unique::approve(962 origin1,963 account(3),964 CollectionId(1),965 TokenId(0),966 5967 ));968 assert_eq!(969 <pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(2))),970 5971 );972 assert_eq!(973 <pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(3))),974 5975 );976977 assert_ok!(Unique::transfer_from(978 origin2.clone(),979 account(1),980 account(3),981 CollectionId(1),982 TokenId(0),983 4984 ));985986 assert_eq!(987 <pallet_fungible::Allowance<Test>>::get((CollectionId(1), account(1), account(2))),988 1989 );990991 assert_noop!(992 Unique::transfer_from(993 origin2,994 account(1),995 account(3),996 CollectionId(1),997 TokenId(0),998 4999 )1000 .map_err(|e| e.error),1001 CommonError::<Test>::ApprovedValueTooLow1002 );1003 });1004}10051006#[test]1007fn change_collection_owner() {1008 new_test_ext().execute_with(|| {1009 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10101011 let origin1 = Origin::signed(1);1012 assert_ok!(Unique::change_collection_owner(origin1, collection_id, 2));1013 assert_eq!(1014 <pallet_common::CollectionById<Test>>::get(collection_id)1015 .unwrap()1016 .owner,1017 21018 );1019 });1020}10211022#[test]1023fn destroy_collection() {1024 new_test_ext().execute_with(|| {1025 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10261027 let origin1 = Origin::signed(1);1028 assert_ok!(Unique::destroy_collection(origin1, collection_id));1029 });1030}10311032#[test]1033fn burn_nft_item() {1034 new_test_ext().execute_with(|| {1035 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10361037 let origin1 = Origin::signed(1);10381039 let data = default_nft_data();1040 create_test_item(collection_id, &data.into());10411042 // check balance (collection with id = 1, user id = 1)1043 assert_eq!(1044 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1045 11046 );10471048 // burn item1049 assert_ok!(Unique::burn_item(1050 origin1.clone(),1051 collection_id,1052 TokenId(1),1053 11054 ));1055 assert_eq!(1056 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1057 01058 );1059 });1060}10611062#[test]1063fn burn_same_nft_item_twice() {1064 new_test_ext().execute_with(|| {1065 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));10661067 let origin1 = Origin::signed(1);10681069 let data = default_nft_data();1070 create_test_item(collection_id, &data.into());10711072 // check balance (collection with id = 1, user id = 1)1073 assert_eq!(1074 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1075 11076 );10771078 // burn item1079 assert_ok!(Unique::burn_item(1080 origin1.clone(),1081 collection_id,1082 TokenId(1),1083 11084 ));10851086 // burn item again1087 assert_noop!(1088 Unique::burn_item(origin1, collection_id, TokenId(1), 1).map_err(|e| e.error),1089 CommonError::<Test>::TokenNotFound1090 );10911092 assert_eq!(1093 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),1094 01095 );1096 });1097}10981099#[test]1100fn burn_fungible_item() {1101 new_test_ext().execute_with(|| {1102 let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));11031104 let origin1 = Origin::signed(1);1105 assert_ok!(Unique::add_collection_admin(1106 origin1.clone(),1107 collection_id,1108 account(2)1109 ));11101111 let data = default_fungible_data();1112 create_test_item(collection_id, &data.into());11131114 // check balance (collection with id = 1, user id = 1)1115 assert_eq!(1116 <pallet_fungible::Balance<Test>>::get((collection_id, account(1))),1117 51118 );11191120 // burn item1121 assert_ok!(Unique::burn_item(1122 origin1.clone(),1123 CollectionId(1),1124 TokenId(0),1125 51126 ));1127 assert_noop!(1128 Unique::burn_item(origin1, CollectionId(1), TokenId(0), 5).map_err(|e| e.error),1129 CommonError::<Test>::TokenValueTooLow1130 );11311132 assert_eq!(1133 <pallet_fungible::Balance<Test>>::get((collection_id, account(1))),1134 01135 );1136 });1137}11381139#[test]1140fn burn_fungible_item_with_token_id() {1141 new_test_ext().execute_with(|| {1142 let collection_id = create_test_collection(&CollectionMode::Fungible(3), CollectionId(1));11431144 let origin1 = Origin::signed(1);1145 assert_ok!(Unique::add_collection_admin(1146 origin1.clone(),1147 collection_id,1148 account(2)1149 ));11501151 let data = default_fungible_data();1152 create_test_item(collection_id, &data.into());11531154 // check balance (collection with id = 1, user id = 1)1155 assert_eq!(1156 <pallet_fungible::Balance<Test>>::get((collection_id, account(1))),1157 51158 );11591160 // Try to burn item using Token ID1161 assert_noop!(1162 Unique::burn_item(origin1, CollectionId(1), TokenId(1), 5).map_err(|e| e.error),1163 <pallet_fungible::Error::<Test>>::FungibleItemsHaveNoId1164 );1165 });1166}1167#[test]1168fn burn_refungible_item() {1169 new_test_ext().execute_with(|| {1170 let collection_id = create_test_collection(&CollectionMode::ReFungible, CollectionId(1));1171 let origin1 = Origin::signed(1);11721173 assert_ok!(Unique::set_collection_permissions(1174 origin1.clone(),1175 collection_id,1176 CollectionPermissions {1177 mint_mode: Some(true),1178 access: Some(AccessMode::AllowList),1179 nesting: None,1180 }1181 ));1182 assert_ok!(Unique::add_to_allow_list(1183 origin1.clone(),1184 collection_id,1185 account(1)1186 ));11871188 assert_ok!(Unique::add_collection_admin(1189 origin1.clone(),1190 collection_id,1191 account(2)1192 ));11931194 let data = default_re_fungible_data();1195 create_test_item(collection_id, &data.into());11961197 // check balance (collection with id = 1, user id = 2)1198 assert_eq!(1199 <pallet_refungible::AccountBalance<Test>>::get((collection_id, account(1))),1200 11201 );1202 assert_eq!(1203 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),1204 10231205 );12061207 // burn item1208 assert_ok!(Unique::burn_item(1209 origin1.clone(),1210 collection_id,1211 TokenId(1),1212 10231213 ));1214 assert_noop!(1215 Unique::burn_item(origin1, collection_id, TokenId(1), 1023).map_err(|e| e.error),1216 CommonError::<Test>::TokenValueTooLow1217 );12181219 assert_eq!(1220 <pallet_refungible::Balance<Test>>::get((collection_id, TokenId(1), account(1))),1221 01222 );1223 });1224}12251226#[test]1227fn add_collection_admin() {1228 new_test_ext().execute_with(|| {1229 let collection1_id =1230 create_test_collection_for_owner(&CollectionMode::NFT, 1, CollectionId(1));1231 let origin1 = Origin::signed(1);12321233 // Add collection admins1234 assert_ok!(Unique::add_collection_admin(1235 origin1.clone(),1236 collection1_id,1237 account(2)1238 ));1239 assert_ok!(Unique::add_collection_admin(1240 origin1,1241 collection1_id,1242 account(3)1243 ));12441245 // Owner is not an admin by default1246 assert_eq!(1247 <pallet_common::IsAdmin<Test>>::get((CollectionId(1), account(1))),1248 false1249 );1250 assert!(<pallet_common::IsAdmin<Test>>::get((1251 CollectionId(1),1252 account(2)1253 )));1254 assert!(<pallet_common::IsAdmin<Test>>::get((1255 CollectionId(1),1256 account(3)1257 )));1258 });1259}12601261#[test]1262fn remove_collection_admin() {1263 new_test_ext().execute_with(|| {1264 let collection1_id =1265 create_test_collection_for_owner(&CollectionMode::NFT, 1, CollectionId(1));1266 let origin1 = Origin::signed(1);12671268 // Add collection admins 2 and 31269 assert_ok!(Unique::add_collection_admin(1270 origin1.clone(),1271 collection1_id,1272 account(2)1273 ));1274 assert_ok!(Unique::add_collection_admin(1275 origin1.clone(),1276 collection1_id,1277 account(3)1278 ));12791280 assert!(<pallet_common::IsAdmin<Test>>::get((1281 CollectionId(1),1282 account(2)1283 )));1284 assert!(<pallet_common::IsAdmin<Test>>::get((1285 CollectionId(1),1286 account(3)1287 )));12881289 // remove admin 31290 assert_ok!(Unique::remove_collection_admin(1291 origin1,1292 CollectionId(1),1293 account(3)1294 ));12951296 // 2 is still admin, 3 is not an admin anymore1297 assert!(<pallet_common::IsAdmin<Test>>::get((1298 CollectionId(1),1299 account(2)1300 )));1301 assert_eq!(1302 <pallet_common::IsAdmin<Test>>::get((CollectionId(1), account(3))),1303 false1304 );1305 });1306}13071308#[test]1309fn balance_of() {1310 new_test_ext().execute_with(|| {1311 let nft_collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1312 let fungible_collection_id =1313 create_test_collection(&CollectionMode::Fungible(3), CollectionId(2));1314 let re_fungible_collection_id =1315 create_test_collection(&CollectionMode::ReFungible, CollectionId(3));13161317 // check balance before1318 assert_eq!(1319 <pallet_nonfungible::AccountBalance<Test>>::get((nft_collection_id, account(1))),1320 01321 );1322 assert_eq!(1323 <pallet_fungible::Balance<Test>>::get((fungible_collection_id, account(1))),1324 01325 );1326 assert_eq!(1327 <pallet_refungible::AccountBalance<Test>>::get((re_fungible_collection_id, account(1))),1328 01329 );13301331 let nft_data = default_nft_data();1332 create_test_item(nft_collection_id, &nft_data.into());13331334 let fungible_data = default_fungible_data();1335 create_test_item(fungible_collection_id, &fungible_data.into());13361337 let re_fungible_data = default_re_fungible_data();1338 create_test_item(re_fungible_collection_id, &re_fungible_data.into());13391340 // check balance (collection with id = 1, user id = 1)1341 assert_eq!(1342 <pallet_nonfungible::AccountBalance<Test>>::get((nft_collection_id, account(1))),1343 11344 );1345 assert_eq!(1346 <pallet_fungible::Balance<Test>>::get((fungible_collection_id, account(1))),1347 51348 );1349 assert_eq!(1350 <pallet_refungible::AccountBalance<Test>>::get((re_fungible_collection_id, account(1))),1351 11352 );13531354 assert_eq!(1355 <pallet_nonfungible::Owned<Test>>::get((nft_collection_id, account(1), TokenId(1))),1356 true1357 );1358 assert_eq!(1359 <pallet_refungible::Owned<Test>>::get((1360 re_fungible_collection_id,1361 account(1),1362 TokenId(1)1363 )),1364 true1365 );1366 });1367}13681369#[test]1370fn approve() {1371 new_test_ext().execute_with(|| {1372 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));13731374 let data = default_nft_data();1375 create_test_item(collection_id, &data.into());13761377 let origin1 = Origin::signed(1);13781379 // approve1380 assert_ok!(Unique::approve(1381 origin1,1382 account(2),1383 CollectionId(1),1384 TokenId(1),1385 11386 ));1387 assert_eq!(1388 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1389 account(2)1390 );1391 });1392}13931394#[test]1395fn transfer_from() {1396 new_test_ext().execute_with(|| {1397 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1398 let origin1 = Origin::signed(1);1399 let origin2 = Origin::signed(2);14001401 let data = default_nft_data();1402 create_test_item(collection_id, &data.into());14031404 // approve1405 assert_ok!(Unique::approve(1406 origin1.clone(),1407 account(2),1408 CollectionId(1),1409 TokenId(1),1410 11411 ));1412 assert_eq!(1413 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1414 account(2)1415 );14161417 assert_ok!(Unique::set_collection_permissions(1418 origin1.clone(),1419 CollectionId(1),1420 CollectionPermissions {1421 mint_mode: Some(true),1422 access: Some(AccessMode::AllowList),1423 nesting: None,1424 }1425 ));1426 assert_ok!(Unique::add_to_allow_list(1427 origin1.clone(),1428 CollectionId(1),1429 account(1)1430 ));1431 assert_ok!(Unique::add_to_allow_list(1432 origin1.clone(),1433 CollectionId(1),1434 account(2)1435 ));1436 assert_ok!(Unique::add_to_allow_list(1437 origin1,1438 CollectionId(1),1439 account(3)1440 ));14411442 assert_ok!(Unique::transfer_from(1443 origin2,1444 account(1),1445 account(2),1446 CollectionId(1),1447 TokenId(1),1448 11449 ));14501451 // after transfer1452 assert_eq!(1453 <pallet_nonfungible::AccountBalance<Test>>::get((CollectionId(1), account(1))),1454 01455 );1456 assert_eq!(1457 <pallet_nonfungible::AccountBalance<Test>>::get((CollectionId(1), account(2))),1458 11459 );1460 });1461}14621463// #endregion14641465// Coverage tests region1466// #region14671468#[test]1469fn owner_can_add_address_to_allow_list() {1470 new_test_ext().execute_with(|| {1471 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));14721473 let origin1 = Origin::signed(1);1474 assert_ok!(Unique::add_to_allow_list(1475 origin1,1476 collection_id,1477 account(2)1478 ));1479 assert!(<pallet_common::Allowlist<Test>>::get((1480 collection_id,1481 account(2)1482 )));1483 });1484}14851486#[test]1487fn admin_can_add_address_to_allow_list() {1488 new_test_ext().execute_with(|| {1489 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1490 let origin1 = Origin::signed(1);1491 let origin2 = Origin::signed(2);14921493 assert_ok!(Unique::add_collection_admin(1494 origin1,1495 collection_id,1496 account(2)1497 ));1498 assert_ok!(Unique::add_to_allow_list(1499 origin2,1500 collection_id,1501 account(3)1502 ));1503 assert!(<pallet_common::Allowlist<Test>>::get((1504 collection_id,1505 account(3)1506 )));1507 });1508}15091510#[test]1511fn nonprivileged_user_cannot_add_address_to_allow_list() {1512 new_test_ext().execute_with(|| {1513 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));15141515 let origin2 = Origin::signed(2);1516 assert_noop!(1517 Unique::add_to_allow_list(origin2, collection_id, account(3)),1518 CommonError::<Test>::NoPermission1519 );1520 });1521}15221523#[test]1524fn nobody_can_add_address_to_allow_list_of_nonexisting_collection() {1525 new_test_ext().execute_with(|| {1526 let origin1 = Origin::signed(1);15271528 assert_noop!(1529 Unique::add_to_allow_list(origin1, CollectionId(1), account(2)),1530 CommonError::<Test>::CollectionNotFound1531 );1532 });1533}15341535#[test]1536fn nobody_can_add_address_to_allow_list_of_deleted_collection() {1537 new_test_ext().execute_with(|| {1538 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));15391540 let origin1 = Origin::signed(1);1541 assert_ok!(Unique::destroy_collection(origin1.clone(), collection_id));1542 assert_noop!(1543 Unique::add_to_allow_list(origin1, collection_id, account(2)),1544 CommonError::<Test>::CollectionNotFound1545 );1546 });1547}15481549// If address is already added to allow list, nothing happens1550#[test]1551fn address_is_already_added_to_allow_list() {1552 new_test_ext().execute_with(|| {1553 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1554 let origin1 = Origin::signed(1);15551556 assert_ok!(Unique::add_to_allow_list(1557 origin1.clone(),1558 collection_id,1559 account(2)1560 ));1561 assert_ok!(Unique::add_to_allow_list(1562 origin1,1563 collection_id,1564 account(2)1565 ));1566 assert!(<pallet_common::Allowlist<Test>>::get((1567 collection_id,1568 account(2)1569 )));1570 });1571}15721573#[test]1574fn owner_can_remove_address_from_allow_list() {1575 new_test_ext().execute_with(|| {1576 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));15771578 let origin1 = Origin::signed(1);1579 assert_ok!(Unique::add_to_allow_list(1580 origin1.clone(),1581 collection_id,1582 account(2)1583 ));1584 assert_ok!(Unique::remove_from_allow_list(1585 origin1,1586 collection_id,1587 account(2)1588 ));1589 assert_eq!(1590 <pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1591 false1592 );1593 });1594}15951596#[test]1597fn admin_can_remove_address_from_allow_list() {1598 new_test_ext().execute_with(|| {1599 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1600 let origin1 = Origin::signed(1);1601 let origin2 = Origin::signed(2);16021603 // Owner adds admin1604 assert_ok!(Unique::add_collection_admin(1605 origin1.clone(),1606 collection_id,1607 account(2)1608 ));16091610 // Owner adds address 3 to allow list1611 assert_ok!(Unique::add_to_allow_list(1612 origin1,1613 collection_id,1614 account(3)1615 ));16161617 // Admin removes address 3 from allow list1618 assert_ok!(Unique::remove_from_allow_list(1619 origin2,1620 collection_id,1621 account(3)1622 ));1623 assert_eq!(1624 <pallet_common::Allowlist<Test>>::get((collection_id, account(3))),1625 false1626 );1627 });1628}16291630#[test]1631fn nonprivileged_user_cannot_remove_address_from_allow_list() {1632 new_test_ext().execute_with(|| {1633 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1634 let origin1 = Origin::signed(1);1635 let origin2 = Origin::signed(2);16361637 assert_ok!(Unique::add_to_allow_list(1638 origin1,1639 collection_id,1640 account(2)1641 ));1642 assert_noop!(1643 Unique::remove_from_allow_list(origin2, collection_id, account(2)),1644 CommonError::<Test>::NoPermission1645 );1646 assert!(<pallet_common::Allowlist<Test>>::get((1647 collection_id,1648 account(2)1649 )));1650 });1651}16521653#[test]1654fn nobody_can_remove_address_from_allow_list_of_nonexisting_collection() {1655 new_test_ext().execute_with(|| {1656 let origin1 = Origin::signed(1);16571658 assert_noop!(1659 Unique::remove_from_allow_list(origin1, CollectionId(1), account(2)),1660 CommonError::<Test>::CollectionNotFound1661 );1662 });1663}16641665#[test]1666fn nobody_can_remove_address_from_allow_list_of_deleted_collection() {1667 new_test_ext().execute_with(|| {1668 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1669 let origin1 = Origin::signed(1);1670 let origin2 = Origin::signed(2);16711672 // Add account 2 to allow list1673 assert_ok!(Unique::add_to_allow_list(1674 origin1.clone(),1675 collection_id,1676 account(2)1677 ));16781679 // Account 2 is in collection allow-list1680 assert!(<pallet_common::Allowlist<Test>>::get((1681 collection_id,1682 account(2)1683 )));16841685 // Destroy collection1686 assert_ok!(Unique::destroy_collection(origin1, collection_id));16871688 // Attempt to remove account 2 from collection allow-list => error1689 assert_noop!(1690 Unique::remove_from_allow_list(origin2, collection_id, account(2)),1691 CommonError::<Test>::CollectionNotFound1692 );16931694 // Account 2 is not found in collection allow-list anyway1695 assert_eq!(1696 <pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1697 false1698 );1699 });1700}17011702// If address is already removed from allow list, nothing happens1703#[test]1704fn address_is_already_removed_from_allow_list() {1705 new_test_ext().execute_with(|| {1706 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1707 let origin1 = Origin::signed(1);17081709 assert_ok!(Unique::add_to_allow_list(1710 origin1.clone(),1711 collection_id,1712 account(2)1713 ));1714 assert_ok!(Unique::remove_from_allow_list(1715 origin1.clone(),1716 collection_id,1717 account(2)1718 ));1719 assert_eq!(1720 <pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1721 false1722 );1723 assert_ok!(Unique::remove_from_allow_list(1724 origin1,1725 collection_id,1726 account(2)1727 ));1728 assert_eq!(1729 <pallet_common::Allowlist<Test>>::get((collection_id, account(2))),1730 false1731 );1732 });1733}17341735// If Public Access mode is set to AllowList, tokens can’t be transferred from a non-allowlisted address with transfer or transferFrom (2 tests)1736#[test]1737fn allow_list_test_1() {1738 new_test_ext().execute_with(|| {1739 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));17401741 let origin1 = Origin::signed(1);17421743 let data = default_nft_data();1744 create_test_item(collection_id, &data.into());17451746 assert_ok!(Unique::set_collection_permissions(1747 origin1.clone(),1748 collection_id,1749 CollectionPermissions {1750 mint_mode: None,1751 access: Some(AccessMode::AllowList),1752 nesting: None,1753 }1754 ));1755 assert_ok!(Unique::add_to_allow_list(1756 origin1.clone(),1757 collection_id,1758 account(2)1759 ));17601761 assert_noop!(1762 Unique::transfer(origin1, account(3), CollectionId(1), TokenId(1), 1)1763 .map_err(|e| e.error),1764 CommonError::<Test>::AddressNotInAllowlist1765 );1766 });1767}17681769#[test]1770fn allow_list_test_2() {1771 new_test_ext().execute_with(|| {1772 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));1773 let origin1 = Origin::signed(1);17741775 let data = default_nft_data();1776 create_test_item(collection_id, &data.into());17771778 assert_ok!(Unique::set_collection_permissions(1779 origin1.clone(),1780 collection_id,1781 CollectionPermissions {1782 mint_mode: None,1783 access: Some(AccessMode::AllowList),1784 nesting: None,1785 }1786 ));1787 assert_ok!(Unique::add_to_allow_list(1788 origin1.clone(),1789 collection_id,1790 account(1)1791 ));1792 assert_ok!(Unique::add_to_allow_list(1793 origin1.clone(),1794 collection_id,1795 account(2)1796 ));17971798 // do approve1799 assert_ok!(Unique::approve(1800 origin1.clone(),1801 account(1),1802 collection_id,1803 TokenId(1),1804 11805 ));1806 assert_eq!(1807 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1808 account(1)1809 );18101811 assert_ok!(Unique::remove_from_allow_list(1812 origin1.clone(),1813 collection_id,1814 account(1)1815 ));18161817 assert_noop!(1818 Unique::transfer_from(1819 origin1,1820 account(1),1821 account(3),1822 CollectionId(1),1823 TokenId(1),1824 11825 )1826 .map_err(|e| e.error),1827 CommonError::<Test>::AddressNotInAllowlist1828 );1829 });1830}18311832// If Public Access mode is set to AllowList, tokens can’t be transferred to a non-allowlisted address with transfer or transferFrom (2 tests)1833#[test]1834fn allow_list_test_3() {1835 new_test_ext().execute_with(|| {1836 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));18371838 let origin1 = Origin::signed(1);18391840 let data = default_nft_data();1841 create_test_item(collection_id, &data.into());18421843 assert_ok!(Unique::set_collection_permissions(1844 origin1.clone(),1845 collection_id,1846 CollectionPermissions {1847 mint_mode: None,1848 access: Some(AccessMode::AllowList),1849 nesting: None,1850 }1851 ));1852 assert_ok!(Unique::add_to_allow_list(1853 origin1.clone(),1854 collection_id,1855 account(1)1856 ));18571858 assert_noop!(1859 Unique::transfer(origin1, account(3), collection_id, TokenId(1), 1)1860 .map_err(|e| e.error),1861 CommonError::<Test>::AddressNotInAllowlist1862 );1863 });1864}18651866#[test]1867fn allow_list_test_4() {1868 new_test_ext().execute_with(|| {1869 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));18701871 let origin1 = Origin::signed(1);18721873 let data = default_nft_data();1874 create_test_item(collection_id, &data.into());18751876 assert_ok!(Unique::set_collection_permissions(1877 origin1.clone(),1878 collection_id,1879 CollectionPermissions {1880 mint_mode: None,1881 access: Some(AccessMode::AllowList),1882 nesting: None,1883 }1884 ));1885 assert_ok!(Unique::add_to_allow_list(1886 origin1.clone(),1887 collection_id,1888 account(1)1889 ));1890 assert_ok!(Unique::add_to_allow_list(1891 origin1.clone(),1892 collection_id,1893 account(2)1894 ));18951896 // do approve1897 assert_ok!(Unique::approve(1898 origin1.clone(),1899 account(1),1900 collection_id,1901 TokenId(1),1902 11903 ));1904 assert_eq!(1905 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),1906 account(1)1907 );19081909 assert_ok!(Unique::remove_from_allow_list(1910 origin1.clone(),1911 collection_id,1912 account(2)1913 ));19141915 assert_noop!(1916 Unique::transfer_from(1917 origin1,1918 account(1),1919 account(3),1920 collection_id,1921 TokenId(1),1922 11923 )1924 .map_err(|e| e.error),1925 CommonError::<Test>::AddressNotInAllowlist1926 );1927 });1928}19291930// If Public Access mode is set to AllowList, tokens can’t be destroyed by a non-allowlisted address (even if it owned them before enabling AllowList mode)1931#[test]1932fn allow_list_test_5() {1933 new_test_ext().execute_with(|| {1934 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));19351936 let origin1 = Origin::signed(1);19371938 let data = default_nft_data();1939 create_test_item(collection_id, &data.into());19401941 assert_ok!(Unique::set_collection_permissions(1942 origin1.clone(),1943 collection_id,1944 CollectionPermissions {1945 mint_mode: None,1946 access: Some(AccessMode::AllowList),1947 nesting: None,1948 }1949 ));1950 assert_noop!(1951 Unique::burn_item(origin1.clone(), CollectionId(1), TokenId(1), 1).map_err(|e| e.error),1952 CommonError::<Test>::AddressNotInAllowlist1953 );1954 });1955}19561957// If Public Access mode is set to AllowList, token transfers can’t be Approved by a non-allowlisted address (see Approve method).1958#[test]1959fn allow_list_test_6() {1960 new_test_ext().execute_with(|| {1961 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));19621963 let origin1 = Origin::signed(1);19641965 let data = default_nft_data();1966 create_test_item(collection_id, &data.into());19671968 assert_ok!(Unique::set_collection_permissions(1969 origin1.clone(),1970 collection_id,1971 CollectionPermissions {1972 mint_mode: None,1973 access: Some(AccessMode::AllowList),1974 nesting: None,1975 }1976 ));19771978 // do approve1979 assert_noop!(1980 Unique::approve(origin1, account(1), CollectionId(1), TokenId(1), 1)1981 .map_err(|e| e.error),1982 CommonError::<Test>::AddressNotInAllowlist1983 );1984 });1985}19861987// If Public Access mode is set to AllowList, tokens can be transferred from a allowlisted address with transfer or transferFrom (2 tests) and1988// tokens can be transferred from a allowlisted address with transfer or transferFrom (2 tests)1989#[test]1990fn allow_list_test_7() {1991 new_test_ext().execute_with(|| {1992 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));19931994 let data = default_nft_data();1995 create_test_item(collection_id, &data.into());19961997 let origin1 = Origin::signed(1);19981999 assert_ok!(Unique::set_collection_permissions(2000 origin1.clone(),2001 collection_id,2002 CollectionPermissions {2003 mint_mode: None,2004 access: Some(AccessMode::AllowList),2005 nesting: None,2006 }2007 ));2008 assert_ok!(Unique::add_to_allow_list(2009 origin1.clone(),2010 collection_id,2011 account(1)2012 ));2013 assert_ok!(Unique::add_to_allow_list(2014 origin1.clone(),2015 collection_id,2016 account(2)2017 ));20182019 assert_ok!(Unique::transfer(2020 origin1,2021 account(2),2022 CollectionId(1),2023 TokenId(1),2024 12025 ));2026 });2027}20282029#[test]2030fn allow_list_test_8() {2031 new_test_ext().execute_with(|| {2032 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));20332034 // Create NFT for account 12035 let data = default_nft_data();2036 create_test_item(collection_id, &data.into());20372038 let origin1 = Origin::signed(1);20392040 // Toggle Allow List mode and add accounts 1 and 22041 assert_ok!(Unique::set_collection_permissions(2042 origin1.clone(),2043 collection_id,2044 CollectionPermissions {2045 mint_mode: None,2046 access: Some(AccessMode::AllowList),2047 nesting: None,2048 }2049 ));2050 assert_ok!(Unique::add_to_allow_list(2051 origin1.clone(),2052 collection_id,2053 account(1)2054 ));2055 assert_ok!(Unique::add_to_allow_list(2056 origin1.clone(),2057 collection_id,2058 account(2)2059 ));20602061 // Sself-approve account 1 for NFT 12062 assert_ok!(Unique::approve(2063 origin1.clone(),2064 account(1),2065 CollectionId(1),2066 TokenId(1),2067 12068 ));2069 assert_eq!(2070 <pallet_nonfungible::Allowance<Test>>::get((CollectionId(1), TokenId(1))).unwrap(),2071 account(1)2072 );20732074 // Transfer from 1 to 22075 assert_ok!(Unique::transfer_from(2076 origin1,2077 account(1),2078 account(2),2079 CollectionId(1),2080 TokenId(1),2081 12082 ));2083 });2084}20852086// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by owner.2087#[test]2088fn allow_list_test_9() {2089 new_test_ext().execute_with(|| {2090 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));2091 let origin1 = Origin::signed(1);20922093 assert_ok!(Unique::set_collection_permissions(2094 origin1.clone(),2095 collection_id,2096 CollectionPermissions {2097 mint_mode: Some(false),2098 access: Some(AccessMode::AllowList),2099 nesting: None,2100 }2101 ));21022103 let data = default_nft_data();2104 create_test_item(collection_id, &data.into());2105 });2106}21072108// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens can be created by admin.2109#[test]2110fn allow_list_test_10() {2111 new_test_ext().execute_with(|| {2112 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));21132114 let origin1 = Origin::signed(1);2115 let origin2 = Origin::signed(2);21162117 assert_ok!(Unique::set_collection_permissions(2118 origin1.clone(),2119 collection_id,2120 CollectionPermissions {2121 mint_mode: Some(false),2122 access: Some(AccessMode::AllowList),2123 nesting: None,2124 }2125 ));21262127 assert_ok!(Unique::add_collection_admin(2128 origin1,2129 collection_id,2130 account(2)2131 ));21322133 assert_ok!(Unique::create_item(2134 origin2,2135 collection_id,2136 account(2),2137 default_nft_data().into()2138 ));2139 });2140}21412142// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens cannot be created by non-privileged and allow listed address.2143#[test]2144fn allow_list_test_11() {2145 new_test_ext().execute_with(|| {2146 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));21472148 let origin1 = Origin::signed(1);2149 let origin2 = Origin::signed(2);21502151 assert_ok!(Unique::set_collection_permissions(2152 origin1.clone(),2153 collection_id,2154 CollectionPermissions {2155 mint_mode: Some(false),2156 access: Some(AccessMode::AllowList),2157 nesting: None,2158 }2159 ));2160 assert_ok!(Unique::add_to_allow_list(2161 origin1,2162 collection_id,2163 account(2)2164 ));21652166 assert_noop!(2167 Unique::create_item(2168 origin2,2169 CollectionId(1),2170 account(2),2171 default_nft_data().into()2172 )2173 .map_err(|e| e.error),2174 CommonError::<Test>::PublicMintingNotAllowed2175 );2176 });2177}21782179// If Public Access mode is set to AllowList, and Mint Permission is set to false, tokens cannot be created by non-privileged and non-allow listed address.2180#[test]2181fn allow_list_test_12() {2182 new_test_ext().execute_with(|| {2183 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));21842185 let origin1 = Origin::signed(1);2186 let origin2 = Origin::signed(2);21872188 assert_ok!(Unique::set_collection_permissions(2189 origin1.clone(),2190 collection_id,2191 CollectionPermissions {2192 mint_mode: Some(false),2193 access: Some(AccessMode::AllowList),2194 nesting: None,2195 }2196 ));21972198 assert_noop!(2199 Unique::create_item(2200 origin2,2201 CollectionId(1),2202 account(2),2203 default_nft_data().into()2204 )2205 .map_err(|e| e.error),2206 CommonError::<Test>::PublicMintingNotAllowed2207 );2208 });2209}22102211// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by owner.2212#[test]2213fn allow_list_test_13() {2214 new_test_ext().execute_with(|| {2215 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));22162217 let origin1 = Origin::signed(1);22182219 assert_ok!(Unique::set_collection_permissions(2220 origin1.clone(),2221 collection_id,2222 CollectionPermissions {2223 mint_mode: Some(true),2224 access: Some(AccessMode::AllowList),2225 nesting: None,2226 }2227 ));22282229 let data = default_nft_data();2230 create_test_item(collection_id, &data.into());2231 });2232}22332234// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by admin.2235#[test]2236fn allow_list_test_14() {2237 new_test_ext().execute_with(|| {2238 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));22392240 let origin1 = Origin::signed(1);2241 let origin2 = Origin::signed(2);22422243 assert_ok!(Unique::set_collection_permissions(2244 origin1.clone(),2245 collection_id,2246 CollectionPermissions {2247 mint_mode: Some(true),2248 access: Some(AccessMode::AllowList),2249 nesting: None,2250 }2251 ));22522253 assert_ok!(Unique::add_collection_admin(2254 origin1,2255 collection_id,2256 account(2)2257 ));22582259 assert_ok!(Unique::create_item(2260 origin2,2261 collection_id,2262 account(2),2263 default_nft_data().into()2264 ));2265 });2266}22672268// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens cannot be created by non-privileged and non-allow listed address.2269#[test]2270fn allow_list_test_15() {2271 new_test_ext().execute_with(|| {2272 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));22732274 let origin1 = Origin::signed(1);2275 let origin2 = Origin::signed(2);22762277 assert_ok!(Unique::set_collection_permissions(2278 origin1.clone(),2279 collection_id,2280 CollectionPermissions {2281 mint_mode: Some(true),2282 access: Some(AccessMode::AllowList),2283 nesting: None,2284 }2285 ));22862287 assert_noop!(2288 Unique::create_item(2289 origin2,2290 collection_id,2291 account(2),2292 default_nft_data().into()2293 )2294 .map_err(|e| e.error),2295 CommonError::<Test>::AddressNotInAllowlist2296 );2297 });2298}22992300// If Public Access mode is set to AllowList, and Mint Permission is set to true, tokens can be created by non-privileged and allow listed address.2301#[test]2302fn allow_list_test_16() {2303 new_test_ext().execute_with(|| {2304 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));23052306 let origin1 = Origin::signed(1);2307 let origin2 = Origin::signed(2);23082309 assert_ok!(Unique::set_collection_permissions(2310 origin1.clone(),2311 collection_id,2312 CollectionPermissions {2313 mint_mode: Some(true),2314 access: Some(AccessMode::AllowList),2315 nesting: None,2316 }2317 ));2318 assert_ok!(Unique::add_to_allow_list(2319 origin1,2320 collection_id,2321 account(2)2322 ));23232324 assert_ok!(Unique::create_item(2325 origin2,2326 collection_id,2327 account(2),2328 default_nft_data().into()2329 ));2330 });2331}23322333// Total number of collections. Positive test2334#[test]2335fn total_number_collections_bound() {2336 new_test_ext().execute_with(|| {2337 create_test_collection(&CollectionMode::NFT, CollectionId(1));2338 });2339}23402341#[test]2342fn create_max_collections() {2343 new_test_ext().execute_with(|| {2344 for i in 1..COLLECTION_NUMBER_LIMIT {2345 create_test_collection(&CollectionMode::NFT, CollectionId(i));2346 }2347 });2348}23492350// Total number of collections. Negative test2351#[test]2352fn total_number_collections_bound_neg() {2353 new_test_ext().execute_with(|| {2354 let origin1 = Origin::signed(1);23552356 for i in 1..=COLLECTION_NUMBER_LIMIT {2357 create_test_collection(&CollectionMode::NFT, CollectionId(i));2358 }23592360 let col_name1: Vec<u16> = "Test1\0".encode_utf16().collect::<Vec<u16>>();2361 let col_desc1: Vec<u16> = "TestDescription1\0".encode_utf16().collect::<Vec<u16>>();2362 let token_prefix1: Vec<u8> = b"token_prefix1\0".to_vec();23632364 let data: CreateCollectionData<u64> = CreateCollectionData {2365 name: col_name1.try_into().unwrap(),2366 description: col_desc1.try_into().unwrap(),2367 token_prefix: token_prefix1.try_into().unwrap(),2368 mode: CollectionMode::NFT,2369 ..Default::default()2370 };23712372 // 11-th collection in chain. Expects error2373 assert_noop!(2374 Unique::create_collection_ex(origin1, data),2375 CommonError::<Test>::TotalCollectionsLimitExceeded2376 );2377 });2378}23792380// Owned tokens by a single address. Positive test2381#[test]2382fn owned_tokens_bound() {2383 new_test_ext().execute_with(|| {2384 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));23852386 let data = default_nft_data();2387 create_test_item(collection_id, &data.clone().into());2388 create_test_item(collection_id, &data.into());2389 });2390}23912392// Owned tokens by a single address. Negotive test2393#[test]2394fn owned_tokens_bound_neg() {2395 new_test_ext().execute_with(|| {2396 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));23972398 let origin1 = Origin::signed(1);23992400 for _ in 1..=MAX_TOKEN_OWNERSHIP {2401 let data = default_nft_data();2402 create_test_item(collection_id, &data.clone().into());2403 }24042405 let data = default_nft_data();2406 assert_noop!(2407 Unique::create_item(origin1, CollectionId(1), account(1), data.into())2408 .map_err(|e| e.error),2409 CommonError::<Test>::AccountTokenLimitExceeded2410 );2411 });2412}24132414// Number of collection admins. Positive test2415#[test]2416fn collection_admins_bound() {2417 new_test_ext().execute_with(|| {2418 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));24192420 let origin1 = Origin::signed(1);24212422 assert_ok!(Unique::add_collection_admin(2423 origin1.clone(),2424 collection_id,2425 account(2)2426 ));2427 assert_ok!(Unique::add_collection_admin(2428 origin1,2429 collection_id,2430 account(3)2431 ));2432 });2433}24342435// Number of collection admins. Negotive test2436#[test]2437fn collection_admins_bound_neg() {2438 new_test_ext().execute_with(|| {2439 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));24402441 let origin1 = Origin::signed(1);24422443 for i in 0..COLLECTION_ADMINS_LIMIT {2444 assert_ok!(Unique::add_collection_admin(2445 origin1.clone(),2446 collection_id,2447 account((2 + i).into())2448 ));2449 }2450 assert_noop!(2451 Unique::add_collection_admin(2452 origin1,2453 collection_id,2454 account((3 + COLLECTION_ADMINS_LIMIT).into())2455 ),2456 CommonError::<Test>::CollectionAdminCountExceeded2457 );2458 });2459}2460// #endregion24612462#[test]2463fn collection_transfer_flag_works() {2464 new_test_ext().execute_with(|| {2465 let origin1 = Origin::signed(1);24662467 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));2468 assert_ok!(Unique::set_transfers_enabled_flag(2469 origin1,2470 collection_id,2471 true2472 ));24732474 let data = default_nft_data();2475 create_test_item(collection_id, &data.into());2476 assert_eq!(2477 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2478 12479 );2480 assert_eq!(2481 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2482 true2483 );24842485 let origin1 = Origin::signed(1);24862487 // default scenario2488 assert_ok!(Unique::transfer(2489 origin1,2490 account(2),2491 collection_id,2492 TokenId(1),2493 12494 ));2495 assert_eq!(2496 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2497 false2498 );2499 assert_eq!(2500 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),2501 true2502 );2503 assert_eq!(2504 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2505 02506 );2507 assert_eq!(2508 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),2509 12510 );2511 });2512}25132514#[test]2515fn collection_transfer_flag_works_neg() {2516 new_test_ext().execute_with(|| {2517 let origin1 = Origin::signed(1);25182519 let collection_id = create_test_collection(&CollectionMode::NFT, CollectionId(1));2520 assert_ok!(Unique::set_transfers_enabled_flag(2521 origin1,2522 collection_id,2523 false2524 ));25252526 let data = default_nft_data();2527 create_test_item(collection_id, &data.into());2528 assert_eq!(2529 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2530 12531 );2532 assert_eq!(2533 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2534 true2535 );25362537 let origin1 = Origin::signed(1);25382539 // default scenario2540 assert_noop!(2541 Unique::transfer(origin1, account(2), CollectionId(1), TokenId(1), 1)2542 .map_err(|e| e.error),2543 CommonError::<Test>::TransferNotAllowed2544 );2545 assert_eq!(2546 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(1))),2547 12548 );2549 assert_eq!(2550 <pallet_nonfungible::AccountBalance<Test>>::get((collection_id, account(2))),2551 02552 );2553 assert_eq!(2554 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(1), TokenId(1))),2555 true2556 );2557 assert_eq!(2558 <pallet_nonfungible::Owned<Test>>::get((collection_id, account(2), TokenId(1))),2559 false2560 );2561 });2562}25632564#[test]2565fn collection_sponsoring() {2566 new_test_ext().execute_with(|| {2567 // default_limits();2568 let user1 = 1_u64;2569 let user2 = 777_u64;2570 let origin1 = Origin::signed(user1);2571 let origin2 = Origin::signed(user2);2572 let account2 = account(user2);25732574 let collection_id =2575 create_test_collection_for_owner(&CollectionMode::NFT, user1, CollectionId(1));2576 assert_ok!(Unique::set_collection_sponsor(2577 origin1.clone(),2578 collection_id,2579 user12580 ));2581 assert_ok!(Unique::confirm_sponsorship(origin1.clone(), collection_id));25822583 // Expect error while have no permissions2584 assert!(Unique::create_item(2585 origin2.clone(),2586 collection_id,2587 account2.clone(),2588 default_nft_data().into()2589 )2590 .is_err());25912592 assert_ok!(Unique::set_collection_permissions(2593 origin1.clone(),2594 collection_id,2595 CollectionPermissions {2596 mint_mode: Some(true),2597 access: Some(AccessMode::AllowList),2598 nesting: None,2599 }2600 ));2601 assert_ok!(Unique::add_to_allow_list(2602 origin1.clone(),2603 collection_id,2604 account2.clone()2605 ));26062607 assert_ok!(Unique::create_item(2608 origin2,2609 collection_id,2610 account2,2611 default_nft_data().into()2612 ));2613 });2614}tests/src/eth/api/UniqueNFT.soldiffbeforeafterboth--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -174,7 +174,24 @@
function finishMinting() external returns (bool);
}
-// Selector: 6aea9834
+// Selector: 780e9d63
+interface ERC721Enumerable is Dummy, ERC165 {
+ // Selector: tokenByIndex(uint256) 4f6ccce7
+ function tokenByIndex(uint256 index) external view returns (uint256);
+
+ // Not implemented
+ //
+ // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59
+ function tokenOfOwnerByIndex(address owner, uint256 index)
+ external
+ view
+ returns (uint256);
+
+ // Selector: totalSupply() 18160ddd
+ function totalSupply() external view returns (uint256);
+}
+
+// Selector: 7d9262e6
interface Collection is Dummy, ERC165 {
// Selector: setCollectionProperty(string,bytes) 2f073f66
function setCollectionProperty(string memory key, bytes memory value)
@@ -206,6 +223,12 @@
// Selector: contractAddress() f6b4dfb4
function contractAddress() external view returns (address);
+ // Selector: addCollectionAdminSubstrate(uint256) 5730062b
+ function addCollectionAdminSubstrate(uint256 newAdmin) external view;
+
+ // Selector: removeCollectionAdminSubstrate(uint256) 4048fcf9
+ function removeCollectionAdminSubstrate(uint256 newAdmin) external view;
+
// Selector: addCollectionAdmin(address) 92e462c7
function addCollectionAdmin(address newAdmin) external view;
@@ -230,23 +253,6 @@
// Selector: setCollectionMintMode(bool) 00018e84
function setCollectionMintMode(bool mode) external;
-}
-
-// Selector: 780e9d63
-interface ERC721Enumerable is Dummy, ERC165 {
- // Selector: tokenByIndex(uint256) 4f6ccce7
- function tokenByIndex(uint256 index) external view returns (uint256);
-
- // Not implemented
- //
- // Selector: tokenOfOwnerByIndex(address,uint256) 2f745c59
- function tokenOfOwnerByIndex(address owner, uint256 index)
- external
- view
- returns (uint256);
-
- // Selector: totalSupply() 18160ddd
- function totalSupply() external view returns (uint256);
}
// Selector: d74d154f
tests/src/eth/collectionAdmin.test.tsdiffbeforeafterboth--- /dev/null
+++ b/tests/src/eth/collectionAdmin.test.ts
@@ -0,0 +1,296 @@
+// 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/>.
+
+import {expect} from 'chai';
+import privateKey from '../substrate/privateKey';
+import {
+ createEthAccount,
+ createEthAccountWithBalance,
+ evmCollection,
+ evmCollectionHelpers,
+ getCollectionAddressFromResult,
+ itWeb3,
+} from './util/helpers';
+
+describe('Add collection admins', () => {
+ itWeb3('Add admin by owner', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const collectionHelper = evmCollectionHelpers(web3, owner);
+
+ const result = await collectionHelper.methods
+ .createNonfungibleCollection('A', 'B', 'C')
+ .send();
+ const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
+
+ const newAdmin = await createEthAccount(web3);
+ const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+ await collectionEvm.methods.addCollectionAdmin(newAdmin).send();
+ const adminList = await api.rpc.unique.adminlist(collectionId);
+ expect(adminList[0].asEthereum.toString().toLocaleLowerCase())
+ .to.be.eq(newAdmin.toLocaleLowerCase());
+ });
+
+ itWeb3('Add substrate admin by owner', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const collectionHelper = evmCollectionHelpers(web3, owner);
+
+ const result = await collectionHelper.methods
+ .createNonfungibleCollection('A', 'B', 'C')
+ .send();
+ const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
+
+ const newAdmin = privateKey('//Alice');
+ const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+ await collectionEvm.methods.addCollectionAdminSubstrate(newAdmin.addressRaw).send();
+
+ const adminList = await api.rpc.unique.adminlist(collectionId);
+ expect(adminList[0].asSubstrate.toString().toLocaleLowerCase())
+ .to.be.eq(newAdmin.address.toLocaleLowerCase());
+ });
+
+ itWeb3('(!negative tests!) Add admin by ADMIN is not allowed', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const collectionHelper = evmCollectionHelpers(web3, owner);
+
+ const result = await collectionHelper.methods
+ .createNonfungibleCollection('A', 'B', 'C')
+ .send();
+ const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
+
+ const admin = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+ await collectionEvm.methods.addCollectionAdmin(admin).send();
+
+ const user = await createEthAccount(web3);
+ await expect(collectionEvm.methods.addCollectionAdmin(user).call({from: admin}))
+ .to.be.rejectedWith('NoPermission');
+
+ const adminList = await api.rpc.unique.adminlist(collectionId);
+ expect(adminList.length).to.be.eq(1);
+ expect(adminList[0].asEthereum.toString().toLocaleLowerCase())
+ .to.be.eq(admin.toLocaleLowerCase());
+ });
+
+ itWeb3('(!negative tests!) Add admin by USER is not allowed', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const collectionHelper = evmCollectionHelpers(web3, owner);
+
+ const result = await collectionHelper.methods
+ .createNonfungibleCollection('A', 'B', 'C')
+ .send();
+ const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
+
+ const notAdmin = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+
+ const user = await createEthAccount(web3);
+ await expect(collectionEvm.methods.addCollectionAdmin(user).call({from: notAdmin}))
+ .to.be.rejectedWith('NoPermission');
+
+ const adminList = await api.rpc.unique.adminlist(collectionId);
+ expect(adminList.length).to.be.eq(0);
+ });
+
+ itWeb3('(!negative tests!) Add substrate admin by ADMIN is not allowed', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const collectionHelper = evmCollectionHelpers(web3, owner);
+
+ const result = await collectionHelper.methods
+ .createNonfungibleCollection('A', 'B', 'C')
+ .send();
+ const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
+
+ const admin = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+ await collectionEvm.methods.addCollectionAdmin(admin).send();
+
+ const notAdmin = privateKey('//Alice');
+ await expect(collectionEvm.methods.addCollectionAdminSubstrate(notAdmin.addressRaw).call({from: admin}))
+ .to.be.rejectedWith('NoPermission');
+
+ const adminList = await api.rpc.unique.adminlist(collectionId);
+ expect(adminList.length).to.be.eq(1);
+ expect(adminList[0].asEthereum.toString().toLocaleLowerCase())
+ .to.be.eq(admin.toLocaleLowerCase());
+ });
+
+ itWeb3('(!negative tests!) Add substrate admin by USER is not allowed', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const collectionHelper = evmCollectionHelpers(web3, owner);
+
+ const result = await collectionHelper.methods
+ .createNonfungibleCollection('A', 'B', 'C')
+ .send();
+ const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
+
+ const notAdmin0 = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+ const notAdmin1 = privateKey('//Alice');
+ await expect(collectionEvm.methods.addCollectionAdminSubstrate(notAdmin1.addressRaw).call({from: notAdmin0}))
+ .to.be.rejectedWith('NoPermission');
+
+ const adminList = await api.rpc.unique.adminlist(collectionId);
+ expect(adminList.length).to.be.eq(0);
+ });
+});
+
+describe('Remove collection admins', () => {
+ itWeb3('Remove admin by owner', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const collectionHelper = evmCollectionHelpers(web3, owner);
+
+ const result = await collectionHelper.methods
+ .createNonfungibleCollection('A', 'B', 'C')
+ .send();
+ const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
+
+ const newAdmin = await createEthAccount(web3);
+ const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+ await collectionEvm.methods.addCollectionAdmin(newAdmin).send();
+ {
+ const adminList = await api.rpc.unique.adminlist(collectionId);
+ expect(adminList.length).to.be.eq(1);
+ expect(adminList[0].asEthereum.toString().toLocaleLowerCase())
+ .to.be.eq(newAdmin.toLocaleLowerCase());
+ }
+
+ await collectionEvm.methods.removeCollectionAdmin(newAdmin).send();
+ const adminList = await api.rpc.unique.adminlist(collectionId);
+ expect(adminList.length).to.be.eq(0);
+ });
+
+ itWeb3('Remove substrate admin by owner', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const collectionHelper = evmCollectionHelpers(web3, owner);
+
+ const result = await collectionHelper.methods
+ .createNonfungibleCollection('A', 'B', 'C')
+ .send();
+ const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
+
+ const newAdmin = privateKey('//Alice');
+ const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+ await collectionEvm.methods.addCollectionAdminSubstrate(newAdmin.addressRaw).send();
+ {
+ const adminList = await api.rpc.unique.adminlist(collectionId);
+ expect(adminList[0].asSubstrate.toString().toLocaleLowerCase())
+ .to.be.eq(newAdmin.address.toLocaleLowerCase());
+ }
+
+ await collectionEvm.methods.removeCollectionAdminSubstrate(newAdmin.addressRaw).send();
+ const adminList = await api.rpc.unique.adminlist(collectionId);
+ expect(adminList.length).to.be.eq(0);
+ });
+
+ itWeb3('(!negative tests!) Remove admin by ADMIN is not allowed', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const collectionHelper = evmCollectionHelpers(web3, owner);
+
+ const result = await collectionHelper.methods
+ .createNonfungibleCollection('A', 'B', 'C')
+ .send();
+ const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
+
+ const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+
+ const admin0 = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ await collectionEvm.methods.addCollectionAdmin(admin0).send();
+ const admin1 = await createEthAccount(web3);
+ await collectionEvm.methods.addCollectionAdmin(admin1).send();
+
+ await expect(collectionEvm.methods.removeCollectionAdmin(admin1).call({from: admin0}))
+ .to.be.rejectedWith('NoPermission');
+ {
+ const adminList = await api.rpc.unique.adminlist(collectionId);
+ expect(adminList.length).to.be.eq(2);
+ expect(adminList.toString().toLocaleLowerCase())
+ .to.be.deep.contains(admin0.toLocaleLowerCase())
+ .to.be.deep.contains(admin1.toLocaleLowerCase());
+ }
+ });
+
+ itWeb3('(!negative tests!) Remove admin by USER is not allowed', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const collectionHelper = evmCollectionHelpers(web3, owner);
+
+ const result = await collectionHelper.methods
+ .createNonfungibleCollection('A', 'B', 'C')
+ .send();
+ const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
+
+ const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+
+ const admin = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ await collectionEvm.methods.addCollectionAdmin(admin).send();
+ const notAdmin = await createEthAccount(web3);
+
+ await expect(collectionEvm.methods.removeCollectionAdmin(admin).call({from: notAdmin}))
+ .to.be.rejectedWith('NoPermission');
+ {
+ const adminList = await api.rpc.unique.adminlist(collectionId);
+ expect(adminList[0].asEthereum.toString().toLocaleLowerCase())
+ .to.be.eq(admin.toLocaleLowerCase());
+ expect(adminList.length).to.be.eq(1);
+ }
+ });
+
+ itWeb3('(!negative tests!) Remove substrate admin by ADMIN is not allowed', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const collectionHelper = evmCollectionHelpers(web3, owner);
+
+ const result = await collectionHelper.methods
+ .createNonfungibleCollection('A', 'B', 'C')
+ .send();
+ const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
+
+ const adminSub = privateKey('//Alice');
+ const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+ await collectionEvm.methods.addCollectionAdminSubstrate(adminSub.addressRaw).send();
+ const adminEth = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ await collectionEvm.methods.addCollectionAdmin(adminEth).send();
+
+ await expect(collectionEvm.methods.removeCollectionAdminSubstrate(adminSub.addressRaw).call({from: adminEth}))
+ .to.be.rejectedWith('NoPermission');
+
+ const adminList = await api.rpc.unique.adminlist(collectionId);
+ expect(adminList.length).to.be.eq(2);
+ expect(adminList.toString().toLocaleLowerCase())
+ .to.be.deep.contains(adminSub.address.toLocaleLowerCase())
+ .to.be.deep.contains(adminEth.toLocaleLowerCase());
+ });
+
+ itWeb3('(!negative tests!) Remove substrate admin by USER is not allowed', async ({api, web3, privateKeyWrapper}) => {
+ const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+ const collectionHelper = evmCollectionHelpers(web3, owner);
+
+ const result = await collectionHelper.methods
+ .createNonfungibleCollection('A', 'B', 'C')
+ .send();
+ const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
+
+ const adminSub = privateKey('//Alice');
+ const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
+ await collectionEvm.methods.addCollectionAdminSubstrate(adminSub.addressRaw).send();
+ const notAdminEth = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
+
+ await expect(collectionEvm.methods.removeCollectionAdminSubstrate(adminSub.addressRaw).call({from: notAdminEth}))
+ .to.be.rejectedWith('NoPermission');
+
+ const adminList = await api.rpc.unique.adminlist(collectionId);
+ expect(adminList.length).to.be.eq(1);
+ expect(adminList[0].asSubstrate.toString().toLocaleLowerCase())
+ .to.be.eq(adminSub.address.toLocaleLowerCase());
+ });
+});
\ No newline at end of file
tests/src/eth/contractSponsoring.test.tsdiffbeforeafterboth--- a/tests/src/eth/contractSponsoring.test.ts
+++ b/tests/src/eth/contractSponsoring.test.ts
@@ -233,7 +233,7 @@
const ss58Format = (api.registry.getChainProperties())!.toJSON().ss58Format;
expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;
expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
- await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('Caller is not set as sponsor');
+ await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');
await collectionEvm.methods.confirmCollectionSponsorship().send({from: sponsor});
collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
@@ -241,14 +241,13 @@
expect(collectionSub.sponsorship.asConfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
const user = createEthAccount(web3);
- let nextTokenId = await collectionEvm.methods.nextTokenId().call();
+ const nextTokenId = await collectionEvm.methods.nextTokenId().call();
expect(nextTokenId).to.be.equal('1');
const oldPermissions = (await getDetailedCollectionInfo(api, collectionId))!.permissions.toHuman();
expect(oldPermissions.mintMode).to.be.false;
expect(oldPermissions.access).to.be.equal('Normal');
- //TODO: change value, when enum generated
await collectionEvm.methods.setCollectionAccess(1 /*'AllowList'*/).send({from: owner});
await collectionEvm.methods.addToCollectionAllowList(user).send({from: owner});
await collectionEvm.methods.setCollectionMintMode(true).send({from: owner});
@@ -260,34 +259,35 @@
const ownerBalanceBefore = await ethBalanceViaSub(api, owner);
const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);
- nextTokenId = await collectionEvm.methods.nextTokenId().call({from: user});
- expect(nextTokenId).to.be.equal('1');
- result = await collectionEvm.methods.mintWithTokenURI(
- user,
- nextTokenId,
- 'Test URI',
- ).send({from: user});
- const events = normalizeEvents(result.events);
- events[0].address = events[0].address.toLocaleLowerCase();
+ {
+ const nextTokenId = await collectionEvm.methods.nextTokenId().call();
+ expect(nextTokenId).to.be.equal('1');
+ const result = await collectionEvm.methods.mintWithTokenURI(
+ user,
+ nextTokenId,
+ 'Test URI',
+ ).send({from: user});
+ const events = normalizeEvents(result.events);
- expect(events).to.be.deep.equal([
- {
- address: collectionIdAddress.toLocaleLowerCase(),
- event: 'Transfer',
- args: {
- from: '0x0000000000000000000000000000000000000000',
- to: user,
- tokenId: nextTokenId,
+ expect(events).to.be.deep.equal([
+ {
+ address: collectionIdAddress,
+ event: 'Transfer',
+ args: {
+ from: '0x0000000000000000000000000000000000000000',
+ to: user,
+ tokenId: nextTokenId,
+ },
},
- },
- ]);
+ ]);
- expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');
+ const ownerBalanceAfter = await ethBalanceViaSub(api, owner);
+ const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);
- const ownerBalanceAfter = await ethBalanceViaSub(api, owner);
- expect(ownerBalanceAfter).to.be.eq(ownerBalanceBefore);
- const sponsorBalanceAfter = await ethBalanceViaSub(api, sponsor);
- expect(sponsorBalanceAfter < sponsorBalanceBefore).to.be.true;
+ expect(await collectionEvm.methods.tokenURI(nextTokenId).call()).to.be.equal('Test URI');
+ expect(ownerBalanceBefore).to.be.eq(ownerBalanceAfter);
+ expect(sponsorBalanceBefore > sponsorBalanceAfter).to.be.true;
+ }
});
itWeb3('Check that transaction via EVM spend money from sponsor address', async ({api, web3, privateKeyWrapper}) => {
@@ -302,7 +302,7 @@
const ss58Format = (api.registry.getChainProperties())!.toJSON().ss58Format;
expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;
expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
- await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('Caller is not set as sponsor');
+ await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');
const sponsorCollection = evmCollection(web3, sponsor, collectionIdAddress);
await sponsorCollection.methods.confirmCollectionSponsorship().send();
collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
@@ -314,6 +314,7 @@
const ownerBalanceBefore = await ethBalanceViaSub(api, owner);
const sponsorBalanceBefore = await ethBalanceViaSub(api, sponsor);
+
const userCollectionEvm = evmCollection(web3, user, collectionIdAddress);
const nextTokenId = await userCollectionEvm.methods.nextTokenId().call();
tests/src/eth/createCollection.test.tsdiffbeforeafterboth--- a/tests/src/eth/createCollection.test.ts
+++ b/tests/src/eth/createCollection.test.ts
@@ -80,7 +80,7 @@
expect(collectionSub.sponsorship.isUnconfirmed).to.be.true;
const ss58Format = (api.registry.getChainProperties())!.toJSON().ss58Format;
expect(collectionSub.sponsorship.asUnconfirmed.toHuman()).to.be.eq(evmToAddress(sponsor, Number(ss58Format)));
- await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('Caller is not set as sponsor');
+ await expect(collectionEvm.methods.confirmCollectionSponsorship().call()).to.be.rejectedWith('caller is not set as sponsor');
const sponsorCollection = evmCollection(web3, sponsor, collectionIdAddress);
await sponsorCollection.methods.confirmCollectionSponsorship().send();
collectionSub = (await getDetailedCollectionInfo(api, collectionId))!;
@@ -208,7 +208,7 @@
const sponsorCollection = evmCollection(web3, sponsor, collectionIdAddress);
await expect(sponsorCollection.methods
.confirmCollectionSponsorship()
- .call()).to.be.rejectedWith('Caller is not set as sponsor');
+ .call()).to.be.rejectedWith('caller is not set as sponsor');
}
{
await expect(contractEvmFromNotOwner.methods
@@ -225,6 +225,6 @@
const collectionEvm = evmCollection(web3, owner, collectionIdAddress);
await expect(collectionEvm.methods
.setCollectionLimit('badLimit', 'true')
- .call()).to.be.rejectedWith('Unknown boolean limit "badLimit"');
+ .call()).to.be.rejectedWith('unknown boolean limit "badLimit"');
});
});
\ No newline at end of file
tests/src/eth/nonFungibleAbi.jsondiffbeforeafterboth--- a/tests/src/eth/nonFungibleAbi.json
+++ b/tests/src/eth/nonFungibleAbi.json
@@ -91,6 +91,15 @@
},
{
"inputs": [
+ { "internalType": "uint256", "name": "newAdmin", "type": "uint256" }
+ ],
+ "name": "addCollectionAdminSubstrate",
+ "outputs": [],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "address", "name": "user", "type": "address" }
],
"name": "addToCollectionAllowList",
@@ -300,6 +309,15 @@
},
{
"inputs": [
+ { "internalType": "uint256", "name": "newAdmin", "type": "uint256" }
+ ],
+ "name": "removeCollectionAdminSubstrate",
+ "outputs": [],
+ "stateMutability": "view",
+ "type": "function"
+ },
+ {
+ "inputs": [
{ "internalType": "address", "name": "user", "type": "address" }
],
"name": "removeFromCollectionAllowList",
tests/src/interfaces/augment-api-query.tsdiffbeforeafterboth--- a/tests/src/interfaces/augment-api-query.ts
+++ b/tests/src/interfaces/augment-api-query.ts
@@ -5,7 +5,7 @@
import type { BTreeMap, Bytes, Option, U256, U8aFixed, Vec, bool, u128, u16, u32, u64 } from '@polkadot/types-codec';
import type { AnyNumber, ITuple } from '@polkadot/types-codec/types';
import type { AccountId32, H160, H256 } from '@polkadot/types/interfaces/runtime';
-import type { CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueQueueConfigData, EthereumBlock, EthereumLog, EthereumReceiptReceiptV3, EthereumTransactionTransactionV2, FpRpcTransactionStatus, FrameSupportWeightsPerDispatchClassU64, FrameSystemAccountInfo, FrameSystemEventRecord, FrameSystemLastRuntimeUpgradeInfo, FrameSystemPhase, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesReleases, PalletBalancesReserveData, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmContractHelpersSponsoringModeT, PalletNonfungibleItemData, PalletRefungibleItemData, PalletTransactionPaymentReleases, PalletTreasuryProposal, PalletUnqSchedulerScheduledV3, PhantomTypeUpDataStructs, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, SpRuntimeDigest, SpTrieStorageProof, UpDataStructsCollection, UpDataStructsCollectionStats, UpDataStructsProperties, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsPropertyPermission, UpDataStructsTokenChild } from '@polkadot/types/lookup';
+import type { CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueQueueConfigData, EthereumBlock, EthereumLog, EthereumReceiptReceiptV3, EthereumTransactionTransactionV2, FpRpcTransactionStatus, FrameSupportWeightsPerDispatchClassU64, FrameSystemAccountInfo, FrameSystemEventRecord, FrameSystemLastRuntimeUpgradeInfo, FrameSystemPhase, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesReleases, PalletBalancesReserveData, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmContractHelpersSponsoringModeT, PalletNonfungibleItemData, PalletRefungibleItemData, PalletTransactionPaymentReleases, PalletTreasuryProposal, PalletUniqueSchedulerScheduledV3, PhantomTypeUpDataStructs, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, SpRuntimeDigest, SpTrieStorageProof, UpDataStructsCollection, UpDataStructsCollectionStats, UpDataStructsProperties, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsPropertyPermission, UpDataStructsTokenChild } from '@polkadot/types/lookup';
import type { Observable } from '@polkadot/types/types';
declare module '@polkadot/api-base/types/storage' {
@@ -436,7 +436,7 @@
/**
* Items to be executed, indexed by the block number that they should be executed on.
**/
- agenda: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Vec<Option<PalletUnqSchedulerScheduledV3>>>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;
+ agenda: AugmentedQuery<ApiType, (arg: u32 | AnyNumber | Uint8Array) => Observable<Vec<Option<PalletUniqueSchedulerScheduledV3>>>, [u32]> & QueryableStorageEntry<ApiType, [u32]>;
/**
* Lookup from identity to the block number and index of the task.
**/
tests/src/interfaces/augment-types.tsdiffbeforeafterboth--- a/tests/src/interfaces/augment-types.ts
+++ b/tests/src/interfaces/augment-types.ts
@@ -1,7 +1,7 @@
// Auto-generated via `yarn polkadot-types-from-defs`, do not edit
/* eslint-disable */
-import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSupportWeightsWeightToFeeCoefficient, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUnqSchedulerCall, PalletUnqSchedulerError, PalletUnqSchedulerEvent, PalletUnqSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExData, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsRpcCollection, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipState, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from './default';
+import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSupportWeightsWeightToFeeCoefficient, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUniqueSchedulerCall, PalletUniqueSchedulerError, PalletUniqueSchedulerEvent, PalletUniqueSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExData, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsRpcCollection, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipState, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from './default';
import type { Data, StorageKey } from '@polkadot/types';
import type { BitVec, Bool, Bytes, I128, I16, I256, I32, I64, I8, Json, Null, OptionBool, Raw, Text, Type, U128, U16, U256, U32, U64, U8, USize, bool, i128, i16, i256, i32, i64, i8, u128, u16, u256, u32, u64, u8, usize } from '@polkadot/types-codec';
import type { AssetApproval, AssetApprovalKey, AssetBalance, AssetDestroyWitness, AssetDetails, AssetMetadata, TAssetBalance, TAssetDepositBalance } from '@polkadot/types/interfaces/assets';
@@ -819,10 +819,10 @@
PalletUniqueCall: PalletUniqueCall;
PalletUniqueError: PalletUniqueError;
PalletUniqueRawEvent: PalletUniqueRawEvent;
- PalletUnqSchedulerCall: PalletUnqSchedulerCall;
- PalletUnqSchedulerError: PalletUnqSchedulerError;
- PalletUnqSchedulerEvent: PalletUnqSchedulerEvent;
- PalletUnqSchedulerScheduledV3: PalletUnqSchedulerScheduledV3;
+ PalletUniqueSchedulerCall: PalletUniqueSchedulerCall;
+ PalletUniqueSchedulerError: PalletUniqueSchedulerError;
+ PalletUniqueSchedulerEvent: PalletUniqueSchedulerEvent;
+ PalletUniqueSchedulerScheduledV3: PalletUniqueSchedulerScheduledV3;
PalletVersion: PalletVersion;
PalletXcmCall: PalletXcmCall;
PalletXcmError: PalletXcmError;
tests/src/interfaces/default/types.tsdiffbeforeafterboth--- a/tests/src/interfaces/default/types.ts
+++ b/tests/src/interfaces/default/types.ts
@@ -1784,8 +1784,8 @@
readonly type: 'CollectionSponsorRemoved' | 'CollectionAdminAdded' | 'CollectionOwnedChanged' | 'CollectionSponsorSet' | 'SponsorshipConfirmed' | 'CollectionAdminRemoved' | 'AllowListAddressRemoved' | 'AllowListAddressAdded' | 'CollectionLimitSet' | 'CollectionPermissionSet';
}
-/** @name PalletUnqSchedulerCall */
-export interface PalletUnqSchedulerCall extends Enum {
+/** @name PalletUniqueSchedulerCall */
+export interface PalletUniqueSchedulerCall extends Enum {
readonly isScheduleNamed: boolean;
readonly asScheduleNamed: {
readonly id: U8aFixed;
@@ -1809,8 +1809,8 @@
readonly type: 'ScheduleNamed' | 'CancelNamed' | 'ScheduleNamedAfter';
}
-/** @name PalletUnqSchedulerError */
-export interface PalletUnqSchedulerError extends Enum {
+/** @name PalletUniqueSchedulerError */
+export interface PalletUniqueSchedulerError extends Enum {
readonly isFailedToSchedule: boolean;
readonly isNotFound: boolean;
readonly isTargetBlockNumberInPast: boolean;
@@ -1818,8 +1818,8 @@
readonly type: 'FailedToSchedule' | 'NotFound' | 'TargetBlockNumberInPast' | 'RescheduleNoChange';
}
-/** @name PalletUnqSchedulerEvent */
-export interface PalletUnqSchedulerEvent extends Enum {
+/** @name PalletUniqueSchedulerEvent */
+export interface PalletUniqueSchedulerEvent extends Enum {
readonly isScheduled: boolean;
readonly asScheduled: {
readonly when: u32;
@@ -1845,8 +1845,8 @@
readonly type: 'Scheduled' | 'Canceled' | 'Dispatched' | 'CallLookupFailed';
}
-/** @name PalletUnqSchedulerScheduledV3 */
-export interface PalletUnqSchedulerScheduledV3 extends Struct {
+/** @name PalletUniqueSchedulerScheduledV3 */
+export interface PalletUniqueSchedulerScheduledV3 extends Struct {
readonly maybeId: Option<U8aFixed>;
readonly priority: u8;
readonly call: FrameSupportScheduleMaybeHashed;
tests/src/interfaces/lookup.tsdiffbeforeafterboth--- a/tests/src/interfaces/lookup.ts
+++ b/tests/src/interfaces/lookup.ts
@@ -1526,9 +1526,9 @@
users: 'BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>'
},
/**
- * Lookup206: pallet_unq_scheduler::pallet::Call<T>
+ * Lookup206: pallet_unique_scheduler::pallet::Call<T>
**/
- PalletUnqSchedulerCall: {
+ PalletUniqueSchedulerCall: {
_enum: {
schedule_named: {
id: '[u8;16]',
@@ -2181,9 +2181,9 @@
}
},
/**
- * Lookup283: pallet_unq_scheduler::pallet::Event<T>
+ * Lookup283: pallet_unique_scheduler::pallet::Event<T>
**/
- PalletUnqSchedulerEvent: {
+ PalletUniqueSchedulerEvent: {
_enum: {
Scheduled: {
when: 'u32',
@@ -2589,9 +2589,9 @@
_enum: ['CollectionDecimalPointLimitExceeded', 'ConfirmUnsetSponsorFail', 'EmptyArgument']
},
/**
- * Lookup344: pallet_unq_scheduler::ScheduledV3<frame_support::traits::schedule::MaybeHashed<opal_runtime::Call, primitive_types::H256>, BlockNumber, opal_runtime::OriginCaller, sp_core::crypto::AccountId32>
+ * Lookup344: pallet_unique_scheduler::ScheduledV3<frame_support::traits::schedule::MaybeHashed<opal_runtime::Call, primitive_types::H256>, BlockNumber, opal_runtime::OriginCaller, sp_core::crypto::AccountId32>
**/
- PalletUnqSchedulerScheduledV3: {
+ PalletUniqueSchedulerScheduledV3: {
maybeId: 'Option<[u8;16]>',
priority: 'u8',
call: 'FrameSupportScheduleMaybeHashed',
@@ -2748,9 +2748,9 @@
**/
SpCoreVoid: 'Null',
/**
- * Lookup351: pallet_unq_scheduler::pallet::Error<T>
+ * Lookup351: pallet_unique_scheduler::pallet::Error<T>
**/
- PalletUnqSchedulerError: {
+ PalletUniqueSchedulerError: {
_enum: ['FailedToSchedule', 'NotFound', 'TargetBlockNumberInPast', 'RescheduleNoChange']
},
/**
tests/src/interfaces/registry.tsdiffbeforeafterboth--- a/tests/src/interfaces/registry.ts
+++ b/tests/src/interfaces/registry.ts
@@ -1,7 +1,7 @@
// Auto-generated via `yarn polkadot-types-from-defs`, do not edit
/* eslint-disable */
-import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSupportWeightsWeightToFeeCoefficient, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUnqSchedulerCall, PalletUnqSchedulerError, PalletUnqSchedulerEvent, PalletUnqSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExData, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsRpcCollection, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipState, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup';
+import type { CumulusPalletDmpQueueCall, CumulusPalletDmpQueueConfigData, CumulusPalletDmpQueueError, CumulusPalletDmpQueueEvent, CumulusPalletDmpQueuePageIndexData, CumulusPalletParachainSystemCall, CumulusPalletParachainSystemError, CumulusPalletParachainSystemEvent, CumulusPalletParachainSystemRelayStateSnapshotMessagingStateSnapshot, CumulusPalletXcmCall, CumulusPalletXcmError, CumulusPalletXcmEvent, CumulusPalletXcmOrigin, CumulusPalletXcmpQueueCall, CumulusPalletXcmpQueueError, CumulusPalletXcmpQueueEvent, CumulusPalletXcmpQueueInboundChannelDetails, CumulusPalletXcmpQueueInboundState, CumulusPalletXcmpQueueOutboundChannelDetails, CumulusPalletXcmpQueueOutboundState, CumulusPalletXcmpQueueQueueConfigData, CumulusPrimitivesParachainInherentParachainInherentData, EthbloomBloom, EthereumBlock, EthereumHeader, EthereumLog, EthereumReceiptEip658ReceiptData, EthereumReceiptReceiptV3, EthereumTransactionAccessListItem, EthereumTransactionEip1559Transaction, EthereumTransactionEip2930Transaction, EthereumTransactionLegacyTransaction, EthereumTransactionTransactionAction, EthereumTransactionTransactionSignature, EthereumTransactionTransactionV2, EthereumTypesHashH64, EvmCoreErrorExitError, EvmCoreErrorExitFatal, EvmCoreErrorExitReason, EvmCoreErrorExitRevert, EvmCoreErrorExitSucceed, FpRpcTransactionStatus, FrameSupportDispatchRawOrigin, FrameSupportPalletId, FrameSupportScheduleLookupError, FrameSupportScheduleMaybeHashed, FrameSupportTokensMiscBalanceStatus, FrameSupportWeightsDispatchClass, FrameSupportWeightsDispatchInfo, FrameSupportWeightsPays, FrameSupportWeightsPerDispatchClassU32, FrameSupportWeightsPerDispatchClassU64, FrameSupportWeightsPerDispatchClassWeightsPerClass, FrameSupportWeightsRuntimeDbWeight, FrameSupportWeightsWeightToFeeCoefficient, FrameSystemAccountInfo, FrameSystemCall, FrameSystemError, FrameSystemEvent, FrameSystemEventRecord, FrameSystemExtensionsCheckGenesis, FrameSystemExtensionsCheckNonce, FrameSystemExtensionsCheckSpecVersion, FrameSystemExtensionsCheckWeight, FrameSystemLastRuntimeUpgradeInfo, FrameSystemLimitsBlockLength, FrameSystemLimitsBlockWeights, FrameSystemLimitsWeightsPerClass, FrameSystemPhase, OpalRuntimeOriginCaller, OpalRuntimeRuntime, OrmlVestingModuleCall, OrmlVestingModuleError, OrmlVestingModuleEvent, OrmlVestingVestingSchedule, PalletBalancesAccountData, PalletBalancesBalanceLock, PalletBalancesCall, PalletBalancesError, PalletBalancesEvent, PalletBalancesReasons, PalletBalancesReleases, PalletBalancesReserveData, PalletCommonError, PalletCommonEvent, PalletEthereumCall, PalletEthereumError, PalletEthereumEvent, PalletEthereumFakeTransactionFinalizer, PalletEthereumRawOrigin, PalletEvmAccountBasicCrossAccountIdRepr, PalletEvmCall, PalletEvmCoderSubstrateError, PalletEvmContractHelpersError, PalletEvmContractHelpersSponsoringModeT, PalletEvmError, PalletEvmEvent, PalletEvmMigrationCall, PalletEvmMigrationError, PalletFungibleError, PalletInflationCall, PalletNonfungibleError, PalletNonfungibleItemData, PalletRefungibleError, PalletRefungibleItemData, PalletRmrkCoreCall, PalletRmrkCoreError, PalletRmrkCoreEvent, PalletRmrkEquipCall, PalletRmrkEquipError, PalletRmrkEquipEvent, PalletStructureCall, PalletStructureError, PalletStructureEvent, PalletSudoCall, PalletSudoError, PalletSudoEvent, PalletTemplateTransactionPaymentCall, PalletTemplateTransactionPaymentChargeTransactionPayment, PalletTimestampCall, PalletTransactionPaymentReleases, PalletTreasuryCall, PalletTreasuryError, PalletTreasuryEvent, PalletTreasuryProposal, PalletUniqueCall, PalletUniqueError, PalletUniqueRawEvent, PalletUniqueSchedulerCall, PalletUniqueSchedulerError, PalletUniqueSchedulerEvent, PalletUniqueSchedulerScheduledV3, PalletXcmCall, PalletXcmError, PalletXcmEvent, PalletXcmOrigin, PhantomTypeUpDataStructs, PolkadotCorePrimitivesInboundDownwardMessage, PolkadotCorePrimitivesInboundHrmpMessage, PolkadotCorePrimitivesOutboundHrmpMessage, PolkadotParachainPrimitivesXcmpMessageFormat, PolkadotPrimitivesV2AbridgedHostConfiguration, PolkadotPrimitivesV2AbridgedHrmpChannel, PolkadotPrimitivesV2PersistedValidationData, PolkadotPrimitivesV2UpgradeRestriction, RmrkTraitsBaseBaseInfo, RmrkTraitsCollectionCollectionInfo, RmrkTraitsNftAccountIdOrCollectionNftTuple, RmrkTraitsNftNftChild, RmrkTraitsNftNftInfo, RmrkTraitsNftRoyaltyInfo, RmrkTraitsPartEquippableList, RmrkTraitsPartFixedPart, RmrkTraitsPartPartType, RmrkTraitsPartSlotPart, RmrkTraitsPropertyPropertyInfo, RmrkTraitsResourceBasicResource, RmrkTraitsResourceComposableResource, RmrkTraitsResourceResourceInfo, RmrkTraitsResourceResourceTypes, RmrkTraitsResourceSlotResource, RmrkTraitsTheme, RmrkTraitsThemeThemeProperty, SpCoreEcdsaSignature, SpCoreEd25519Signature, SpCoreSr25519Signature, SpCoreVoid, SpRuntimeArithmeticError, SpRuntimeDigest, SpRuntimeDigestDigestItem, SpRuntimeDispatchError, SpRuntimeModuleError, SpRuntimeMultiSignature, SpRuntimeTokenError, SpRuntimeTransactionalError, SpTrieStorageProof, SpVersionRuntimeVersion, UpDataStructsAccessMode, UpDataStructsCollection, UpDataStructsCollectionLimits, UpDataStructsCollectionMode, UpDataStructsCollectionPermissions, UpDataStructsCollectionStats, UpDataStructsCreateCollectionData, UpDataStructsCreateFungibleData, UpDataStructsCreateItemData, UpDataStructsCreateItemExData, UpDataStructsCreateNftData, UpDataStructsCreateNftExData, UpDataStructsCreateReFungibleData, UpDataStructsCreateRefungibleExData, UpDataStructsNestingPermissions, UpDataStructsOwnerRestrictedSet, UpDataStructsProperties, UpDataStructsPropertiesMapBoundedVec, UpDataStructsPropertiesMapPropertyPermission, UpDataStructsProperty, UpDataStructsPropertyKeyPermission, UpDataStructsPropertyPermission, UpDataStructsRpcCollection, UpDataStructsSponsoringRateLimit, UpDataStructsSponsorshipState, UpDataStructsTokenChild, UpDataStructsTokenData, XcmDoubleEncoded, XcmV0Junction, XcmV0JunctionBodyId, XcmV0JunctionBodyPart, XcmV0JunctionNetworkId, XcmV0MultiAsset, XcmV0MultiLocation, XcmV0Order, XcmV0OriginKind, XcmV0Response, XcmV0Xcm, XcmV1Junction, XcmV1MultiAsset, XcmV1MultiLocation, XcmV1MultiassetAssetId, XcmV1MultiassetAssetInstance, XcmV1MultiassetFungibility, XcmV1MultiassetMultiAssetFilter, XcmV1MultiassetMultiAssets, XcmV1MultiassetWildFungibility, XcmV1MultiassetWildMultiAsset, XcmV1MultilocationJunctions, XcmV1Order, XcmV1Response, XcmV1Xcm, XcmV2Instruction, XcmV2Response, XcmV2TraitsError, XcmV2TraitsOutcome, XcmV2WeightLimit, XcmV2Xcm, XcmVersionedMultiAssets, XcmVersionedMultiLocation, XcmVersionedXcm } from '@polkadot/types/lookup';
declare module '@polkadot/types/types/registry' {
export interface InterfaceTypes {
@@ -133,10 +133,10 @@
PalletUniqueCall: PalletUniqueCall;
PalletUniqueError: PalletUniqueError;
PalletUniqueRawEvent: PalletUniqueRawEvent;
- PalletUnqSchedulerCall: PalletUnqSchedulerCall;
- PalletUnqSchedulerError: PalletUnqSchedulerError;
- PalletUnqSchedulerEvent: PalletUnqSchedulerEvent;
- PalletUnqSchedulerScheduledV3: PalletUnqSchedulerScheduledV3;
+ PalletUniqueSchedulerCall: PalletUniqueSchedulerCall;
+ PalletUniqueSchedulerError: PalletUniqueSchedulerError;
+ PalletUniqueSchedulerEvent: PalletUniqueSchedulerEvent;
+ PalletUniqueSchedulerScheduledV3: PalletUniqueSchedulerScheduledV3;
PalletXcmCall: PalletXcmCall;
PalletXcmError: PalletXcmError;
PalletXcmEvent: PalletXcmEvent;
tests/src/interfaces/types-lookup.tsdiffbeforeafterboth--- a/tests/src/interfaces/types-lookup.ts
+++ b/tests/src/interfaces/types-lookup.ts
@@ -1650,8 +1650,8 @@
readonly users: BTreeMap<PalletEvmAccountBasicCrossAccountIdRepr, u128>;
}
- /** @name PalletUnqSchedulerCall (206) */
- export interface PalletUnqSchedulerCall extends Enum {
+ /** @name PalletUniqueSchedulerCall (206) */
+ export interface PalletUniqueSchedulerCall extends Enum {
readonly isScheduleNamed: boolean;
readonly asScheduleNamed: {
readonly id: U8aFixed;
@@ -2350,8 +2350,8 @@
readonly type: 'CollectionSponsorRemoved' | 'CollectionAdminAdded' | 'CollectionOwnedChanged' | 'CollectionSponsorSet' | 'SponsorshipConfirmed' | 'CollectionAdminRemoved' | 'AllowListAddressRemoved' | 'AllowListAddressAdded' | 'CollectionLimitSet' | 'CollectionPermissionSet';
}
- /** @name PalletUnqSchedulerEvent (283) */
- export interface PalletUnqSchedulerEvent extends Enum {
+ /** @name PalletUniqueSchedulerEvent (283) */
+ export interface PalletUniqueSchedulerEvent extends Enum {
readonly isScheduled: boolean;
readonly asScheduled: {
readonly when: u32;
@@ -2805,8 +2805,8 @@
readonly type: 'CollectionDecimalPointLimitExceeded' | 'ConfirmUnsetSponsorFail' | 'EmptyArgument';
}
- /** @name PalletUnqSchedulerScheduledV3 (344) */
- export interface PalletUnqSchedulerScheduledV3 extends Struct {
+ /** @name PalletUniqueSchedulerScheduledV3 (344) */
+ export interface PalletUniqueSchedulerScheduledV3 extends Struct {
readonly maybeId: Option<U8aFixed>;
readonly priority: u8;
readonly call: FrameSupportScheduleMaybeHashed;
@@ -2864,8 +2864,8 @@
/** @name SpCoreVoid (350) */
export type SpCoreVoid = Null;
- /** @name PalletUnqSchedulerError (351) */
- export interface PalletUnqSchedulerError extends Enum {
+ /** @name PalletUniqueSchedulerError (351) */
+ export interface PalletUniqueSchedulerError extends Enum {
readonly isFailedToSchedule: boolean;
readonly isNotFound: boolean;
readonly isTargetBlockNumberInPast: boolean;
tests/src/nesting/properties.test.tsdiffbeforeafterboth--- a/tests/src/nesting/properties.test.ts
+++ b/tests/src/nesting/properties.test.ts
@@ -106,6 +106,58 @@
});
});
+ it('Check valid names for collection properties keys', async () => {
+ await usingApi(async api => {
+ const events = await executeTransaction(api, bob, api.tx.unique.createCollectionEx({mode: 'NFT'}));
+ const {collectionId} = getCreateCollectionResult(events);
+
+ // alpha symbols
+ await expect(executeTransaction(
+ api,
+ bob,
+ api.tx.unique.setCollectionProperties(collectionId, [{key: 'alpha'}]),
+ )).to.not.be.rejected;
+
+ // numeric symbols
+ await expect(executeTransaction(
+ api,
+ bob,
+ api.tx.unique.setCollectionProperties(collectionId, [{key: '123'}]),
+ )).to.not.be.rejected;
+
+ // underscore symbol
+ await expect(executeTransaction(
+ api,
+ bob,
+ api.tx.unique.setCollectionProperties(collectionId, [{key: 'black_hole'}]),
+ )).to.not.be.rejected;
+
+ // dash symbol
+ await expect(executeTransaction(
+ api,
+ bob,
+ api.tx.unique.setCollectionProperties(collectionId, [{key: 'semi-automatic'}]),
+ )).to.not.be.rejected;
+
+ // underscore symbol
+ await expect(executeTransaction(
+ api,
+ bob,
+ api.tx.unique.setCollectionProperties(collectionId, [{key: 'build.rs'}]),
+ )).to.not.be.rejected;
+
+ const propertyKeys = ['alpha', '123', 'black_hole', 'semi-automatic', 'build.rs'];
+ const properties = (await api.rpc.unique.collectionProperties(collectionId, propertyKeys)).toHuman();
+ expect(properties).to.be.deep.equal([
+ {key: 'alpha', value: ''},
+ {key: '123', value: ''},
+ {key: 'black_hole', value: ''},
+ {key: 'semi-automatic', value: ''},
+ {key: 'build.rs', value: ''},
+ ]);
+ });
+ });
+
it('Changes properties of a collection', async () => {
await usingApi(async api => {
const collection = await createCollectionExpectSuccess();
@@ -241,7 +293,7 @@
const invalidProperties = [
[{key: 'electron', value: 'negative'}, {key: 'string theory', value: 'understandable'}],
- [{key: 'Mr.Sandman', value: 'Bring me a gene'}],
+ [{key: 'Mr/Sandman', value: 'Bring me a gene'}],
[{key: 'déjà vu', value: 'hmm...'}],
];
tests/src/removeCollectionAdmin.test.tsdiffbeforeafterboth--- a/tests/src/removeCollectionAdmin.test.ts
+++ b/tests/src/removeCollectionAdmin.test.ts
@@ -118,11 +118,17 @@
const bob = privateKeyWrapper('//Bob');
const charlie = privateKeyWrapper('//Charlie');
+ const addBobAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(bob.address));
+ await submitTransactionAsync(alice, addBobAdminTx);
+ const addCharlieAdminTx = api.tx.unique.addCollectionAdmin(collectionId, normalizeAccountId(charlie.address));
+ await submitTransactionAsync(alice, addCharlieAdminTx);
+
const adminListAfterAddAdmin = await getAdminList(api, collectionId);
expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
+ expect(adminListAfterAddAdmin).to.be.deep.contains(normalizeAccountId(charlie.address));
const removeAdminTx = api.tx.unique.removeCollectionAdmin(collectionId, normalizeAccountId(bob.address));
- await expect(submitTransactionAsync(charlie, removeAdminTx)).to.be.rejected;
+ await expect(submitTransactionExpectFailAsync(charlie, removeAdminTx)).to.be.rejected;
const adminListAfterRemoveAdmin = await getAdminList(api, collectionId);
expect(adminListAfterRemoveAdmin).to.be.deep.contains(normalizeAccountId(bob.address));
tests/src/setCollectionLimits.test.tsdiffbeforeafterboth--- a/tests/src/setCollectionLimits.test.ts
+++ b/tests/src/setCollectionLimits.test.ts
@@ -46,6 +46,7 @@
before(async () => {
await usingApi(async (api, privateKeyWrapper) => {
alice = privateKeyWrapper('//Alice');
+ bob = privateKeyWrapper('//Bob');
collectionIdForTesting = await createCollectionExpectSuccess({name: 'A', description: 'B', tokenPrefix: 'C', mode: {type: 'NFT'}});
});
});
@@ -115,6 +116,21 @@
});
});
+ it('execute setCollectionLimits from admin collection', async () => {
+ await addCollectionAdminExpectSuccess(alice, collectionIdForTesting, bob.address);
+ await usingApi(async (api: ApiPromise) => {
+ tx = api.tx.unique.setCollectionLimits(
+ collectionIdForTesting,
+ {
+ accountTokenOwnershipLimit,
+ sponsoredDataSize,
+ // sponsoredMintSize,
+ tokenLimit,
+ },
+ );
+ await expect(submitTransactionAsync(bob, tx)).to.be.not.rejected;
+ });
+ });
});
describe('setCollectionLimits negative', () => {
@@ -143,21 +159,6 @@
});
});
it('execute setCollectionLimits from user who is not owner of this collection', async () => {
- await usingApi(async (api: ApiPromise) => {
- tx = api.tx.unique.setCollectionLimits(
- collectionIdForTesting,
- {
- accountTokenOwnershipLimit,
- sponsoredDataSize,
- // sponsoredMintSize,
- tokenLimit,
- },
- );
- await expect(submitTransactionExpectFailAsync(bob, tx)).to.be.rejected;
- });
- });
- it('execute setCollectionLimits from admin collection', async () => {
- await addCollectionAdminExpectSuccess(alice, collectionIdForTesting, bob.address);
await usingApi(async (api: ApiPromise) => {
tx = api.tx.unique.setCollectionLimits(
collectionIdForTesting,
tests/src/setCollectionSponsor.test.tsdiffbeforeafterboth--- a/tests/src/setCollectionSponsor.test.ts
+++ b/tests/src/setCollectionSponsor.test.ts
@@ -65,6 +65,11 @@
await setCollectionSponsorExpectSuccess(collectionId, bob.address);
await setCollectionSponsorExpectSuccess(collectionId, charlie.address);
});
+ it('Collection admin add sponsor', async () => {
+ const collectionId = await createCollectionExpectSuccess();
+ await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
+ await setCollectionSponsorExpectSuccess(collectionId, charlie.address, '//Bob');
+ });
});
describe('(!negative test!) integration test: ext. setCollectionSponsor():', () => {
@@ -93,10 +98,5 @@
const collectionId = await createCollectionExpectSuccess();
await destroyCollectionExpectSuccess(collectionId);
await setCollectionSponsorExpectFailure(collectionId, bob.address);
- });
- it('(!negative test!) Collection admin add sponsor', async () => {
- const collectionId = await createCollectionExpectSuccess();
- await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
- await setCollectionSponsorExpectFailure(collectionId, charlie.address, '//Bob');
});
});
tests/src/setMintPermission.test.tsdiffbeforeafterboth--- a/tests/src/setMintPermission.test.ts
+++ b/tests/src/setMintPermission.test.ts
@@ -67,6 +67,14 @@
await setMintPermissionExpectSuccess(alice, collectionId, false);
});
});
+
+ it('Collection admin success on set', async () => {
+ await usingApi(async () => {
+ const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
+ await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
+ await setMintPermissionExpectSuccess(bob, collectionId, true);
+ });
+ });
});
describe('Negative Integration Test setMintPermission', () => {
@@ -100,14 +108,6 @@
const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
await enableAllowListExpectSuccess(alice, collectionId);
await setMintPermissionExpectFailure(bob, collectionId, true);
- });
-
- it('Collection admin fails on set', async () => {
- await usingApi(async () => {
- const collectionId = await createCollectionExpectSuccess({mode: {type: 'NFT'}});
- await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
- await setMintPermissionExpectFailure(bob, collectionId, true);
- });
});
it('ensure non-allow-listed non-privileged address can\'t mint tokens', async () => {
tests/src/setPublicAccessMode.test.tsdiffbeforeafterboth--- a/tests/src/setPublicAccessMode.test.ts
+++ b/tests/src/setPublicAccessMode.test.ts
@@ -103,22 +103,23 @@
await expect(submitTransactionExpectFailAsync(bob, tx)).to.be.rejected;
});
});
-});
-describe('Negative Integration Test ext. collection admin setPublicAccessMode(): ', () => {
- before(async () => {
- await usingApi(async (api, privateKeyWrapper) => {
- alice = privateKeyWrapper('//Alice');
- bob = privateKeyWrapper('//Bob');
- });
- });
it('setPublicAccessMode by collection admin', async () => {
await usingApi(async (api: ApiPromise) => {
// tslint:disable-next-line: no-bitwise
const collectionId = await createCollectionExpectSuccess();
await addCollectionAdminExpectSuccess(alice, collectionId, bob.address);
const tx = api.tx.unique.setCollectionPermissions(collectionId, {access: 'AllowList'});
- await expect(submitTransactionExpectFailAsync(bob, tx)).to.be.rejected;
+ await expect(submitTransactionExpectFailAsync(bob, tx)).to.be.not.rejected;
+ });
+ });
+});
+
+describe('Negative Integration Test ext. collection admin setPublicAccessMode(): ', () => {
+ before(async () => {
+ await usingApi(async (api, privateKeyWrapper) => {
+ alice = privateKeyWrapper('//Alice');
+ bob = privateKeyWrapper('//Bob');
});
});
});