difftreelog
feat add conditional supportInterface for ERC721Metadata
in: master
29 files changed
pallets/common/src/erc.rsdiffbeforeafterboth685 property_key_from_bytes(b"parentNft").expect(EXPECT_CONVERT_ERROR)685 property_key_from_bytes(b"parentNft").expect(EXPECT_CONVERT_ERROR)686 }686 }687688 /// Key "parentNft".689 pub fn erc721_metadata() -> up_data_structs::PropertyKey {690 property_key_from_bytes(b"ERC721Metadata").expect(EXPECT_CONVERT_ERROR)691 }687 }692 }688693689 /// Values.694 /// Values.693 /// Value "ERC721Metadata".698 /// Value "ERC721Metadata".694 pub const ERC721_METADATA: &[u8] = b"ERC721Metadata";699 pub const ERC721_METADATA: &[u8] = b"ERC721Metadata";700701 /// Value "1" ERC721 metadata supported.702 pub const ERC721_METADATA_SUPPORTED: &[u8] = b"1";703704 /// Value "0" ERC721 metadata supported.705 pub const ERC721_METADATA_UNSUPPORTED: &[u8] = b"0";695706696 /// Value for [`ERC721_METADATA`].707 /// Value for [`ERC721_METADATA`].697 pub fn erc721() -> up_data_structs::PropertyValue {708 pub fn erc721() -> up_data_structs::PropertyValue {698 property_value_from_bytes(ERC721_METADATA).expect(EXPECT_CONVERT_ERROR)709 property_value_from_bytes(ERC721_METADATA).expect(EXPECT_CONVERT_ERROR)699 }710 }711712 /// Value for [`ERC721_METADATA`].713 pub fn erc721_metadata_supported() -> up_data_structs::PropertyValue {714 property_value_from_bytes(ERC721_METADATA_SUPPORTED).expect(EXPECT_CONVERT_ERROR)715 }700 }716 }701717702 /// Convert `byte` to [`PropertyKey`].718 /// Convert `byte` to [`PropertyKey`].pallets/nonfungible/src/erc.rsdiffbeforeafterboth232 if !url.is_empty() {232 if !url.is_empty() {233 return Ok(url);233 return Ok(url);234 }234 }235 } else if !is_erc721_metadata_compatible::<T>(self.id) {235 } else if !self.supports_metadata() {236 return Err("tokenURI not set".into());236 return Err("tokenURI not set".into());237 }237 }238238550 Err("Property tokenURI not found".into())550 Err("Property tokenURI not found".into())551}551}552553fn is_erc721_metadata_compatible<T: Config>(collection_id: CollectionId) -> bool {554 if let Some(shema_name) =555 pallet_common::Pallet::<T>::get_collection_property(collection_id, &key::schema_name())556 {557 let shema_name = shema_name.into_inner();558 shema_name == property_value::ERC721_METADATA559 } else {560 false561 }562}563552564fn get_token_permission<T: Config>(553fn get_token_permission<T: Config>(565 collection_id: CollectionId,554 collection_id: CollectionId,577 Ok(a)566 Ok(a)578}567}579580fn has_token_permission<T: Config>(collection_id: CollectionId, key: &PropertyKey) -> bool {581 if let Ok(token_property_permissions) =582 CollectionPropertyPermissions::<T>::try_get(collection_id)583 {584 return token_property_permissions.contains_key(key);585 }586587 false588}589568590/// @title Unique extensions for ERC721.569/// @title Unique extensions for ERC721.591#[solidity_interface(name = ERC721UniqueExtensions)]570#[solidity_interface(name = ERC721UniqueExtensions)]731 name = UniqueNFT,710 name = UniqueNFT,732 is(711 is(733 ERC721,712 ERC721,734 ERC721Metadata,713 ERC721Metadata(if(this.supports_metadata())),735 ERC721Enumerable,714 ERC721Enumerable,736 ERC721UniqueExtensions,715 ERC721UniqueExtensions,737 ERC721Mintable,716 ERC721Mintable,pallets/nonfungible/src/lib.rsdiffbeforeafterboth108use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};108use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};109use pallet_common::{109use pallet_common::{110 Error as CommonError, Pallet as PalletCommon, Event as CommonEvent, CollectionHandle,110 Error as CommonError, Pallet as PalletCommon, Event as CommonEvent, CollectionHandle,111 erc::static_property::{key, value},111 eth::collection_id_to_address,112 eth::collection_id_to_address,112};113};113use pallet_structure::{Pallet as PalletStructure, Error as StructureError};114use pallet_structure::{Pallet as PalletStructure, Error as StructureError};296 }297 }297}298}299300impl<T: Config> NonfungibleHandle<T> {301 pub fn supports_metadata(&self) -> bool {302 if let Some(erc721_metadata) =303 pallet_common::Pallet::<T>::get_collection_property(self.id, &key::erc721_metadata())304 {305 *erc721_metadata.into_inner() == *value::ERC721_METADATA_SUPPORTED306 } else {307 false308 }309 }310}311298impl<T: Config> WithRecorder<T> for NonfungibleHandle<T> {312impl<T: Config> WithRecorder<T> for NonfungibleHandle<T> {299 fn recorder(&self) -> &SubstrateRecorder<T> {313 fn recorder(&self) -> &SubstrateRecorder<T> {pallets/refungible/src/erc.rsdiffbeforeafterboth228 if !url.is_empty() {228 if !url.is_empty() {229 return Ok(url);229 return Ok(url);230 }230 }231 } else if !is_erc721_metadata_compatible::<T>(self.id) {231 } else if !self.supports_metadata() {232 return Err("tokenURI not set".into());232 return Err("tokenURI not set".into());233 }233 }234234578 Err("Property tokenURI not found".into())578 Err("Property tokenURI not found".into())579}579}580581fn is_erc721_metadata_compatible<T: Config>(collection_id: CollectionId) -> bool {582 if let Some(shema_name) =583 pallet_common::Pallet::<T>::get_collection_property(collection_id, &key::schema_name())584 {585 let shema_name = shema_name.into_inner();586 shema_name == property_value::ERC721_METADATA587 } else {588 false589 }590}591580592fn get_token_permission<T: Config>(581fn get_token_permission<T: Config>(593 collection_id: CollectionId,582 collection_id: CollectionId,780 name = UniqueRefungible,769 name = UniqueRefungible,781 is(770 is(782 ERC721,771 ERC721,783 ERC721Metadata,772 ERC721Metadata(if(this.supports_metadata())),784 ERC721Enumerable,773 ERC721Enumerable,785 ERC721UniqueExtensions,774 ERC721UniqueExtensions,786 ERC721Mintable,775 ERC721Mintable,pallets/refungible/src/lib.rsdiffbeforeafterboth929293use codec::{Encode, Decode, MaxEncodedLen};93use codec::{Encode, Decode, MaxEncodedLen};94use core::ops::Deref;94use core::ops::Deref;95use derivative::Derivative;95use evm_coder::ToLog;96use evm_coder::ToLog;96use frame_support::{97use frame_support::{97 BoundedVec, ensure, fail, storage::with_transaction, transactional, pallet_prelude::ConstU32,98 BoundedBTreeMap, BoundedVec, ensure, fail, storage::with_transaction, transactional,99 pallet_prelude::ConstU32,98};100};99use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};101use pallet_evm::{account::CrossAccountId, Pallet as PalletEvm};100use pallet_evm_coder_substrate::WithRecorder;102use pallet_evm_coder_substrate::WithRecorder;101use pallet_common::{103use pallet_common::{102 CommonCollectionOperations, Error as CommonError, eth::collection_id_to_address,104 CommonCollectionOperations,105 erc::static_property::{key, value},106 Error as CommonError,107 eth::collection_id_to_address,103 Event as CommonEvent, Pallet as PalletCommon,108 Event as CommonEvent, Pallet as PalletCommon,113 MAX_REFUNGIBLE_PIECES, Property, PropertyKey, PropertyKeyPermission, PropertyPermission,118 MAX_REFUNGIBLE_PIECES, Property, PropertyKey, PropertyKeyPermission, PropertyPermission,114 PropertyScope, PropertyValue, TokenId, TrySetProperty,119 PropertyScope, PropertyValue, TokenId, TrySetProperty,115};120};116use frame_support::BoundedBTreeMap;117use derivative::Derivative;118121119pub use pallet::*;122pub use pallet::*;120#[cfg(feature = "runtime-benchmarks")]123#[cfg(feature = "runtime-benchmarks")]301 }304 }302}305}306307impl<T: Config> RefungibleHandle<T> {308 pub fn supports_metadata(&self) -> bool {309 if let Some(erc721_metadata) =310 pallet_common::Pallet::<T>::get_collection_property(self.id, &key::erc721_metadata())311 {312 *erc721_metadata.into_inner() == *value::ERC721_METADATA_SUPPORTED313 } else {314 false315 }316 }317}303318304impl<T: Config> Deref for RefungibleHandle<T> {319impl<T: Config> Deref for RefungibleHandle<T> {305 type Target = pallet_common::CollectionHandle<T>;320 type Target = pallet_common::CollectionHandle<T>;pallets/unique/src/eth/mod.rsdiffbeforeafterboth130 })130 })131 .map_err(|e| Error::Revert(format!("{:?}", e)))?;131 .map_err(|e| Error::Revert(format!("{:?}", e)))?;132133 properties134 .try_push(up_data_structs::Property {135 key: key::erc721_metadata(),136 value: property_value::erc721_metadata_supported(),137 })138 .map_err(|e| Error::Revert(format!("{:?}", e)))?;132139133 if !base_uri_value.is_empty() {140 if !base_uri_value.is_empty() {134 properties141 properties212 /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications219 /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications213 /// @return address Address of the newly created collection220 /// @return address Address of the newly created collection214 #[weight(<SelfWeightOf<T>>::create_collection())]221 #[weight(<SelfWeightOf<T>>::create_collection())]222 #[solidity(rename_selector = "createNFTCollection")]215 fn create_nonfungible_collection(223 fn create_nft_collection(216 &mut self,224 &mut self,217 caller: caller,225 caller: caller,218 value: value,226 value: value,239 let address = pallet_common::eth::collection_id_to_address(collection_id);247 let address = pallet_common::eth::collection_id_to_address(collection_id);240 Ok(address)248 Ok(address)241 }249 }250 /// Create an NFT collection251 /// @param name Name of the collection252 /// @param description Informative description of the collection253 /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications254 /// @return address Address of the newly created collection255 #[weight(<SelfWeightOf<T>>::create_collection())]256 #[deprecated(note = "mathod was renamed to `create_nft_collection`, prefer it instead")]257 fn create_nonfungible_collection(258 &mut self,259 caller: caller,260 value: value,261 name: string,262 description: string,263 token_prefix: string,264 ) -> Result<address> {265 self.create_nft_collection(caller, value, name, description, token_prefix)266 }242267243 #[weight(<SelfWeightOf<T>>::create_collection())]268 #[weight(<SelfWeightOf<T>>::create_collection())]244 #[solidity(rename_selector = "createERC721MetadataCompatibleCollection")]269 #[solidity(rename_selector = "createERC721MetadataNFTCollection")]245 fn create_nonfungible_collection_with_properties(270 fn create_nonfungible_collection_with_properties(246 &mut self,271 &mut self,247 caller: caller,272 caller: caller,273298274 #[weight(<SelfWeightOf<T>>::create_collection())]299 #[weight(<SelfWeightOf<T>>::create_collection())]275 #[solidity(rename_selector = "createRFTCollection")]300 #[solidity(rename_selector = "createRFTCollection")]276 fn create_refungible_collection(301 fn create_rft_collection(302 &mut self,303 caller: caller,304 value: value,305 name: string,306 description: string,307 token_prefix: string,308 ) -> Result<address> {309 create_refungible_collection_internal::<T>(310 caller,311 value,312 name,313 description,314 token_prefix,315 Default::default(),316 false,317 )318 }319320 #[weight(<SelfWeightOf<T>>::create_collection())]321 #[deprecated(note = "mathod was renamed to `create_rft_collection`, prefer it instead")]322 fn create_refungible_collection(277 &mut self,323 &mut self,278 caller: caller,324 caller: caller,279 value: value,325 value: value,293 }339 }294340295 #[weight(<SelfWeightOf<T>>::create_collection())]341 #[weight(<SelfWeightOf<T>>::create_collection())]296 #[solidity(rename_selector = "createERC721MetadataCompatibleRFTCollection")]342 #[solidity(rename_selector = "createERC721MetadataRFTCollection")]297 fn create_refungible_collection_with_properties(343 fn create_refungible_collection_with_properties(298 &mut self,344 &mut self,299 caller: caller,345 caller: caller,pallets/unique/src/eth/stubs/CollectionHelpers.rawdiffbeforeafterbothbinary blob — no preview
pallets/unique/src/eth/stubs/CollectionHelpers.soldiffbeforeafterboth23}23}242425/// @title Contract, which allows users to operate with collections25/// @title Contract, which allows users to operate with collections26/// @dev the ERC-165 identifier for this interface is 0x5ad4f44026/// @dev the ERC-165 identifier for this interface is 0xf62c7aa927contract CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {27contract CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {28 /// Create an NFT collection28 /// Create an NFT collection29 /// @param name Name of the collection29 /// @param name Name of the collection30 /// @param description Informative description of the collection30 /// @param description Informative description of the collection31 /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications32 /// @return address Address of the newly created collection33 /// @dev EVM selector for this function is: 0x844af658,34 /// or in textual repr: createNFTCollection(string,string,string)35 function createNFTCollection(36 string memory name,37 string memory description,38 string memory tokenPrefix39 ) public payable returns (address) {40 require(false, stub_error);41 name;42 description;43 tokenPrefix;44 dummy = 0;45 return 0x0000000000000000000000000000000000000000;46 }4748 /// Create an NFT collection49 /// @param name Name of the collection50 /// @param description Informative description of the collection31 /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications51 /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications32 /// @return address Address of the newly created collection52 /// @return address Address of the newly created collection33 /// @dev EVM selector for this function is: 0xe34a6844,53 /// @dev EVM selector for this function is: 0xe34a6844,45 return 0x0000000000000000000000000000000000000000;65 return 0x0000000000000000000000000000000000000000;46 }66 }476748 /// @dev EVM selector for this function is: 0xa634a5f9,68 /// @dev EVM selector for this function is: 0xd1df968c,49 /// or in textual repr: createERC721MetadataCompatibleCollection(string,string,string,string)69 /// or in textual repr: createERC721MetadataNFTCollection(string,string,string,string)50 function createERC721MetadataCompatibleCollection(70 function createERC721MetadataNFTCollection(51 string memory name,71 string memory name,52 string memory description,72 string memory description,53 string memory tokenPrefix,73 string memory tokenPrefix,77 return 0x0000000000000000000000000000000000000000;97 return 0x0000000000000000000000000000000000000000;78 }98 }99100 /// @dev EVM selector for this function is: 0x44a68ad5,101 /// or in textual repr: createRefungibleCollection(string,string,string)102 function createRefungibleCollection(103 string memory name,104 string memory description,105 string memory tokenPrefix106 ) public payable returns (address) {107 require(false, stub_error);108 name;109 description;110 tokenPrefix;111 dummy = 0;112 return 0x0000000000000000000000000000000000000000;113 }7911480 /// @dev EVM selector for this function is: 0xa5596388,115 /// @dev EVM selector for this function is: 0xbea6a299,81 /// or in textual repr: createERC721MetadataCompatibleRFTCollection(string,string,string,string)116 /// or in textual repr: createERC721MetadataRFTCollection(string,string,string,string)82 function createERC721MetadataCompatibleRFTCollection(117 function createERC721MetadataRFTCollection(83 string memory name,118 string memory name,84 string memory description,119 string memory description,85 string memory tokenPrefix,120 string memory tokenPrefix,tests/src/deprecated-helpers/eth/helpers.tsdiffbeforeafterboth150}150}151151152152153export async function createNonfungibleCollection(api: ApiPromise, web3: Web3, owner: string) {153export async function createNFTCollection(api: ApiPromise, web3: Web3, owner: string) {154 const collectionHelper = evmCollectionHelpers(web3, owner);154 const collectionHelper = evmCollectionHelpers(web3, owner);155 const result = await collectionHelper.methods155 const result = await collectionHelper.methods156 .createNonfungibleCollection('A', 'B', 'C')156 .createNFTCollection('A', 'B', 'C')157 .send({value: Number(2n * UNIQUE)});157 .send({value: Number(2n * UNIQUE)});158 return await getCollectionAddressFromResult(api, result);158 return await getCollectionAddressFromResult(api, result);159}159}tests/src/deprecated-helpers/helpers.tsdiffbeforeafterboth433 mode: {type: 'NFT'},433 mode: {type: 'NFT'},434 name: 'name',434 name: 'name',435 tokenPrefix: 'prefix',435 tokenPrefix: 'prefix',436 properties: [{key: 'ERC721Metadata', value: '1'}],436};437};437438438export async function439export async function441 sender: IKeyringPair,442 sender: IKeyringPair,442 params: Partial<CreateCollectionParams> = {},443 params: Partial<CreateCollectionParams> = {},443): Promise<CreateCollectionResult> {444): Promise<CreateCollectionResult> {444 const {name, description, mode, tokenPrefix} = {...defaultCreateCollectionParams, ...params};445 const {name, description, mode, tokenPrefix, properties} = {...defaultCreateCollectionParams, ...params};445446446 let modeprm = {};447 let modeprm = {};447 if (mode.type === 'NFT') {448 if (mode.type === 'NFT') {457 description: strToUTF16(description),458 description: strToUTF16(description),458 tokenPrefix: strToUTF16(tokenPrefix),459 tokenPrefix: strToUTF16(tokenPrefix),459 mode: modeprm as any,460 mode: modeprm as any,461 properties,460 });462 });461 const events = await executeTransaction(api, sender, tx);463 const events = await executeTransaction(api, sender, tx);462 return getCreateCollectionResult(events);464 return getCreateCollectionResult(events);tests/src/eth/allowlist.test.tsdiffbeforeafterboth78 const owner = await helper.eth.createAccountWithBalance(donor);78 const owner = await helper.eth.createAccountWithBalance(donor);79 const user = helper.eth.createAccount();79 const user = helper.eth.createAccount();808081 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');81 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');82 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);82 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);838384 expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;84 expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;94 // const owner = await helper.eth.createAccountWithBalance(donor);94 // const owner = await helper.eth.createAccountWithBalance(donor);95 // const user = donor;95 // const user = donor;969697 // const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');97 // const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');98 // const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);98 // const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);9999100 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;100 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;110 const notOwner = await helper.eth.createAccountWithBalance(donor);110 const notOwner = await helper.eth.createAccountWithBalance(donor);111 const user = helper.eth.createAccount();111 const user = helper.eth.createAccount();112112113 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');113 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');114 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);114 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);115115116 expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;116 expect(await collectionEvm.methods.allowed(user).call({from: owner})).to.be.false;129 // const notOwner = await helper.eth.createAccountWithBalance(donor);129 // const notOwner = await helper.eth.createAccountWithBalance(donor);130 // const user = donor;130 // const user = donor;131131132 // const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');132 // const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');133 // const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);133 // const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);134134135 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;135 // expect(await helper.collection.allowed(collectionId, {Substrate: user.address})).to.be.false;tests/src/eth/api/CollectionHelpers.soldiffbeforeafterboth18}18}191920/// @title Contract, which allows users to operate with collections20/// @title Contract, which allows users to operate with collections21/// @dev the ERC-165 identifier for this interface is 0x5ad4f44021/// @dev the ERC-165 identifier for this interface is 0xf62c7aa922interface CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {22interface CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {23 /// Create an NFT collection23 /// Create an NFT collection24 /// @param name Name of the collection24 /// @param name Name of the collection25 /// @param description Informative description of the collection25 /// @param description Informative description of the collection26 /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications27 /// @return address Address of the newly created collection28 /// @dev EVM selector for this function is: 0x844af658,29 /// or in textual repr: createNFTCollection(string,string,string)30 function createNFTCollection(31 string memory name,32 string memory description,33 string memory tokenPrefix34 ) external payable returns (address);3536 /// Create an NFT collection37 /// @param name Name of the collection38 /// @param description Informative description of the collection26 /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications39 /// @param tokenPrefix Token prefix to represent the collection tokens in UI and user applications27 /// @return address Address of the newly created collection40 /// @return address Address of the newly created collection28 /// @dev EVM selector for this function is: 0xe34a6844,41 /// @dev EVM selector for this function is: 0xe34a6844,33 string memory tokenPrefix46 string memory tokenPrefix34 ) external payable returns (address);47 ) external payable returns (address);354836 /// @dev EVM selector for this function is: 0xa634a5f9,49 /// @dev EVM selector for this function is: 0xd1df968c,37 /// or in textual repr: createERC721MetadataCompatibleCollection(string,string,string,string)50 /// or in textual repr: createERC721MetadataNFTCollection(string,string,string,string)38 function createERC721MetadataCompatibleCollection(51 function createERC721MetadataNFTCollection(39 string memory name,52 string memory name,40 string memory description,53 string memory description,41 string memory tokenPrefix,54 string memory tokenPrefix,50 string memory tokenPrefix63 string memory tokenPrefix51 ) external payable returns (address);64 ) external payable returns (address);6566 /// @dev EVM selector for this function is: 0x44a68ad5,67 /// or in textual repr: createRefungibleCollection(string,string,string)68 function createRefungibleCollection(69 string memory name,70 string memory description,71 string memory tokenPrefix72 ) external payable returns (address);527353 /// @dev EVM selector for this function is: 0xa5596388,74 /// @dev EVM selector for this function is: 0xbea6a299,54 /// or in textual repr: createERC721MetadataCompatibleRFTCollection(string,string,string,string)75 /// or in textual repr: createERC721MetadataRFTCollection(string,string,string,string)55 function createERC721MetadataCompatibleRFTCollection(76 function createERC721MetadataRFTCollection(56 string memory name,77 string memory name,57 string memory description,78 string memory description,58 string memory tokenPrefix,79 string memory tokenPrefix,tests/src/eth/collectionAdmin.test.tsdiffbeforeafterboth383839 itEth('Add admin by owner', async ({helper}) => {39 itEth('Add admin by owner', async ({helper}) => {40 const owner = await helper.eth.createAccountWithBalance(donor);40 const owner = await helper.eth.createAccountWithBalance(donor);41 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');41 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');42 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);42 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);434344 const newAdmin = helper.eth.createAccount();44 const newAdmin = helper.eth.createAccount();515152 itEth.skip('Add substrate admin by owner', async ({helper}) => {52 itEth.skip('Add substrate admin by owner', async ({helper}) => {53 const owner = await helper.eth.createAccountWithBalance(donor);53 const owner = await helper.eth.createAccountWithBalance(donor);54 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');54 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');55 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);55 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);565657 const [newAdmin] = await helper.arrange.createAccounts([10n], donor);57 const [newAdmin] = await helper.arrange.createAccounts([10n], donor);646465 itEth('Verify owner or admin', async ({helper}) => {65 itEth('Verify owner or admin', async ({helper}) => {66 const owner = await helper.eth.createAccountWithBalance(donor);66 const owner = await helper.eth.createAccountWithBalance(donor);67 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');67 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');686869 const newAdmin = helper.eth.createAccount();69 const newAdmin = helper.eth.createAccount();70 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);70 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);757576 itEth('(!negative tests!) Add admin by ADMIN is not allowed', async ({helper}) => {76 itEth('(!negative tests!) Add admin by ADMIN is not allowed', async ({helper}) => {77 const owner = await helper.eth.createAccountWithBalance(donor);77 const owner = await helper.eth.createAccountWithBalance(donor);78 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');78 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');797980 const admin = await helper.eth.createAccountWithBalance(donor);80 const admin = await helper.eth.createAccountWithBalance(donor);81 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);81 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);939394 itEth('(!negative tests!) Add admin by USER is not allowed', async ({helper}) => {94 itEth('(!negative tests!) Add admin by USER is not allowed', async ({helper}) => {95 const owner = await helper.eth.createAccountWithBalance(donor);95 const owner = await helper.eth.createAccountWithBalance(donor);96 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');96 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');979798 const notAdmin = await helper.eth.createAccountWithBalance(donor);98 const notAdmin = await helper.eth.createAccountWithBalance(donor);99 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);99 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);108108109 itEth.skip('(!negative tests!) Add substrate admin by ADMIN is not allowed', async ({helper}) => {109 itEth.skip('(!negative tests!) Add substrate admin by ADMIN is not allowed', async ({helper}) => {110 const owner = await helper.eth.createAccountWithBalance(donor);110 const owner = await helper.eth.createAccountWithBalance(donor);111 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');111 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');112112113 const admin = await helper.eth.createAccountWithBalance(donor);113 const admin = await helper.eth.createAccountWithBalance(donor);114 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);114 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);126126127 itEth.skip('(!negative tests!) Add substrate admin by USER is not allowed', async ({helper}) => {127 itEth.skip('(!negative tests!) Add substrate admin by USER is not allowed', async ({helper}) => {128 const owner = await helper.eth.createAccountWithBalance(donor);128 const owner = await helper.eth.createAccountWithBalance(donor);129 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');129 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');130130131 const notAdmin0 = await helper.eth.createAccountWithBalance(donor);131 const notAdmin0 = await helper.eth.createAccountWithBalance(donor);132 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);132 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);150150151 itEth('Remove admin by owner', async ({helper}) => {151 itEth('Remove admin by owner', async ({helper}) => {152 const owner = await helper.eth.createAccountWithBalance(donor);152 const owner = await helper.eth.createAccountWithBalance(donor);153 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');153 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');154154155 const newAdmin = helper.eth.createAccount();155 const newAdmin = helper.eth.createAccount();156 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);156 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);170170171 itEth.skip('Remove substrate admin by owner', async ({helper}) => {171 itEth.skip('Remove substrate admin by owner', async ({helper}) => {172 const owner = await helper.eth.createAccountWithBalance(donor);172 const owner = await helper.eth.createAccountWithBalance(donor);173 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');173 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');174174175 const [newAdmin] = await helper.arrange.createAccounts([10n], donor);175 const [newAdmin] = await helper.arrange.createAccounts([10n], donor);176 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);176 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);188188189 itEth('(!negative tests!) Remove admin by ADMIN is not allowed', async ({helper}) => {189 itEth('(!negative tests!) Remove admin by ADMIN is not allowed', async ({helper}) => {190 const owner = await helper.eth.createAccountWithBalance(donor);190 const owner = await helper.eth.createAccountWithBalance(donor);191 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');191 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');192192193 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);193 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);194194210210211 itEth('(!negative tests!) Remove admin by USER is not allowed', async ({helper}) => {211 itEth('(!negative tests!) Remove admin by USER is not allowed', async ({helper}) => {212 const owner = await helper.eth.createAccountWithBalance(donor);212 const owner = await helper.eth.createAccountWithBalance(donor);213 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');213 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');214214215 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);215 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);216216230230231 itEth.skip('(!negative tests!) Remove substrate admin by ADMIN is not allowed', async ({helper}) => {231 itEth.skip('(!negative tests!) Remove substrate admin by ADMIN is not allowed', async ({helper}) => {232 const owner = await helper.eth.createAccountWithBalance(donor);232 const owner = await helper.eth.createAccountWithBalance(donor);233 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');233 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');234234235 const [adminSub] = await helper.arrange.createAccounts([10n], donor);235 const [adminSub] = await helper.arrange.createAccounts([10n], donor);236 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);236 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);250250251 itEth.skip('(!negative tests!) Remove substrate admin by USER is not allowed', async ({helper}) => {251 itEth.skip('(!negative tests!) Remove substrate admin by USER is not allowed', async ({helper}) => {252 const owner = await helper.eth.createAccountWithBalance(donor);252 const owner = await helper.eth.createAccountWithBalance(donor);253 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');253 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');254254255 const [adminSub] = await helper.arrange.createAccounts([10n], donor);255 const [adminSub] = await helper.arrange.createAccounts([10n], donor);256 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);256 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);279 itEth('Change owner', async ({helper}) => {279 itEth('Change owner', async ({helper}) => {280 const owner = await helper.eth.createAccountWithBalance(donor);280 const owner = await helper.eth.createAccountWithBalance(donor);281 const newOwner = await helper.eth.createAccountWithBalance(donor);281 const newOwner = await helper.eth.createAccountWithBalance(donor);282 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');282 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');283 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);283 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);284284285 await collectionEvm.methods.setOwner(newOwner).send();285 await collectionEvm.methods.setOwner(newOwner).send();291 itEth('change owner call fee', async ({helper}) => {291 itEth('change owner call fee', async ({helper}) => {292 const owner = await helper.eth.createAccountWithBalance(donor);292 const owner = await helper.eth.createAccountWithBalance(donor);293 const newOwner = await helper.eth.createAccountWithBalance(donor);293 const newOwner = await helper.eth.createAccountWithBalance(donor);294 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');294 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');295 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);295 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);296 const cost = await recordEthFee(helper, owner, () => collectionEvm.methods.setOwner(newOwner).send());296 const cost = await recordEthFee(helper, owner, () => collectionEvm.methods.setOwner(newOwner).send());297 expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));297 expect(cost < BigInt(0.2 * Number(helper.balance.getOneTokenNominal())));301 itEth('(!negative tests!) call setOwner by non owner', async ({helper}) => {301 itEth('(!negative tests!) call setOwner by non owner', async ({helper}) => {302 const owner = await helper.eth.createAccountWithBalance(donor);302 const owner = await helper.eth.createAccountWithBalance(donor);303 const newOwner = await helper.eth.createAccountWithBalance(donor);303 const newOwner = await helper.eth.createAccountWithBalance(donor);304 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');304 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');305 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);305 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);306306307 await expect(collectionEvm.methods.setOwner(newOwner).send({from: newOwner})).to.be.rejected;307 await expect(collectionEvm.methods.setOwner(newOwner).send({from: newOwner})).to.be.rejected;321 itEth.skip('Change owner', async ({helper}) => {321 itEth.skip('Change owner', async ({helper}) => {322 const owner = await helper.eth.createAccountWithBalance(donor);322 const owner = await helper.eth.createAccountWithBalance(donor);323 const [newOwner] = await helper.arrange.createAccounts([10n], donor);323 const [newOwner] = await helper.arrange.createAccounts([10n], donor);324 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');324 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');325 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);325 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);326326327 expect(await collectionEvm.methods.isOwnerOrAdmin(owner).call()).to.be.true;327 expect(await collectionEvm.methods.isOwnerOrAdmin(owner).call()).to.be.true;336 itEth.skip('change owner call fee', async ({helper}) => {336 itEth.skip('change owner call fee', async ({helper}) => {337 const owner = await helper.eth.createAccountWithBalance(donor);337 const owner = await helper.eth.createAccountWithBalance(donor);338 const [newOwner] = await helper.arrange.createAccounts([10n], donor);338 const [newOwner] = await helper.arrange.createAccounts([10n], donor);339 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');339 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');340 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);340 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);341341342 const cost = await recordEthFee(helper, owner, () => collectionEvm.methods.setOwnerSubstrate(newOwner.addressRaw).send());342 const cost = await recordEthFee(helper, owner, () => collectionEvm.methods.setOwnerSubstrate(newOwner.addressRaw).send());348 const owner = await helper.eth.createAccountWithBalance(donor);348 const owner = await helper.eth.createAccountWithBalance(donor);349 const otherReceiver = await helper.eth.createAccountWithBalance(donor);349 const otherReceiver = await helper.eth.createAccountWithBalance(donor);350 const [newOwner] = await helper.arrange.createAccounts([10n], donor);350 const [newOwner] = await helper.arrange.createAccounts([10n], donor);351 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');351 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');352 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);352 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);353353354 await expect(collectionEvm.methods.setOwnerSubstrate(newOwner.addressRaw).send({from: otherReceiver})).to.be.rejected;354 await expect(collectionEvm.methods.setOwnerSubstrate(newOwner.addressRaw).send({from: otherReceiver})).to.be.rejected;tests/src/eth/collectionHelpersAbi.jsondiffbeforeafterboth32 { "internalType": "string", "name": "tokenPrefix", "type": "string" },32 { "internalType": "string", "name": "tokenPrefix", "type": "string" },33 { "internalType": "string", "name": "baseUri", "type": "string" }33 { "internalType": "string", "name": "baseUri", "type": "string" }34 ],34 ],35 "name": "createERC721MetadataCompatibleCollection",35 "name": "createERC721MetadataNFTCollection",36 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],36 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],37 "stateMutability": "payable",37 "stateMutability": "payable",38 "type": "function"38 "type": "function"44 { "internalType": "string", "name": "tokenPrefix", "type": "string" },44 { "internalType": "string", "name": "tokenPrefix", "type": "string" },45 { "internalType": "string", "name": "baseUri", "type": "string" }45 { "internalType": "string", "name": "baseUri", "type": "string" }46 ],46 ],47 "name": "createERC721MetadataCompatibleRFTCollection",47 "name": "createERC721MetadataRFTCollection",48 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],48 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],49 "stateMutability": "payable",49 "stateMutability": "payable",50 "type": "function"50 "type": "function"51 },51 },52 {53 "inputs": [54 { "internalType": "string", "name": "name", "type": "string" },55 { "internalType": "string", "name": "description", "type": "string" },56 { "internalType": "string", "name": "tokenPrefix", "type": "string" }57 ],58 "name": "createNFTCollection",59 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],60 "stateMutability": "payable",61 "type": "function"62 },52 {63 {53 "inputs": [64 "inputs": [54 { "internalType": "string", "name": "name", "type": "string" },65 { "internalType": "string", "name": "name", "type": "string" },71 "stateMutability": "payable",82 "stateMutability": "payable",72 "type": "function"83 "type": "function"73 },84 },85 {86 "inputs": [87 { "internalType": "string", "name": "name", "type": "string" },88 { "internalType": "string", "name": "description", "type": "string" },89 { "internalType": "string", "name": "tokenPrefix", "type": "string" }90 ],91 "name": "createRefungibleCollection",92 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],93 "stateMutability": "payable",94 "type": "function"95 },74 {96 {75 "inputs": [97 "inputs": [76 {98 {tests/src/eth/collectionProperties.test.tsdiffbeforeafterboth242425 const raw = (await collection.getData())?.raw;25 const raw = (await collection.getData())?.raw;262627 expect(raw.properties[0].value).to.equal('testValue');27 expect(raw.properties[1].value).to.equal('testValue');28 });28 });292930 itEth('Can be deleted', async({helper}) => {30 itEth('Can be deleted', async({helper}) => {55 });55 });56});56});5758describe('Supports ERC721Metadata', () => {59 let donor: IKeyringPair;6061 before(async function() {62 await usingEthPlaygrounds(async (_helper, privateKey) => {63 donor = privateKey('//Alice');64 });65 });6667 itEth('ERC721Metadata property can be set for NFT collection', async({helper}) => {68 const caller = await helper.eth.createAccountWithBalance(donor);69 const collection = await helper.nft.mintCollection(donor, {name: 'col', description: 'descr', tokenPrefix: 'COL'});7071 await collection.addAdmin(donor, {Ethereum: caller});72 const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller);7374 await contract.methods.setCollectionProperty('ERC721Metadata', Buffer.from('1')).send({from: caller});7576 expect(await contract.methods.supportsInterface('0x5b5e139f').call()).to.be.true;7778 await contract.methods.setCollectionProperty('ERC721Metadata', Buffer.from('0')).send({from: caller});7980 expect(await contract.methods.supportsInterface('0x5b5e139f').call()).to.be.false;81 });8283 itEth('ERC721Metadata property can be set for RFT collection', async({helper}) => {84 const caller = await helper.eth.createAccountWithBalance(donor);85 const collection = await helper.rft.mintCollection(donor, {name: 'col', description: 'descr', tokenPrefix: 'COL'});8687 await collection.addAdmin(donor, {Ethereum: caller});8889 const contract = helper.ethNativeContract.collectionById(collection.collectionId, 'nft', caller);9091 await contract.methods.setCollectionProperty('ERC721Metadata', Buffer.from('1')).send({from: caller});9293 expect(await contract.methods.supportsInterface('0x5b5e139f').call()).to.be.true;9495 await contract.methods.setCollectionProperty('ERC721Metadata', Buffer.from('0')).send({from: caller});9697 expect(await contract.methods.supportsInterface('0x5b5e139f').call()).to.be.false;98 });99});57100tests/src/eth/collectionSponsoring.test.tsdiffbeforeafterboth54 // itWeb3('Set substrate sponsor', async ({api, web3, privateKeyWrapper}) => {54 // itWeb3('Set substrate sponsor', async ({api, web3, privateKeyWrapper}) => {55 // const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);55 // const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);56 // const collectionHelpers = evmCollectionHelpers(web3, owner);56 // const collectionHelpers = evmCollectionHelpers(web3, owner);57 // let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();57 // let result = await collectionHelpers.methods.createNFTCollection('Sponsor collection', '1', '1').send();58 // const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);58 // const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);59 // const sponsor = privateKeyWrapper('//Alice');59 // const sponsor = privateKeyWrapper('//Alice');60 // const collectionEvm = evmCollection(web3, owner, collectionIdAddress);60 // const collectionEvm = evmCollection(web3, owner, collectionIdAddress);75 const owner = await helper.eth.createAccountWithBalance(donor);75 const owner = await helper.eth.createAccountWithBalance(donor);76 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);76 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);777778 let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});78 let result = await collectionHelpers.methods.createNFTCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});79 const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);79 const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);80 const sponsor = await helper.eth.createAccountWithBalance(donor);80 const sponsor = await helper.eth.createAccountWithBalance(donor);81 const collectionEvm = helper.ethNativeContract.collection(collectionIdAddress, 'nft', owner);81 const collectionEvm = helper.ethNativeContract.collection(collectionIdAddress, 'nft', owner);97 const owner = await helper.eth.createAccountWithBalance(donor);97 const owner = await helper.eth.createAccountWithBalance(donor);98 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);98 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);9999100 let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});100 let result = await collectionHelpers.methods.createERC721MetadataNFTCollection('Sponsor collection', '1', '1', '').send({value: Number(2n * nominal)});101 const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);101 const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);102 const collectionId = helper.ethAddress.extractCollectionId(collectionIdAddress);102 const collectionId = helper.ethAddress.extractCollectionId(collectionIdAddress);103 const collection = helper.nft.getCollectionObject(collectionId);103 const collection = helper.nft.getCollectionObject(collectionId);167 // itWeb3('Sponsoring collection from substrate address via access list', async ({api, web3, privateKeyWrapper}) => {167 // itWeb3('Sponsoring collection from substrate address via access list', async ({api, web3, privateKeyWrapper}) => {168 // const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);168 // const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);169 // const collectionHelpers = evmCollectionHelpers(web3, owner);169 // const collectionHelpers = evmCollectionHelpers(web3, owner);170 // const result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send();170 // const result = await collectionHelpers.methods.createERC721MetadataNFTCollection('Sponsor collection', '1', '1', '').send();171 // const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);171 // const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);172 // const sponsor = privateKeyWrapper('//Alice');172 // const sponsor = privateKeyWrapper('//Alice');173 // const collectionEvm = evmCollection(web3, owner, collectionIdAddress);173 // const collectionEvm = evmCollection(web3, owner, collectionIdAddress);223 const owner = await helper.eth.createAccountWithBalance(donor);223 const owner = await helper.eth.createAccountWithBalance(donor);224 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);224 const collectionHelpers = helper.ethNativeContract.collectionHelpers(owner);225225226 let result = await collectionHelpers.methods.createNonfungibleCollection('Sponsor collection', '1', '1').send({value: Number(2n * nominal)});226 let result = await collectionHelpers.methods.createERC721MetadataNFTCollection('Sponsor collection', '1', '1', '').send({value: Number(2n * nominal)});227 const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);227 const collectionIdAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);228 const collectionId = helper.ethAddress.extractCollectionId(collectionIdAddress);228 const collectionId = helper.ethAddress.extractCollectionId(collectionIdAddress);229 const collection = helper.nft.getCollectionObject(collectionId);229 const collection = helper.nft.getCollectionObject(collectionId);tests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth373738 // todo:playgrounds this might fail when in async environment.38 // todo:playgrounds this might fail when in async environment.39 const collectionCountBefore = +(await helper.callRpc('api.rpc.unique.collectionStats')).created;39 const collectionCountBefore = +(await helper.callRpc('api.rpc.unique.collectionStats')).created;40 const {collectionId} = await helper.eth.createNonfungibleCollection(owner, name, description, prefix);40 const {collectionId} = await helper.eth.createNFTCollection(owner, name, description, prefix);41 const collectionCountAfter = +(await helper.callRpc('api.rpc.unique.collectionStats')).created;41 const collectionCountAfter = +(await helper.callRpc('api.rpc.unique.collectionStats')).created;424243 const collection = helper.nft.getCollectionObject(collectionId);43 const collection = helper.nft.getCollectionObject(collectionId);64 .call()).to.be.false;64 .call()).to.be.false;656566 await collectionHelpers.methods66 await collectionHelpers.methods67 .createNonfungibleCollection('A', 'A', 'A')67 .createNFTCollection('A', 'A', 'A')68 .send({value: Number(2n * helper.balance.getOneTokenNominal())});68 .send({value: Number(2n * helper.balance.getOneTokenNominal())});69 69 70 expect(await collectionHelpers.methods70 expect(await collectionHelpers.methods76 const owner = await helper.eth.createAccountWithBalance(donor);76 const owner = await helper.eth.createAccountWithBalance(donor);77 const sponsor = await helper.eth.createAccountWithBalance(donor);77 const sponsor = await helper.eth.createAccountWithBalance(donor);78 const ss58Format = helper.chain.getChainProperties().ss58Format;78 const ss58Format = helper.chain.getChainProperties().ss58Format;79 const {collectionId, collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Sponsor', 'absolutely anything', 'ROC');79 const {collectionId, collectionAddress} = await helper.eth.createNFTCollection(owner, 'Sponsor', 'absolutely anything', 'ROC');808081 const collection = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);81 const collection = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);82 await collection.methods.setCollectionSponsor(sponsor).send();82 await collection.methods.setCollectionSponsor(sponsor).send();959596 itEth('Set limits', async ({helper}) => {96 itEth('Set limits', async ({helper}) => {97 const owner = await helper.eth.createAccountWithBalance(donor);97 const owner = await helper.eth.createAccountWithBalance(donor);98 const {collectionId, collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Limits', 'absolutely anything', 'FLO');98 const {collectionId, collectionAddress} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'FLO');99 const limits = {99 const limits = {100 accountTokenOwnershipLimit: 1000,100 accountTokenOwnershipLimit: 1000,101 sponsoredDataSize: 1024,101 sponsoredDataSize: 1024,138 .methods.isCollectionExist(collectionAddressForNonexistentCollection).call())138 .methods.isCollectionExist(collectionAddressForNonexistentCollection).call())139 .to.be.false;139 .to.be.false;140 140 141 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Exister', 'absolutely anything', 'EVC');141 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Exister', 'absolutely anything', 'EVC');142 expect(await helper.ethNativeContract.collectionHelpers(collectionAddress)142 expect(await helper.ethNativeContract.collectionHelpers(collectionAddress)143 .methods.isCollectionExist(collectionAddress).call())143 .methods.isCollectionExist(collectionAddress).call())144 .to.be.true;144 .to.be.true;166 const tokenPrefix = 'A';166 const tokenPrefix = 'A';167167168 await expect(collectionHelper.methods168 await expect(collectionHelper.methods169 .createNonfungibleCollection(collectionName, description, tokenPrefix)169 .createNFTCollection(collectionName, description, tokenPrefix)170 .call({value: Number(2n * nominal)})).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGTH);170 .call({value: Number(2n * nominal)})).to.be.rejectedWith('name is too long. Max length is ' + MAX_NAME_LENGTH);171 171 172 }172 }176 const description = 'A'.repeat(MAX_DESCRIPTION_LENGTH + 1);176 const description = 'A'.repeat(MAX_DESCRIPTION_LENGTH + 1);177 const tokenPrefix = 'A';177 const tokenPrefix = 'A';178 await expect(collectionHelper.methods178 await expect(collectionHelper.methods179 .createNonfungibleCollection(collectionName, description, tokenPrefix)179 .createNFTCollection(collectionName, description, tokenPrefix)180 .call({value: Number(2n * nominal)})).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGTH);180 .call({value: Number(2n * nominal)})).to.be.rejectedWith('description is too long. Max length is ' + MAX_DESCRIPTION_LENGTH);181 }181 }182 {182 {185 const description = 'A';185 const description = 'A';186 const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGTH + 1);186 const tokenPrefix = 'A'.repeat(MAX_TOKEN_PREFIX_LENGTH + 1);187 await expect(collectionHelper.methods187 await expect(collectionHelper.methods188 .createNonfungibleCollection(collectionName, description, tokenPrefix)188 .createNFTCollection(collectionName, description, tokenPrefix)189 .call({value: Number(2n * nominal)})).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGTH);189 .call({value: Number(2n * nominal)})).to.be.rejectedWith('token_prefix is too long. Max length is ' + MAX_TOKEN_PREFIX_LENGTH);190 }190 }191 });191 });194 const owner = await helper.eth.createAccountWithBalance(donor);194 const owner = await helper.eth.createAccountWithBalance(donor);195 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);195 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);196 await expect(collectionHelper.methods196 await expect(collectionHelper.methods197 .createNonfungibleCollection('Peasantry', 'absolutely anything', 'CVE')197 .createNFTCollection('Peasantry', 'absolutely anything', 'CVE')198 .call({value: Number(1n * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');198 .call({value: Number(1n * nominal)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');199 });199 });200200201 itEth('(!negative test!) Check owner', async ({helper}) => {201 itEth('(!negative test!) Check owner', async ({helper}) => {202 const owner = await helper.eth.createAccountWithBalance(donor);202 const owner = await helper.eth.createAccountWithBalance(donor);203 const malfeasant = helper.eth.createAccount();203 const malfeasant = helper.eth.createAccount();204 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Transgressed', 'absolutely anything', 'COR');204 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Transgressed', 'absolutely anything', 'COR');205 const malfeasantCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', malfeasant);205 const malfeasantCollection = helper.ethNativeContract.collection(collectionAddress, 'nft', malfeasant);206 const EXPECTED_ERROR = 'NoPermission';206 const EXPECTED_ERROR = 'NoPermission';207 {207 {224224225 itEth('(!negative test!) Set limits', async ({helper}) => {225 itEth('(!negative test!) Set limits', async ({helper}) => {226 const owner = await helper.eth.createAccountWithBalance(donor);226 const owner = await helper.eth.createAccountWithBalance(donor);227 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Limits', 'absolutely anything', 'OLF');227 const {collectionAddress} = await helper.eth.createNFTCollection(owner, 'Limits', 'absolutely anything', 'OLF');228 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);228 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);229 await expect(collectionEvm.methods229 await expect(collectionEvm.methods230 .setCollectionLimit('badLimit', 'true')230 .setCollectionLimit('badLimit', 'true')tests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth39 39 40 // todo:playgrounds this might fail when in async environment.40 // todo:playgrounds this might fail when in async environment.41 const collectionCountBefore = +(await helper.callRpc('api.rpc.unique.collectionStats')).created;41 const collectionCountBefore = +(await helper.callRpc('api.rpc.unique.collectionStats')).created;42 const {collectionId} = await helper.eth.createRefungibleCollection(owner, name, description, prefix);42 const {collectionId} = await helper.eth.createRFTCollection(owner, name, description, prefix);43 const collectionCountAfter = +(await helper.callRpc('api.rpc.unique.collectionStats')).created;43 const collectionCountAfter = +(await helper.callRpc('api.rpc.unique.collectionStats')).created;44 44 45 const data = (await helper.rft.getData(collectionId))!;45 const data = (await helper.rft.getData(collectionId))!;77 const owner = await helper.eth.createAccountWithBalance(donor);77 const owner = await helper.eth.createAccountWithBalance(donor);78 const sponsor = await helper.eth.createAccountWithBalance(donor);78 const sponsor = await helper.eth.createAccountWithBalance(donor);79 const ss58Format = helper.chain.getChainProperties().ss58Format;79 const ss58Format = helper.chain.getChainProperties().ss58Format;80 const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Sponsor', 'absolutely anything', 'ENVY');80 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Sponsor', 'absolutely anything', 'ENVY');818182 const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);82 const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);83 await collection.methods.setCollectionSponsor(sponsor).send();83 await collection.methods.setCollectionSponsor(sponsor).send();969697 itEth('Set limits', async ({helper}) => {97 itEth('Set limits', async ({helper}) => {98 const owner = await helper.eth.createAccountWithBalance(donor);98 const owner = await helper.eth.createAccountWithBalance(donor);99 const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Limits', 'absolutely anything', 'INSI');99 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'INSI');100 const limits = {100 const limits = {101 accountTokenOwnershipLimit: 1000,101 accountTokenOwnershipLimit: 1000,102 sponsoredDataSize: 1024,102 sponsoredDataSize: 1024,139 .methods.isCollectionExist(collectionAddressForNonexistentCollection).call())139 .methods.isCollectionExist(collectionAddressForNonexistentCollection).call())140 .to.be.false;140 .to.be.false;141 141 142 const {collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Exister', 'absolutely anything', 'WIWT');142 const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Exister', 'absolutely anything', 'WIWT');143 expect(await helper.ethNativeContract.collectionHelpers(collectionAddress)143 expect(await helper.ethNativeContract.collectionHelpers(collectionAddress)144 .methods.isCollectionExist(collectionAddress).call())144 .methods.isCollectionExist(collectionAddress).call())145 .to.be.true;145 .to.be.true;202 itEth('(!negative test!) Check owner', async ({helper}) => {202 itEth('(!negative test!) Check owner', async ({helper}) => {203 const owner = await helper.eth.createAccountWithBalance(donor);203 const owner = await helper.eth.createAccountWithBalance(donor);204 const peasant = helper.eth.createAccount();204 const peasant = helper.eth.createAccount();205 const {collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Transgressed', 'absolutely anything', 'YVNE');205 const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Transgressed', 'absolutely anything', 'YVNE');206 const peasantCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', peasant);206 const peasantCollection = helper.ethNativeContract.collection(collectionAddress, 'rft', peasant);207 const EXPECTED_ERROR = 'NoPermission';207 const EXPECTED_ERROR = 'NoPermission';208 {208 {225225226 itEth('(!negative test!) Set limits', async ({helper}) => {226 itEth('(!negative test!) Set limits', async ({helper}) => {227 const owner = await helper.eth.createAccountWithBalance(donor);227 const owner = await helper.eth.createAccountWithBalance(donor);228 const {collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Limits', 'absolutely anything', 'ISNI');228 const {collectionAddress} = await helper.eth.createRFTCollection(owner, 'Limits', 'absolutely anything', 'ISNI');229 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);229 const collectionEvm = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);230 await expect(collectionEvm.methods230 await expect(collectionEvm.methods231 .setCollectionLimit('badLimit', 'true')231 .setCollectionLimit('badLimit', 'true')tests/src/eth/evmCoder.test.tsdiffbeforeafterboth65 65 66 itEth('Call non-existing function', async ({helper}) => {66 itEth('Call non-existing function', async ({helper}) => {67 const owner = await helper.eth.createAccountWithBalance(donor);67 const owner = await helper.eth.createAccountWithBalance(donor);68 const collection = await helper.eth.createNonfungibleCollection(owner, 'EVMCODER', '', 'TEST');68 const collection = await helper.eth.createNFTCollection(owner, 'EVMCODER', '', 'TEST');69 const contract = await helper.ethContract.deployByCode(owner, 'Test', getContractSource(collection.collectionAddress, '0x1bfed5D614b886b9Ab2eA4CBAc22A96B7EC29c9c'));69 const contract = await helper.ethContract.deployByCode(owner, 'Test', getContractSource(collection.collectionAddress, '0x1bfed5D614b886b9Ab2eA4CBAc22A96B7EC29c9c'));70 const testContract = await helper.ethContract.deployByCode(owner, 'Test', getContractSource(collection.collectionAddress, contract.options.address));70 const testContract = await helper.ethContract.deployByCode(owner, 'Test', getContractSource(collection.collectionAddress, contract.options.address));71 {71 {tests/src/eth/fractionalizer/fractionalizer.test.tsdiffbeforeafterboth62const mintRFTToken = async (helper: EthUniqueHelper, owner: string, fractionalizer: Contract, amount: bigint): Promise<{62const mintRFTToken = async (helper: EthUniqueHelper, owner: string, fractionalizer: Contract, amount: bigint): Promise<{63 nftCollectionAddress: string, nftTokenId: number, rftTokenAddress: string63 nftCollectionAddress: string, nftTokenId: number, rftTokenAddress: string64}> => {64}> => {65 const nftCollection = await helper.eth.createNonfungibleCollection(owner, 'nft', 'NFT collection', 'NFT');65 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');66 const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);66 const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);67 const nftTokenId = await nftContract.methods.nextTokenId().call();67 const nftTokenId = await nftContract.methods.nextTokenId().call();68 await nftContract.methods.mint(owner, nftTokenId).send({from: owner});68 await nftContract.methods.mint(owner, nftTokenId).send({from: owner});92 itEth('Set RFT collection', async ({helper}) => {92 itEth('Set RFT collection', async ({helper}) => {93 const owner = await helper.eth.createAccountWithBalance(donor, 10n);93 const owner = await helper.eth.createAccountWithBalance(donor, 10n);94 const fractionalizer = await deployContract(helper, owner);94 const fractionalizer = await deployContract(helper, owner);95 const rftCollection = await helper.eth.createRefungibleCollection(owner, 'rft', 'RFT collection', 'RFT');95 const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');96 const rftContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);96 const rftContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);979798 await rftContract.methods.addCollectionAdmin(fractionalizer.options.address).send({from: owner});98 await rftContract.methods.addCollectionAdmin(fractionalizer.options.address).send({from: owner});121 itEth('Set Allowlist', async ({helper}) => {121 itEth('Set Allowlist', async ({helper}) => {122 const owner = await helper.eth.createAccountWithBalance(donor, 20n);122 const owner = await helper.eth.createAccountWithBalance(donor, 20n);123 const {contract: fractionalizer} = await initContract(helper, owner);123 const {contract: fractionalizer} = await initContract(helper, owner);124 const nftCollection = await helper.eth.createNonfungibleCollection(owner, 'nft', 'NFT collection', 'NFT');124 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');125125126 const result1 = await fractionalizer.methods.setNftCollectionIsAllowed(nftCollection.collectionAddress, true).send({from: owner});126 const result1 = await fractionalizer.methods.setNftCollectionIsAllowed(nftCollection.collectionAddress, true).send({from: owner});127 expect(result1.events).to.be.like({127 expect(result1.events).to.be.like({146 itEth('NFT to RFT', async ({helper}) => {146 itEth('NFT to RFT', async ({helper}) => {147 const owner = await helper.eth.createAccountWithBalance(donor, 20n);147 const owner = await helper.eth.createAccountWithBalance(donor, 20n);148148149 const nftCollection = await helper.eth.createNonfungibleCollection(owner, 'nft', 'NFT collection', 'NFT');149 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');150 const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);150 const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);151 const nftTokenId = await nftContract.methods.nextTokenId().call();151 const nftTokenId = await nftContract.methods.nextTokenId().call();152 await nftContract.methods.mint(owner, nftTokenId).send({from: owner});152 await nftContract.methods.mint(owner, nftTokenId).send({from: owner});231231232 itEth('call setRFTCollection twice', async ({helper}) => {232 itEth('call setRFTCollection twice', async ({helper}) => {233 const owner = await helper.eth.createAccountWithBalance(donor, 20n);233 const owner = await helper.eth.createAccountWithBalance(donor, 20n);234 const rftCollection = await helper.eth.createRefungibleCollection(owner, 'rft', 'RFT collection', 'RFT');234 const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');235 const refungibleContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);235 const refungibleContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);236236237 const fractionalizer = await deployContract(helper, owner);237 const fractionalizer = await deployContract(helper, owner);244244245 itEth('call setRFTCollection with NFT collection', async ({helper}) => {245 itEth('call setRFTCollection with NFT collection', async ({helper}) => {246 const owner = await helper.eth.createAccountWithBalance(donor, 20n);246 const owner = await helper.eth.createAccountWithBalance(donor, 20n);247 const nftCollection = await helper.eth.createNonfungibleCollection(owner, 'nft', 'NFT collection', 'NFT');247 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');248 const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);248 const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);249249250 const fractionalizer = await deployContract(helper, owner);250 const fractionalizer = await deployContract(helper, owner);257 itEth('call setRFTCollection while not collection admin', async ({helper}) => {257 itEth('call setRFTCollection while not collection admin', async ({helper}) => {258 const owner = await helper.eth.createAccountWithBalance(donor, 20n);258 const owner = await helper.eth.createAccountWithBalance(donor, 20n);259 const fractionalizer = await deployContract(helper, owner);259 const fractionalizer = await deployContract(helper, owner);260 const rftCollection = await helper.eth.createRefungibleCollection(owner, 'rft', 'RFT collection', 'RFT');260 const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');261261262 await expect(fractionalizer.methods.setRFTCollection(rftCollection.collectionAddress).call())262 await expect(fractionalizer.methods.setRFTCollection(rftCollection.collectionAddress).call())263 .to.be.rejectedWith(/Fractionalizer contract should be an admin of the collection$/g);263 .to.be.rejectedWith(/Fractionalizer contract should be an admin of the collection$/g);278 itEth('call nft2rft without setting RFT collection for contract', async ({helper}) => {278 itEth('call nft2rft without setting RFT collection for contract', async ({helper}) => {279 const owner = await helper.eth.createAccountWithBalance(donor, 20n);279 const owner = await helper.eth.createAccountWithBalance(donor, 20n);280280281 const nftCollection = await helper.eth.createNonfungibleCollection(owner, 'nft', 'NFT collection', 'NFT');281 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');282 const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);282 const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);283 const nftTokenId = await nftContract.methods.nextTokenId().call();283 const nftTokenId = await nftContract.methods.nextTokenId().call();284 await nftContract.methods.mint(owner, nftTokenId).send({from: owner});284 await nftContract.methods.mint(owner, nftTokenId).send({from: owner});293 const owner = await helper.eth.createAccountWithBalance(donor, 20n);293 const owner = await helper.eth.createAccountWithBalance(donor, 20n);294 const nftOwner = await helper.eth.createAccountWithBalance(donor, 10n);294 const nftOwner = await helper.eth.createAccountWithBalance(donor, 10n);295295296 const nftCollection = await helper.eth.createNonfungibleCollection(owner, 'nft', 'NFT collection', 'NFT');296 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');297 const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);297 const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);298 const nftTokenId = await nftContract.methods.nextTokenId().call();298 const nftTokenId = await nftContract.methods.nextTokenId().call();299 await nftContract.methods.mint(owner, nftTokenId).send({from: owner});299 await nftContract.methods.mint(owner, nftTokenId).send({from: owner});310 itEth('call nft2rft while not in list of allowed accounts', async ({helper}) => {310 itEth('call nft2rft while not in list of allowed accounts', async ({helper}) => {311 const owner = await helper.eth.createAccountWithBalance(donor, 20n);311 const owner = await helper.eth.createAccountWithBalance(donor, 20n);312312313 const nftCollection = await helper.eth.createNonfungibleCollection(owner, 'nft', 'NFT collection', 'NFT');313 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');314 const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);314 const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);315 const nftTokenId = await nftContract.methods.nextTokenId().call();315 const nftTokenId = await nftContract.methods.nextTokenId().call();316 await nftContract.methods.mint(owner, nftTokenId).send({from: owner});316 await nftContract.methods.mint(owner, nftTokenId).send({from: owner});325 itEth('call nft2rft while fractionalizer doesnt have approval for nft token', async ({helper}) => {325 itEth('call nft2rft while fractionalizer doesnt have approval for nft token', async ({helper}) => {326 const owner = await helper.eth.createAccountWithBalance(donor, 20n);326 const owner = await helper.eth.createAccountWithBalance(donor, 20n);327327328 const nftCollection = await helper.eth.createNonfungibleCollection(owner, 'nft', 'NFT collection', 'NFT');328 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');329 const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);329 const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);330 const nftTokenId = await nftContract.methods.nextTokenId().call();330 const nftTokenId = await nftContract.methods.nextTokenId().call();331 await nftContract.methods.mint(owner, nftTokenId).send({from: owner});331 await nftContract.methods.mint(owner, nftTokenId).send({from: owner});341 const owner = await helper.eth.createAccountWithBalance(donor, 20n);341 const owner = await helper.eth.createAccountWithBalance(donor, 20n);342342343 const fractionalizer = await deployContract(helper, owner);343 const fractionalizer = await deployContract(helper, owner);344 const rftCollection = await helper.eth.createRefungibleCollection(owner, 'rft', 'RFT collection', 'RFT');344 const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');345 const refungibleContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);345 const refungibleContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);346 const rftTokenId = await refungibleContract.methods.nextTokenId().call();346 const rftTokenId = await refungibleContract.methods.nextTokenId().call();347 await refungibleContract.methods.mint(owner, rftTokenId).send({from: owner});347 await refungibleContract.methods.mint(owner, rftTokenId).send({from: owner});354 const owner = await helper.eth.createAccountWithBalance(donor, 20n);354 const owner = await helper.eth.createAccountWithBalance(donor, 20n);355355356 const {contract: fractionalizer} = await initContract(helper, owner);356 const {contract: fractionalizer} = await initContract(helper, owner);357 const rftCollection = await helper.eth.createRefungibleCollection(owner, 'rft', 'RFT collection', 'RFT');357 const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');358 const refungibleContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);358 const refungibleContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);359 const rftTokenId = await refungibleContract.methods.nextTokenId().call();359 const rftTokenId = await refungibleContract.methods.nextTokenId().call();360 await refungibleContract.methods.mint(owner, rftTokenId).send({from: owner});360 await refungibleContract.methods.mint(owner, rftTokenId).send({from: owner});365365366 itEth('call rft2nft for RFT token that was not minted by fractionalizer contract', async ({helper}) => {366 itEth('call rft2nft for RFT token that was not minted by fractionalizer contract', async ({helper}) => {367 const owner = await helper.eth.createAccountWithBalance(donor, 20n);367 const owner = await helper.eth.createAccountWithBalance(donor, 20n);368 const rftCollection = await helper.eth.createRefungibleCollection(owner, 'rft', 'RFT collection', 'RFT');368 const rftCollection = await helper.eth.createRFTCollection(owner, 'rft', 'RFT collection', 'RFT');369 const refungibleContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);369 const refungibleContract = helper.ethNativeContract.collection(rftCollection.collectionAddress, 'rft', owner);370370371 const fractionalizer = await deployContract(helper, owner);371 const fractionalizer = await deployContract(helper, owner);432 await fractionalizer.methods.setRFTCollection(rftCollectionAddress).send({from: owner});432 await fractionalizer.methods.setRFTCollection(rftCollectionAddress).send({from: owner});433 await helper.executeExtrinsic(donor, 'api.tx.unique.setTransfersEnabledFlag', [rftCollection.collectionId, false], true);433 await helper.executeExtrinsic(donor, 'api.tx.unique.setTransfersEnabledFlag', [rftCollection.collectionId, false], true);434434435 const nftCollection = await helper.eth.createNonfungibleCollection(owner, 'nft', 'NFT collection', 'NFT');435 const nftCollection = await helper.eth.createNFTCollection(owner, 'nft', 'NFT collection', 'NFT');436 const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);436 const nftContract = helper.ethNativeContract.collection(nftCollection.collectionAddress, 'nft', owner);437 const nftTokenId = await nftContract.methods.nextTokenId().call();437 const nftTokenId = await nftContract.methods.nextTokenId().call();438 await nftContract.methods.mint(owner, nftTokenId).send({from: owner});438 await nftContract.methods.mint(owner, nftTokenId).send({from: owner});tests/src/eth/nesting/nest.test.tsdiffbeforeafterboth7 helper: EthUniqueHelper,7 helper: EthUniqueHelper,8 owner: string,8 owner: string,9): Promise<{ collectionId: number, collectionAddress: string, contract: Contract }> => {9): Promise<{ collectionId: number, collectionAddress: string, contract: Contract }> => {10 const {collectionAddress, collectionId} = await helper.eth.createNonfungibleCollection(owner, 'A', 'B', 'C');10 const {collectionAddress, collectionId} = await helper.eth.createNFTCollection(owner, 'A', 'B', 'C');111112 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);12 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);13 await contract.methods.setCollectionNesting(true).send({from: owner});13 await contract.methods.setCollectionNesting(true).send({from: owner});tests/src/eth/nonFungible.test.tsdiffbeforeafterboth84 const receiver = helper.eth.createAccount();84 const receiver = helper.eth.createAccount();858586 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);86 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);87 let result = await collectionHelper.methods.createERC721MetadataCompatibleCollection('Mint collection', 'a', 'b', tokenPrefix).send({value: Number(2n * helper.balance.getOneTokenNominal())});87 let result = await collectionHelper.methods.createERC721MetadataNFTCollection('Mint collection', 'a', 'b', tokenPrefix).send({value: Number(2n * helper.balance.getOneTokenNominal())});88 const collectionAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);88 const collectionAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);89 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);89 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);90 90 146 const owner = await helper.eth.createAccountWithBalance(donor);146 const owner = await helper.eth.createAccountWithBalance(donor);147 const receiver = helper.eth.createAccount();147 const receiver = helper.eth.createAccount();148148149 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'Minty', '6', '6');149 const {collectionAddress} = await helper.eth.createERC721MetadataNFTCollection(owner, 'Mint collection', '6', '6', '');150 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);150 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);151 const nextTokenId = await contract.methods.nextTokenId().call();151 const nextTokenId = await contract.methods.nextTokenId().call();152152tests/src/eth/payable.test.tsdiffbeforeafterboth146 const caller = await helper.eth.createAccountWithBalance(donor);146 const caller = await helper.eth.createAccountWithBalance(donor);147 const contract = await deployProxyContract(helper, deployer);147 const contract = await deployProxyContract(helper, deployer);148148149 const collectionAddress = (await contract.methods.createNonfungibleCollection().send({from: caller, value: Number(CONTRACT_BALANCE)})).events.CollectionCreated.returnValues.collection;149 const collectionAddress = (await contract.methods.createNFTCollection().send({from: caller, value: Number(CONTRACT_BALANCE)})).events.CollectionCreated.returnValues.collection;150 const initialCallerBalance = await helper.balance.getEthereum(caller);150 const initialCallerBalance = await helper.balance.getEthereum(caller);151 const initialContractBalance = await helper.balance.getEthereum(contract.options.address);151 const initialContractBalance = await helper.balance.getEthereum(contract.options.address);152 await contract.methods.mintNftToken(collectionAddress).send({from: caller});152 await contract.methods.mintNftToken(collectionAddress).send({from: caller});164164165 const initialCallerBalance = await helper.balance.getEthereum(caller);165 const initialCallerBalance = await helper.balance.getEthereum(caller);166 const initialContractBalance = await helper.balance.getEthereum(contract.options.address);166 const initialContractBalance = await helper.balance.getEthereum(contract.options.address);167 await contract.methods.createNonfungibleCollection().send({from: caller, value: Number(CONTRACT_BALANCE)});167 await contract.methods.createNFTCollection().send({from: caller, value: Number(CONTRACT_BALANCE)});168 const finalCallerBalance = await helper.balance.getEthereum(caller);168 const finalCallerBalance = await helper.balance.getEthereum(caller);169 const finalContractBalance = await helper.balance.getEthereum(contract.options.address);169 const finalContractBalance = await helper.balance.getEthereum(contract.options.address);170 expect(finalCallerBalance < initialCallerBalance).to.be.true;170 expect(finalCallerBalance < initialCallerBalance).to.be.true;177 const caller = await helper.eth.createAccountWithBalance(donor);177 const caller = await helper.eth.createAccountWithBalance(donor);178 const collectionHelper = helper.ethNativeContract.collectionHelpers(caller);178 const collectionHelper = helper.ethNativeContract.collectionHelpers(caller);179 179 180 await expect(collectionHelper.methods.createNonfungibleCollection('A', 'B', 'C').call({value: Number(SMALL_FEE)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');180 await expect(collectionHelper.methods.createNFTCollection('A', 'B', 'C').call({value: Number(SMALL_FEE)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');181 await expect(collectionHelper.methods.createNonfungibleCollection('A', 'B', 'C').call({value: Number(BIG_FEE)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');181 await expect(collectionHelper.methods.createNFTCollection('A', 'B', 'C').call({value: Number(BIG_FEE)})).to.be.rejectedWith('Sent amount not equals to collection creation price (2000000000000000000)');182 });182 });183183184 itEth('Negative test: call createRFTCollection with wrong fee', async({helper}) => {184 itEth('Negative test: call createRFTCollection with wrong fee', async({helper}) => {200 return await helper.ethContract.deployByCode(200 return await helper.ethContract.deployByCode(201 deployer,201 deployer,202 'ProxyContract',202 'ProxyContract',203 `203 `204 // SPDX-License-Identifier: UNLICENSED204 // SPDX-License-Identifier: UNLICENSED205 pragma solidity ^0.8.6;205 pragma solidity ^0.8.6;206206207 import {CollectionHelpers} from "../api/CollectionHelpers.sol";207 import {CollectionHelpers} from "../api/CollectionHelpers.sol";208 import {UniqueNFT} from "../api/UniqueNFT.sol";208 import {UniqueNFT} from "../api/UniqueNFT.sol";209209210 error Value(uint256 value);210 error Value(uint256 value);211211212 contract ProxyContract {212 contract ProxyContract {213 bool value = false;213 bool value = false;214 address innerContract;214 address innerContract;215215216 event CollectionCreated(address collection);216 event CollectionCreated(address collection);217 event TokenMinted(uint256 tokenId);217 event TokenMinted(uint256 tokenId);218218219 receive() external payable {}219 receive() external payable {}220220221 constructor() {221 constructor() {222 innerContract = address(new InnerContract());222 innerContract = address(new InnerContract());223 }223 }224224225 function flip() public {225 function flip() public {226 value = !value;226 value = !value;227 InnerContract(innerContract).flip();227 InnerContract(innerContract).flip();228 }228 }229229230 function createNonfungibleCollection() external payable {230 function createNFTCollection() external payable {231 address collectionHelpers = 0x6C4E9fE1AE37a41E93CEE429e8E1881aBdcbb54F;231 address collectionHelpers = 0x6C4E9fE1AE37a41E93CEE429e8E1881aBdcbb54F;232 address nftCollection = CollectionHelpers(collectionHelpers).createNonfungibleCollection{value: msg.value}("A", "B", "C");232 address nftCollection = CollectionHelpers(collectionHelpers).createNFTCollection{value: msg.value}("A", "B", "C");233 emit CollectionCreated(nftCollection);233 emit CollectionCreated(nftCollection);234 }234 }235235236 function mintNftToken(address collectionAddress) external {236 function mintNftToken(address collectionAddress) external {237 UniqueNFT collection = UniqueNFT(collectionAddress);237 UniqueNFT collection = UniqueNFT(collectionAddress);238 uint256 tokenId = collection.nextTokenId();238 uint256 tokenId = collection.nextTokenId();239 collection.mint(msg.sender, tokenId);239 collection.mint(msg.sender, tokenId);240 emit TokenMinted(tokenId);240 emit TokenMinted(tokenId);241 }241 }242242243 function getValue() external view returns (bool) {243 function getValue() external view returns (bool) {244 return InnerContract(innerContract).getValue();244 return InnerContract(innerContract).getValue();245 }245 }246 }246 }247247248 contract InnerContract {248 contract InnerContract {249 bool value = false;249 bool value = false;250 function flip() external {250 function flip() external {251 value = !value;251 value = !value;252 }252 }253 function getValue() external view returns (bool) {253 function getValue() external view returns (bool) {254 return value;254 return value;255 }255 }256 }256 }257 `,257 `,258 [258 [259 {259 {260 solPath: 'api/CollectionHelpers.sol',260 solPath: 'api/CollectionHelpers.sol',tests/src/eth/proxy/nonFungibleProxy.test.tsdiffbeforeafterboth101101102 itEth('Can perform mint()', async ({helper}) => {102 itEth('Can perform mint()', async ({helper}) => {103 const owner = await helper.eth.createAccountWithBalance(donor);103 const owner = await helper.eth.createAccountWithBalance(donor);104 const {collectionAddress} = await helper.eth.createNonfungibleCollection(owner, 'A', 'A', 'A');104 const {collectionAddress} = await helper.eth.createERC721MetadataNFTCollection(owner, 'A', 'A', 'A', '');105 const caller = await helper.eth.createAccountWithBalance(donor);105 const caller = await helper.eth.createAccountWithBalance(donor);106 const receiver = helper.eth.createAccount();106 const receiver = helper.eth.createAccount();107107tests/src/eth/reFungible.test.tsdiffbeforeafterboth313132 itEth('totalSupply', async ({helper}) => {32 itEth('totalSupply', async ({helper}) => {33 const caller = await helper.eth.createAccountWithBalance(donor);33 const caller = await helper.eth.createAccountWithBalance(donor);34 const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'TotalSupply', '6', '6');34 const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'TotalSupply', '6', '6');35 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);35 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);36 const nextTokenId = await contract.methods.nextTokenId().call();36 const nextTokenId = await contract.methods.nextTokenId().call();37 await contract.methods.mint(caller, nextTokenId).send();37 await contract.methods.mint(caller, nextTokenId).send();414142 itEth('balanceOf', async ({helper}) => {42 itEth('balanceOf', async ({helper}) => {43 const caller = await helper.eth.createAccountWithBalance(donor);43 const caller = await helper.eth.createAccountWithBalance(donor);44 const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'BalanceOf', '6', '6');44 const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'BalanceOf', '6', '6');45 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);45 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);464647 {47 {636364 itEth('ownerOf', async ({helper}) => {64 itEth('ownerOf', async ({helper}) => {65 const caller = await helper.eth.createAccountWithBalance(donor);65 const caller = await helper.eth.createAccountWithBalance(donor);66 const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'OwnerOf', '6', '6');66 const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'OwnerOf', '6', '6');67 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);67 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);686869 const tokenId = await contract.methods.nextTokenId().call();69 const tokenId = await contract.methods.nextTokenId().call();76 itEth('ownerOf after burn', async ({helper}) => {76 itEth('ownerOf after burn', async ({helper}) => {77 const caller = await helper.eth.createAccountWithBalance(donor);77 const caller = await helper.eth.createAccountWithBalance(donor);78 const receiver = helper.eth.createAccount();78 const receiver = helper.eth.createAccount();79 const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'OwnerOf-AfterBurn', '6', '6');79 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'OwnerOf-AfterBurn', '6', '6');80 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);80 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);818182 const tokenId = await contract.methods.nextTokenId().call();82 const tokenId = await contract.methods.nextTokenId().call();95 itEth('ownerOf for partial ownership', async ({helper}) => {95 itEth('ownerOf for partial ownership', async ({helper}) => {96 const caller = await helper.eth.createAccountWithBalance(donor);96 const caller = await helper.eth.createAccountWithBalance(donor);97 const receiver = helper.eth.createAccount();97 const receiver = helper.eth.createAccount();98 const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Partial-OwnerOf', '6', '6');98 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'Partial-OwnerOf', '6', '6');99 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);99 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);100100101 const tokenId = await contract.methods.nextTokenId().call();101 const tokenId = await contract.methods.nextTokenId().call();124 itEth('Can perform mint()', async ({helper}) => {124 itEth('Can perform mint()', async ({helper}) => {125 const owner = await helper.eth.createAccountWithBalance(donor);125 const owner = await helper.eth.createAccountWithBalance(donor);126 const receiver = helper.eth.createAccount();126 const receiver = helper.eth.createAccount();127 const {collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Minty', '6', '6');127 const {collectionAddress} = await helper.eth.createERC721MetadataRFTCollection(owner, 'Minty', '6', '6', '');128 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);128 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);129 129 130 const nextTokenId = await contract.methods.nextTokenId().call();130 const nextTokenId = await contract.methods.nextTokenId().call();147 itEth('Can perform mintBulk()', async ({helper}) => {147 itEth('Can perform mintBulk()', async ({helper}) => {148 const owner = await helper.eth.createAccountWithBalance(donor);148 const owner = await helper.eth.createAccountWithBalance(donor);149 const receiver = helper.eth.createAccount();149 const receiver = helper.eth.createAccount();150 const {collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'MintBulky', '6', '6');150 const {collectionAddress} = await helper.eth.createERC721MetadataRFTCollection(owner, 'MintBulky', '6', '6', '');151 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);151 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);152152153 {153 {179179180 itEth('Can perform burn()', async ({helper}) => {180 itEth('Can perform burn()', async ({helper}) => {181 const caller = await helper.eth.createAccountWithBalance(donor);181 const caller = await helper.eth.createAccountWithBalance(donor);182 const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Burny', '6', '6');182 const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'Burny', '6', '6');183 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);183 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);184184185 const tokenId = await contract.methods.nextTokenId().call();185 const tokenId = await contract.methods.nextTokenId().call();197 itEth('Can perform transferFrom()', async ({helper}) => {197 itEth('Can perform transferFrom()', async ({helper}) => {198 const caller = await helper.eth.createAccountWithBalance(donor);198 const caller = await helper.eth.createAccountWithBalance(donor);199 const receiver = helper.eth.createAccount();199 const receiver = helper.eth.createAccount();200 const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'TransferFromy', '6', '6');200 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'TransferFromy', '6', '6');201 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);201 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);202202203 const tokenId = await contract.methods.nextTokenId().call();203 const tokenId = await contract.methods.nextTokenId().call();241 itEth('Can perform transfer()', async ({helper}) => {241 itEth('Can perform transfer()', async ({helper}) => {242 const caller = await helper.eth.createAccountWithBalance(donor);242 const caller = await helper.eth.createAccountWithBalance(donor);243 const receiver = helper.eth.createAccount();243 const receiver = helper.eth.createAccount();244 const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Transferry', '6', '6');244 const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'Transferry', '6', '6');245 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);245 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);246246247 const tokenId = await contract.methods.nextTokenId().call();247 const tokenId = await contract.methods.nextTokenId().call();271 itEth('transfer event on transfer from partial ownership to full ownership', async ({helper}) => {271 itEth('transfer event on transfer from partial ownership to full ownership', async ({helper}) => {272 const caller = await helper.eth.createAccountWithBalance(donor);272 const caller = await helper.eth.createAccountWithBalance(donor);273 const receiver = helper.eth.createAccount();273 const receiver = helper.eth.createAccount();274 const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Transferry-Partial-to-Full', '6', '6');274 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'Transferry-Partial-to-Full', '6', '6');275 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);275 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);276276277 const tokenId = await contract.methods.nextTokenId().call();277 const tokenId = await contract.methods.nextTokenId().call();298 itEth('transfer event on transfer from full ownership to partial ownership', async ({helper}) => {298 itEth('transfer event on transfer from full ownership to partial ownership', async ({helper}) => {299 const caller = await helper.eth.createAccountWithBalance(donor);299 const caller = await helper.eth.createAccountWithBalance(donor);300 const receiver = helper.eth.createAccount();300 const receiver = helper.eth.createAccount();301 const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Transferry-Full-to-Partial', '6', '6');301 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'Transferry-Full-to-Partial', '6', '6');302 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);302 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);303303304 const tokenId = await contract.methods.nextTokenId().call();304 const tokenId = await contract.methods.nextTokenId().call();336 itEth('transferFrom() call fee is less than 0.2UNQ', async ({helper}) => {336 itEth('transferFrom() call fee is less than 0.2UNQ', async ({helper}) => {337 const caller = await helper.eth.createAccountWithBalance(donor);337 const caller = await helper.eth.createAccountWithBalance(donor);338 const receiver = helper.eth.createAccount();338 const receiver = helper.eth.createAccount();339 const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Feeful-Transfer-From', '6', '6');339 const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'Feeful-Transfer-From', '6', '6');340 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);340 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);341341342 const tokenId = await contract.methods.nextTokenId().call();342 const tokenId = await contract.methods.nextTokenId().call();350 itEth('transfer() call fee is less than 0.2UNQ', async ({helper}) => {350 itEth('transfer() call fee is less than 0.2UNQ', async ({helper}) => {351 const caller = await helper.eth.createAccountWithBalance(donor);351 const caller = await helper.eth.createAccountWithBalance(donor);352 const receiver = helper.eth.createAccount();352 const receiver = helper.eth.createAccount();353 const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Feeful-Transfer', '6', '6');353 const {collectionAddress} = await helper.eth.createRFTCollection(caller, 'Feeful-Transfer', '6', '6');354 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);354 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);355355356 const tokenId = await contract.methods.nextTokenId().call();356 const tokenId = await contract.methods.nextTokenId().call();386386387 itEth('Returns symbol name', async ({helper}) => {387 itEth('Returns symbol name', async ({helper}) => {388 const caller = await helper.eth.createAccountWithBalance(donor);388 const caller = await helper.eth.createAccountWithBalance(donor);389 const {collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Leviathan', '', '12');389 const {collectionId} = await helper.rft.mintCollection(alice, {name: 'Leviathan', tokenPrefix: '12'});390 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);390 const contract = helper.ethNativeContract.collectionById(collectionId, 'rft', caller);391 const symbol = await contract.methods.symbol().call();391 const symbol = await contract.methods.symbol().call();392 expect(symbol).to.equal('12');392 expect(symbol).to.equal('12');393 });393 });tests/src/eth/reFungibleToken.test.tsdiffbeforeafterboth81 const receiver = helper.eth.createAccount();81 const receiver = helper.eth.createAccount();828283 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);83 const collectionHelper = helper.ethNativeContract.collectionHelpers(owner);84 let result = await collectionHelper.methods.createERC721MetadataCompatibleCollection('Mint collection', 'a', 'b', tokenPrefix).send({value: Number(2n * helper.balance.getOneTokenNominal())});84 let result = await collectionHelper.methods.createERC721MetadataNFTCollection('Mint collection', 'a', 'b', tokenPrefix).send({value: Number(2n * helper.balance.getOneTokenNominal())});85 const collectionAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);85 const collectionAddress = helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);86 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);86 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);87 87 294 itEth('Receiving Transfer event on burning into full ownership', async ({helper}) => {294 itEth('Receiving Transfer event on burning into full ownership', async ({helper}) => {295 const caller = await helper.eth.createAccountWithBalance(donor);295 const caller = await helper.eth.createAccountWithBalance(donor);296 const receiver = await helper.eth.createAccountWithBalance(donor);296 const receiver = await helper.eth.createAccountWithBalance(donor);297 const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(caller, 'Devastation', '6', '6');297 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(caller, 'Devastation', '6', '6');298 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);298 const contract = helper.ethNativeContract.collection(collectionAddress, 'rft', caller);299299300 const tokenId = await contract.methods.nextTokenId().call();300 const tokenId = await contract.methods.nextTokenId().call();479 itEth('Default parent token address and id', async ({helper}) => {479 itEth('Default parent token address and id', async ({helper}) => {480 const owner = await helper.eth.createAccountWithBalance(donor);480 const owner = await helper.eth.createAccountWithBalance(donor);481481482 const {collectionId, collectionAddress} = await helper.eth.createRefungibleCollection(owner, 'Sands', '', 'GRAIN');482 const {collectionId, collectionAddress} = await helper.eth.createRFTCollection(owner, 'Sands', '', 'GRAIN');483 const collectionContract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);483 const collectionContract = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);484 484 485 const tokenId = await collectionContract.methods.nextTokenId().call();485 const tokenId = await collectionContract.methods.nextTokenId().call();tests/src/eth/util/playgrounds/unique.dev.tsdiffbeforeafterboth174 return await this.helper.callRpc('api.rpc.eth.call', [{from: signer, to: contractAddress, data: abi}]);174 return await this.helper.callRpc('api.rpc.eth.call', [{from: signer, to: contractAddress, data: abi}]);175 }175 }176176177 async createNonfungibleCollection(signer: string, name: string, description: string, tokenPrefix: string): Promise<{collectionId: number, collectionAddress: string}> {177 async createNFTCollection(signer: string, name: string, description: string, tokenPrefix: string): Promise<{collectionId: number, collectionAddress: string}> {178 const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice();178 const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice();179 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);179 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);180 180 181 const result = await collectionHelper.methods.createNonfungibleCollection(name, description, tokenPrefix).send({value: Number(collectionCreationPrice)});181 const result = await collectionHelper.methods.createNFTCollection(name, description, tokenPrefix).send({value: Number(collectionCreationPrice)});182182183 const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);183 const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);184 const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress);184 const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress);185185186 return {collectionId, collectionAddress};186 return {collectionId, collectionAddress};187 }187 }188189 async createERC721MetadataNFTCollection(signer: string, name: string, description: string, tokenPrefix: string, baseUri: string): Promise<{collectionId: number, collectionAddress: string}> {190 const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice();191 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);192 193 const result = await collectionHelper.methods.createERC721MetadataNFTCollection(name, description, tokenPrefix, baseUri).send({value: Number(collectionCreationPrice)});194195 const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);196 const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress);197198 return {collectionId, collectionAddress};199 }188200189 async createRefungibleCollection(signer: string, name: string, description: string, tokenPrefix: string): Promise<{collectionId: number, collectionAddress: string}> {201 async createRFTCollection(signer: string, name: string, description: string, tokenPrefix: string): Promise<{collectionId: number, collectionAddress: string}> {190 const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice();202 const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice();191 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);203 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);192 204 198 return {collectionId, collectionAddress};210 return {collectionId, collectionAddress};199 }211 }212213 async createERC721MetadataRFTCollection(signer: string, name: string, description: string, tokenPrefix: string, baseUri: string): Promise<{collectionId: number, collectionAddress: string}> {214 const collectionCreationPrice = this.helper.balance.getCollectionCreationPrice();215 const collectionHelper = this.helper.ethNativeContract.collectionHelpers(signer);216 217 const result = await collectionHelper.methods.createERC721MetadataRFTCollection(name, description, tokenPrefix, baseUri).send({value: Number(collectionCreationPrice)});218219 const collectionAddress = this.helper.ethAddress.normalizeAddress(result.events.CollectionCreated.returnValues.collectionId);220 const collectionId = this.helper.ethAddress.extractCollectionId(collectionAddress);221222 return {collectionId, collectionAddress};223 }200224201 async deployCollectorContract(signer: string): Promise<Contract> {225 async deployCollectorContract(signer: string): Promise<Contract> {202 return await this.helper.ethContract.deployByCode(signer, 'Collector', `226 return await this.helper.ethContract.deployByCode(signer, 'Collector', `tests/src/nesting/properties.test.tsdiffbeforeafterboth19import {UniqueHelper, UniqueBaseCollection, UniqueNFTCollection, UniqueNFToken, UniqueRFTCollection, UniqueRFToken} from '../util/playgrounds/unique';19import {UniqueHelper, UniqueBaseCollection, UniqueNFTCollection, UniqueNFToken, UniqueRFTCollection, UniqueRFToken} from '../util/playgrounds/unique';20202122describe('Composite Properties Test', () => {23 let alice: IKeyringPair;2425 before(async () => {26 await usingPlaygrounds(async (helper, privateKey) => {27 const donor = privateKey('//Alice');28 [alice] = await helper.arrange.createAccounts([50n], donor);29 });30 });3132 async function testMakeSureSuppliesRequired(baseCollection: UniqueNFTCollection | UniqueRFTCollection) {3334 const collectionOption = await baseCollection.getOptions();35 expect(collectionOption).is.not.null;36 let collection = collectionOption;37 expect(collection.tokenPropertyPermissions).to.be.empty;38 expect(collection.properties).to.be.deep.equal([{key: 'ERC721Metadata', value: '1'}]);3940 const propertyPermissions = [41 {key: 'mindgame', permission: {collectionAdmin: true, mutable: false, tokenOwner: true}},42 {key: 'skullduggery', permission: {collectionAdmin: false, mutable: true, tokenOwner: false}},43 ];44 await expect(await baseCollection.setTokenPropertyPermissions(alice, propertyPermissions)).to.be.true;4546 const collectionProperties = [47 {key: 'ERC721Metadata', value: '1'}, 48 {key: 'black_hole', value: 'LIGO'},49 {key: 'electron', value: 'come bond'}, 50 ];51 52 await expect(await baseCollection.setProperties(alice, collectionProperties)).to.be.true;5354 collection = await baseCollection.getOptions();55 expect(collection.tokenPropertyPermissions).to.be.deep.equal(propertyPermissions);56 expect(collection.properties).to.be.deep.equal(collectionProperties);57 }5859 itSub('Makes sure collectionById supplies required fields for NFT', async ({helper}) => {60 await testMakeSureSuppliesRequired(await helper.nft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'}));61 });6263 itSub.ifWithPallets('Makes sure collectionById supplies required fields for ReFungible', [Pallets.ReFungible], async ({helper}) => {64 await testMakeSureSuppliesRequired(await helper.rft.mintCollection(alice, {name: 'A', description: 'B', tokenPrefix: 'C'}));65 });66});21// ---------- COLLECTION PROPERTIES67// ---------- COLLECTION PROPERTIES226823describe('Integration Test: Collection Properties', () => {69describe('Integration Test: Collection Properties', () => {337934 itSub('Properties are initially empty', async ({helper}) => {80 itSub('Properties are initially empty', async ({helper}) => {35 const collection = await helper.nft.mintCollection(alice);81 const collection = await helper.nft.mintCollection(alice);36 expect(await collection.getProperties()).to.be.empty;82 const properties = await collection.getProperties();83 expect(properties).to.be.deep.equal([{84 'key': 'ERC721Metadata',85 'value': '1',86 }]);37 });87 });388839 async function testSetsPropertiesForCollection(collection: UniqueBaseCollection) {89 async function testSetsPropertiesForCollection(collection: UniqueBaseCollection) {150 await expect(collection.setProperties(bob, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}]))200 await expect(collection.setProperties(bob, [{key: 'electron', value: 'come bond'}, {key: 'black_hole', value: 'LIGO'}]))151 .to.be.rejectedWith(/common\.NoPermission/);201 .to.be.rejectedWith(/common\.NoPermission/);152202153 expect(await collection.getProperties()).to.be.empty;203 const properties = await collection.getProperties();204 expect(properties).to.be.deep.equal([{205 'key': 'ERC721Metadata',206 'value': '1',207 }]);154 }208 }155209156 itSub('Fails to set properties in a NFT collection if not its onwer/administrator', async ({helper}) => {210 itSub('Fails to set properties in a NFT collection if not its onwer/administrator', async ({helper}) => {202 await expect(collection.setProperties(alice, propertiesToBeSet)).256 await expect(collection.setProperties(alice, propertiesToBeSet)).203 to.be.rejectedWith(/common\.PropertyLimitReached/);257 to.be.rejectedWith(/common\.PropertyLimitReached/);204258205 expect(await collection.getProperties()).to.be.empty;259 const properties = await collection.getProperties();260 expect(properties).to.be.deep.equal([{261 'key': 'ERC721Metadata',262 'value': '1',263 }]);206 }264 }207265208 itSub('Fails to set more properties than it is allowed (NFT)', async ({helper}) => {266 itSub('Fails to set more properties than it is allowed (NFT)', async ({helper}) => {tests/src/util/playgrounds/unique.tsdiffbeforeafterboth981 return (await this.helper.callRpc('api.rpc.unique.collectionProperties', [collectionId, propertyKeys])).toHuman();981 return (await this.helper.callRpc('api.rpc.unique.collectionProperties', [collectionId, propertyKeys])).toHuman();982 }982 }983984 async getCollectionOptions(collectionId: number) {985 return (await this.helper.callRpc('api.rpc.unique.collectionById', [collectionId])).toHuman();986 }983987984 /**988 /**985 * Deletes onchain properties from the collection.989 * Deletes onchain properties from the collection.1293 async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions, mode: 'NFT' | 'RFT'): Promise<UniqueBaseCollection> {1297 async mintCollection(signer: TSigner, collectionOptions: ICollectionCreationOptions, mode: 'NFT' | 'RFT'): Promise<UniqueBaseCollection> {1294 collectionOptions = JSON.parse(JSON.stringify(collectionOptions)) as ICollectionCreationOptions; // Clone object1298 collectionOptions = JSON.parse(JSON.stringify(collectionOptions)) as ICollectionCreationOptions; // Clone object1295 collectionOptions.mode = (mode === 'NFT') ? {nft: null} : {refungible: null};1299 collectionOptions.mode = (mode === 'NFT') ? {nft: null} : {refungible: null};1300 collectionOptions.properties = collectionOptions.properties || [{key: 'ERC721Metadata', value: '1'}];1296 for (const key of ['name', 'description', 'tokenPrefix']) {1301 for (const key of ['name', 'description', 'tokenPrefix']) {1297 if (typeof collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] === 'string') collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] = this.helper.util.str2vec(collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] as string);1302 if (typeof collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] === 'string') collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] = this.helper.util.str2vec(collectionOptions[key as 'name' | 'description' | 'tokenPrefix'] as string);1298 }1303 }2476 return await this.helper.collection.getTokenNextSponsored(this.collectionId, tokenId, addressObj);2481 return await this.helper.collection.getTokenNextSponsored(this.collectionId, tokenId, addressObj);2477 }2482 }24832484 async getOptions() {2485 return await this.helper.collection.getCollectionOptions(this.collectionId);2486 }247824872479 async setSponsor(signer: TSigner, sponsorAddress: TSubstrateAccount) {2488 async setSponsor(signer: TSigner, sponsorAddress: TSubstrateAccount) {2480 return await this.helper.collection.setSponsor(signer, this.collectionId, sponsorAddress);2489 return await this.helper.collection.setSponsor(signer, this.collectionId, sponsorAddress);