git.delta.rocks / unique-network / refs/commits / 2232fc1c912c

difftreelog

Merge pull request #391 from UniqueNetwork/feature/CORE-412

Yaroslav Bolyukin2022-07-27parents: #d4f7a1e #7e1b91d.patch.diff
in: master
Feature/core 412 Helper for create RFT collection

40 files changed

modifiedCargo.lockdiffbeforeafterboth
57315731
5732[[package]]5732[[package]]
5733name = "pallet-common"5733name = "pallet-common"
5734version = "0.1.2"5734version = "0.1.3"
5735dependencies = [5735dependencies = [
5736 "ethereum",5736 "ethereum",
5737 "evm-coder",5737 "evm-coder",
61986198
6199[[package]]6199[[package]]
6200name = "pallet-nonfungible"6200name = "pallet-nonfungible"
6201version = "0.1.1"6201version = "0.1.2"
6202dependencies = [6202dependencies = [
6203 "ethereum",6203 "ethereum",
6204 "evm-coder",6204 "evm-coder",
66386638
6639[[package]]6639[[package]]
6640name = "pallet-unique"6640name = "pallet-unique"
6641version = "0.1.0"6641version = "0.1.1"
6642dependencies = [6642dependencies = [
6643 "ethereum",6643 "ethereum",
6644 "evm-coder",6644 "evm-coder",
6649 "pallet-evm",6649 "pallet-evm",
6650 "pallet-evm-coder-substrate",6650 "pallet-evm-coder-substrate",
6651 "pallet-nonfungible",6651 "pallet-nonfungible",
6652 "pallet-refungible",
6652 "parity-scale-codec 3.1.5",6653 "parity-scale-codec 3.1.5",
6653 "scale-info",6654 "scale-info",
6654 "serde",6655 "serde",
1273612737
12737[[package]]12738[[package]]
12738name = "up-data-structs"12739name = "up-data-structs"
12739version = "0.1.1"12740version = "0.1.2"
12740dependencies = [12741dependencies = [
12741 "derivative",12742 "derivative",
12742 "frame-support",12743 "frame-support",
modifiedMakefilediffbeforeafterboth
9FUNGIBLE_EVM_STUBS=./pallets/fungible/src/stubs9FUNGIBLE_EVM_STUBS=./pallets/fungible/src/stubs
10FUNGIBLE_EVM_ABI=./tests/src/eth/fungibleAbi.json10FUNGIBLE_EVM_ABI=./tests/src/eth/fungibleAbi.json
11
12REFUNGIBLE_EVM_STUBS=./pallets/refungible/src/stubs
13REFUNGIBLE_EVM_ABI=./tests/src/eth/refungibleAbi.json
1114
12NONFUNGIBLE_EVM_STUBS=./pallets/nonfungible/src/stubs15NONFUNGIBLE_EVM_STUBS=./pallets/nonfungible/src/stubs
13NONFUNGIBLE_EVM_ABI=./tests/src/eth/nonFungibleAbi.json16NONFUNGIBLE_EVM_ABI=./tests/src/eth/nonFungibleAbi.json
1417
15REFUNGIBLE_EVM_STUBS=./pallets/refungible/src/stubs
16RENFUNGIBLE_EVM_ABI=./tests/src/eth/reFungibleAbi.json18RENFUNGIBLE_EVM_ABI=./tests/src/eth/reFungibleAbi.json
17RENFUNGIBLE_TOKEN_EVM_ABI=./tests/src/eth/reFungibleTokenAbi.json19RENFUNGIBLE_TOKEN_EVM_ABI=./tests/src/eth/reFungibleTokenAbi.json
1820
25TESTS_API=./tests/src/eth/api/27TESTS_API=./tests/src/eth/api/
2628
27.PHONY: regenerate_solidity29.PHONY: regenerate_solidity
28regenerate_solidity: UniqueFungible.sol UniqueNFT.sol UniqueRefungibleToken.sol ContractHelpers.sol CollectionHelpers.sol30regenerate_solidity: UniqueFungible.sol UniqueNFT.sol UniqueRefungible.sol UniqueRefungibleToken.sol ContractHelpers.sol CollectionHelpers.sol
2931
30UniqueFungible.sol:32UniqueFungible.sol:
31 PACKAGE=pallet-fungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh33 PACKAGE=pallet-fungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh
35 PACKAGE=pallet-nonfungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh37 PACKAGE=pallet-nonfungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh
36 PACKAGE=pallet-nonfungible NAME=erc::gen_impl OUTPUT=$(NONFUNGIBLE_EVM_STUBS)/$@ ./.maintain/scripts/generate_sol.sh38 PACKAGE=pallet-nonfungible NAME=erc::gen_impl OUTPUT=$(NONFUNGIBLE_EVM_STUBS)/$@ ./.maintain/scripts/generate_sol.sh
37 39
40UniqueRefungible.sol:
41 PACKAGE=pallet-refungible NAME=erc::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh
42 PACKAGE=pallet-refungible NAME=erc::gen_impl OUTPUT=$(REFUNGIBLE_EVM_STUBS)/$@ ./.maintain/scripts/generate_sol.sh
43
38UniqueRefungibleToken.sol:44UniqueRefungibleToken.sol:
39 PACKAGE=pallet-refungible NAME=erc_token::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh45 PACKAGE=pallet-refungible NAME=erc_token::gen_iface OUTPUT=$(TESTS_API)/$@ ./.maintain/scripts/generate_sol.sh
59 INPUT=$(REFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(REFUNGIBLE_EVM_STUBS)/UniqueRefungibleToken.raw ./.maintain/scripts/compile_stub.sh65 INPUT=$(REFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(REFUNGIBLE_EVM_STUBS)/UniqueRefungibleToken.raw ./.maintain/scripts/compile_stub.sh
60 INPUT=$(REFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(RENFUNGIBLE_TOKEN_EVM_ABI) ./.maintain/scripts/generate_abi.sh66 INPUT=$(REFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(RENFUNGIBLE_TOKEN_EVM_ABI) ./.maintain/scripts/generate_abi.sh
67
68UniqueRefungible: UniqueRefungible.sol
69 INPUT=$(REFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(REFUNGIBLE_EVM_STUBS)/UniqueRefungible.raw ./.maintain/scripts/compile_stub.sh
70 INPUT=$(REFUNGIBLE_EVM_STUBS)/$< OUTPUT=$(REFUNGIBLE_EVM_ABI) ./.maintain/scripts/generate_abi.sh
6171
62ContractHelpers: ContractHelpers.sol72ContractHelpers: ContractHelpers.sol
63 INPUT=$(CONTRACT_HELPERS_STUBS)/$< OUTPUT=$(CONTRACT_HELPERS_STUBS)/ContractHelpers.raw ./.maintain/scripts/compile_stub.sh73 INPUT=$(CONTRACT_HELPERS_STUBS)/$< OUTPUT=$(CONTRACT_HELPERS_STUBS)/ContractHelpers.raw ./.maintain/scripts/compile_stub.sh
67 INPUT=$(COLLECTION_HELPER_STUBS)/$< OUTPUT=$(COLLECTION_HELPER_STUBS)/CollectionHelpers.raw ./.maintain/scripts/compile_stub.sh77 INPUT=$(COLLECTION_HELPER_STUBS)/$< OUTPUT=$(COLLECTION_HELPER_STUBS)/CollectionHelpers.raw ./.maintain/scripts/compile_stub.sh
68 INPUT=$(COLLECTION_HELPER_STUBS)/$< OUTPUT=$(COLLECTION_HELPER_ABI) ./.maintain/scripts/generate_abi.sh78 INPUT=$(COLLECTION_HELPER_STUBS)/$< OUTPUT=$(COLLECTION_HELPER_ABI) ./.maintain/scripts/generate_abi.sh
6979
70evm_stubs: UniqueFungible UniqueNFT UniqueRefungibleToken ContractHelpers CollectionHelpers80evm_stubs: UniqueFungible UniqueNFT UniqueRefungible UniqueRefungibleToken ContractHelpers CollectionHelpers
7181
72.PHONY: _bench82.PHONY: _bench
73_bench:83_bench:
modifiedpallets/common/CHANGELOG.MDdiffbeforeafterboth
22
3All notable changes to this project will be documented in this file.3All notable changes to this project will be documented in this file.
44
5## [0.1.3] - 2022-07-25
6### Add
7- Some static property keys and values.
8
5## [0.1.2] - 2022-07-209## [0.1.2] - 2022-07-20
610
7### Fixed11### Fixed
modifiedpallets/common/Cargo.tomldiffbeforeafterboth
1[package]1[package]
2name = "pallet-common"2name = "pallet-common"
3version = "0.1.2"3version = "0.1.3"
4license = "GPLv3"4license = "GPLv3"
5edition = "2021"5edition = "2021"
66
modifiedpallets/common/src/dispatch.rsdiffbeforeafterboth
8 weights::Pays,8 weights::Pays,
9 traits::Get,9 traits::Get,
10};10};
11use sp_runtime::DispatchError;
11use up_data_structs::{CollectionId, CreateCollectionData};12use up_data_structs::{CollectionId, CreateCollectionData};
1213
13use crate::{pallet::Config, CommonCollectionOperations, CollectionHandle};14use crate::{pallet::Config, CommonCollectionOperations, CollectionHandle};
78 fn create(79 fn create(
79 sender: T::CrossAccountId,80 sender: T::CrossAccountId,
80 data: CreateCollectionData<T::AccountId>,81 data: CreateCollectionData<T::AccountId>,
81 ) -> DispatchResult;82 ) -> Result<CollectionId, DispatchError>;
8283
83 /// Delete the collection.84 /// Delete the collection.
84 ///85 ///
modifiedpallets/common/src/erc.rsdiffbeforeafterboth
430 Ok(())430 Ok(())
431}431}
432432
433/// Get the "tokenURI" key as [PropertyKey](up_data_structs::PropertyKey).433/// Contains static property keys and values.
434pub fn token_uri_key() -> up_data_structs::PropertyKey {434pub mod static_property {
435 b"tokenURI"435 use evm_coder::{
436 execution::{Result, Error},
437 };
438 use alloc::format;
439
440 const EXPECT_CONVERT_ERROR: &str = "length < limit";
441
442 /// Keys.
443 pub mod key {
444 use super::*;
445
446 /// Key "schemaName".
447 pub fn schema_name() -> up_data_structs::PropertyKey {
448 property_key_from_bytes(b"schemaName").expect(EXPECT_CONVERT_ERROR)
449 }
450
451 /// Key "baseURI".
452 pub fn base_uri() -> up_data_structs::PropertyKey {
453 property_key_from_bytes(b"baseURI").expect(EXPECT_CONVERT_ERROR)
454 }
455
456 /// Key "url".
457 pub fn url() -> up_data_structs::PropertyKey {
458 property_key_from_bytes(b"url").expect(EXPECT_CONVERT_ERROR)
459 }
460
461 /// Key "suffix".
462 pub fn suffix() -> up_data_structs::PropertyKey {
463 property_key_from_bytes(b"suffix").expect(EXPECT_CONVERT_ERROR)
464 }
465 }
466
467 /// Values.
468 pub mod value {
469 use super::*;
470
471 /// Value "ERC721Metadata".
472 pub const ERC721_METADATA: &[u8] = b"ERC721Metadata";
473
474 /// Value for [`ERC721_METADATA`].
475 pub fn erc721() -> up_data_structs::PropertyValue {
476 property_value_from_bytes(ERC721_METADATA).expect(EXPECT_CONVERT_ERROR)
477 }
478 }
479
480 /// Convert `byte` to [`PropertyKey`].
481 pub fn property_key_from_bytes(bytes: &[u8]) -> Result<up_data_structs::PropertyKey> {
436 .to_vec()482 bytes.to_vec().try_into().map_err(|_| {
437 .try_into()483 Error::Revert(format!(
484 "Property key is too long. Max length is {}.",
485 up_data_structs::PropertyKey::bound()
486 ))
438 .expect("length < limit; qed")487 })
439}488 }
489
490 /// Convert `bytes` to [`PropertyValue`].
491 pub fn property_value_from_bytes(bytes: &[u8]) -> Result<up_data_structs::PropertyValue> {
492 bytes.to_vec().try_into().map_err(|_| {
493 Error::Revert(format!(
494 "Property key is too long. Max length is {}.",
495 up_data_structs::PropertyKey::bound()
496 ))
497 })
498 }
499}
440500
modifiedpallets/nonfungible/CHANGELOG.mddiffbeforeafterboth
22
3All notable changes to this project will be documented in this file.3All notable changes to this project will be documented in this file.
44
5## [0.1.2] - 2022-07-25
6### Changed
7- New `token_uri` retrieval logic:
8
9 If the collection has a `url` property and it is not empty, it is returned.
10 Else If the collection does not have a property with key `schemaName` or its value is not equal to `ERC721Metadata`, it return an error `tokenURI not set`.
11
12 If the property `baseURI` is empty or absent, return "" (empty string)
13 otherwise, if property `suffix` present and is non-empty, return concatenation of baseURI and suffix
14 otherwise, return concatenation of `baseURI` and stringified token id (decimal stringifying, without paddings).
15
5## [0.1.1] - 2022-07-1416## [0.1.1] - 2022-07-14
6
7### Added17### Added
818
9- Implementation of RPC method `token_owners`.19- Implementation of RPC method `token_owners`.
10 For reasons of compatibility with this pallet, returns only one owner if token exists.20 For reasons of compatibility with this pallet, returns only one owner if token exists.
11 This was an internal request to improve the web interface and support fractionalization event. 21 This was an internal request to improve the web interface and support fractionalization event.
22
modifiedpallets/nonfungible/Cargo.tomldiffbeforeafterboth
1[package]1[package]
2name = "pallet-nonfungible"2name = "pallet-nonfungible"
3version = "0.1.1"3version = "0.1.2"
4license = "GPLv3"4license = "GPLv3"
5edition = "2021"5edition = "2021"
66
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
33use pallet_evm_coder_substrate::dispatch_to_evm;33use pallet_evm_coder_substrate::dispatch_to_evm;
34use sp_std::vec::Vec;34use sp_std::vec::Vec;
35use pallet_common::{35use pallet_common::{
36 erc::{CommonEvmHandler, PrecompileResult, CollectionCall, token_uri_key},36 erc::{
37 CommonEvmHandler, PrecompileResult, CollectionCall,
38 static_property::{key, value as property_value},
39 },
37 CollectionHandle, CollectionPropertyPermissions,40 CollectionHandle, CollectionPropertyPermissions,
38};41};
39use pallet_evm::{account::CrossAccountId, PrecompileHandle};42use pallet_evm::{account::CrossAccountId, PrecompileHandle};
40use pallet_evm_coder_substrate::call;43use pallet_evm_coder_substrate::call;
41use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};44use pallet_structure::{SelfWeightOf as StructureWeight, weights::WeightInfo as _};
45use alloc::string::ToString;
4246
43use crate::{47use crate::{
44 AccountBalance, Config, CreateItemData, NonfungibleHandle, Pallet, TokenData, TokensMinted,48 AccountBalance, Config, CreateItemData, NonfungibleHandle, Pallet, TokenData, TokensMinted,
212 }216 }
213217
214 /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.218 /// @notice A distinct Uniform Resource Identifier (URI) for a given asset.
215 /// @dev Throws if `tokenId` is not a valid NFT. URIs are defined in RFC219 ///
216 /// 3986. The URI may point to a JSON file that conforms to the "ERC721220 /// @dev If the token has a `url` property and it is not empty, it is returned.
217 /// Metadata JSON Schema".221 /// Else If the collection does not have a property with key `schemaName` or its value is not equal to `ERC721Metadata`, it return an error `tokenURI not set`.
222 /// If the collection property `baseURI` is empty or absent, return "" (empty string)
223 /// otherwise, if token property `suffix` present and is non-empty, return concatenation of baseURI and suffix
224 /// otherwise, return concatenation of `baseURI` and stringified token id (decimal stringifying, without paddings).
225 ///
218 /// @return token's const_metadata226 /// @return token's const_metadata
219 #[solidity(rename_selector = "tokenURI")]227 #[solidity(rename_selector = "tokenURI")]
220 fn token_uri(&self, token_id: uint256) -> Result<string> {228 fn token_uri(&self, token_id: uint256) -> Result<string> {
221 let key = token_uri_key();229 let token_id_u32: u32 = token_id.try_into().map_err(|_| "token id overflow")?;
230
222 if !has_token_permission::<T>(self.id, &key) {231 if let Ok(url) = get_token_property(self, token_id_u32, &key::url()) {
232 if !url.is_empty() {
233 return Ok(url);
234 }
235 } else if !is_erc721_metadata_compatible::<T>(self.id) {
223 return Err("No tokenURI permission".into());236 return Err("tokenURI not set".into());
224 }237 }
225238
226 self.consume_store_reads(1)?;
227 let token_id: u32 = token_id.try_into().map_err(|_| "token id overflow")?;239 if let Some(base_uri) =
228240 pallet_common::Pallet::<T>::get_collection_property(self.id, &key::base_uri())
241 {
242 if !base_uri.is_empty() {
229 let properties = <TokenProperties<T>>::try_get((self.id, token_id))243 let base_uri = string::from_utf8(base_uri.into_inner()).map_err(|e| {
230 .map_err(|_| Error::Revert("Token properties not found".into()))?;244 Error::Revert(alloc::format!(
245 "Can not convert value \"baseURI\" to string with error \"{}\"",
246 e
247 ))
248 })?;
231 if let Some(property) = properties.get(&key) {249 if let Ok(suffix) = get_token_property(self, token_id_u32, &key::suffix()) {
250 if !suffix.is_empty() {
232 return Ok(string::from_utf8_lossy(property).into());251 return Ok(base_uri + suffix.as_str());
252 }
233 }253 }
254
255 return Ok(base_uri + token_id.to_string().as_str());
256 }
257 }
234258
235 Err("Property tokenURI not found".into())259 Ok("".into())
236 }260 }
237}261}
238262
469 token_id: uint256,493 token_id: uint256,
470 token_uri: string,494 token_uri: string,
471 ) -> Result<bool> {495 ) -> Result<bool> {
472 let key = token_uri_key();496 let key = key::url();
473 let permission = get_token_permission::<T>(self.id, &key)?;497 let permission = get_token_permission::<T>(self.id, &key)?;
474 if !permission.collection_admin {498 if !permission.collection_admin {
475 return Err("Operation is not allowed".into());499 return Err("Operation is not allowed".into());
520 }544 }
521}545}
546
547fn get_token_property<T: Config>(
548 collection: &CollectionHandle<T>,
549 token_id: u32,
550 key: &up_data_structs::PropertyKey,
551) -> Result<string> {
552 collection.consume_store_reads(1)?;
553 let properties = <TokenProperties<T>>::try_get((collection.id, token_id))
554 .map_err(|_| Error::Revert("Token properties not found".into()))?;
555 if let Some(property) = properties.get(key) {
556 return Ok(string::from_utf8_lossy(property).into());
557 }
558
559 Err("Property tokenURI not found".into())
560}
561
562fn is_erc721_metadata_compatible<T: Config>(collection_id: CollectionId) -> bool {
563 if let Some(shema_name) =
564 pallet_common::Pallet::<T>::get_collection_property(collection_id, &key::schema_name())
565 {
566 let shema_name = shema_name.into_inner();
567 shema_name == property_value::ERC721_METADATA
568 } else {
569 false
570 }
571}
522572
523fn get_token_permission<T: Config>(573fn get_token_permission<T: Config>(
524 collection_id: CollectionId,574 collection_id: CollectionId,
528 .map_err(|_| Error::Revert("No permissions for collection".into()))?;578 .map_err(|_| Error::Revert("No permissions for collection".into()))?;
529 let a = token_property_permissions579 let a = token_property_permissions
530 .get(key)580 .get(key)
531 .map(|p| p.clone())581 .map(Clone::clone)
532 .ok_or_else(|| Error::Revert("No permission".into()))?;582 .ok_or_else(|| {
583 let key = string::from_utf8(key.clone().into_inner()).unwrap_or_default();
584 Error::Revert(alloc::format!("No permission for key {}", key))
585 })?;
533 Ok(a)586 Ok(a)
534}587}
535588
656 to: address,709 to: address,
657 tokens: Vec<(uint256, string)>,710 tokens: Vec<(uint256, string)>,
658 ) -> Result<bool> {711 ) -> Result<bool> {
659 let key = token_uri_key();712 let key = key::url();
660 let caller = T::CrossAccountId::from_eth(caller);713 let caller = T::CrossAccountId::from_eth(caller);
661 let to = T::CrossAccountId::from_eth(to);714 let to = T::CrossAccountId::from_eth(to);
662 let mut expected_index = <TokensMinted<T>>::get(self.id)715 let mut expected_index = <TokensMinted<T>>::get(self.id)
modifiedpallets/nonfungible/src/stubs/UniqueNFT.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/refungible/CHANGELOG.mddiffbeforeafterboth
10test(refungible-pallet): add tests for ERC-20 EVM API for RFT token pieces ([#413](https://github.com/UniqueNetwork/unique-chain/pull/413))10test(refungible-pallet): add tests for ERC-20 EVM API for RFT token pieces ([#413](https://github.com/UniqueNetwork/unique-chain/pull/413))
1111
12## [v0.1.1] - 2022-07-1412## [v0.1.1] - 2022-07-14
13### Added
14- Support for properties for RFT collections and tokens.
1315
14### Other changes16### Other changes
1517
deletedpallets/refungible/Changelog.mddiffbeforeafterboth

no changes

modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
25use crate::{Config, RefungibleHandle};25use crate::{Config, RefungibleHandle};
2626
27#[solidity_interface(27#[solidity_interface(
28 name = "UniqueRFT",28 name = "UniqueRefungible",
29 is(via("CollectionHandle<T>", common_mut, Collection),)29 is(via("CollectionHandle<T>", common_mut, Collection),)
30)]30)]
31impl<T: Config> RefungibleHandle<T> where T::AccountId: From<[u8; 32]> {}31impl<T: Config> RefungibleHandle<T> where T::AccountId: From<[u8; 32]> {}
3232
33// Not a tests, but code generators33// Not a tests, but code generators
34generate_stubgen!(gen_impl, UniqueRFTCall<()>, true);34generate_stubgen!(gen_impl, UniqueRefungibleCall<()>, true);
35generate_stubgen!(gen_iface, UniqueRFTCall<()>, false);35generate_stubgen!(gen_iface, UniqueRefungibleCall<()>, false);
3636
37impl<T: Config> CommonEvmHandler for RefungibleHandle<T>37impl<T: Config> CommonEvmHandler for RefungibleHandle<T>
38where38where
43 self,43 self,
44 handle: &mut impl PrecompileHandle,44 handle: &mut impl PrecompileHandle,
45 ) -> Option<pallet_common::erc::PrecompileResult> {45 ) -> Option<pallet_common::erc::PrecompileResult> {
46 call::<T, UniqueRFTCall<T>, _, _>(handle, self)46 call::<T, UniqueRefungibleCall<T>, _, _>(handle, self)
47 }47 }
48}48}
4949
modifiedpallets/refungible/src/stubs/UniqueRefungible.rawdiffbeforeafterboth

binary blob — no preview

addedpallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth

no changes

modifiedpallets/refungible/src/stubs/UniqueRefungibleToken.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/refungible/src/stubs/UniqueRefungibleToken.soldiffbeforeafterboth
3333
34// Selector: 942e8b2234// Selector: 942e8b22
35contract ERC20 is Dummy, ERC165, ERC20Events {35contract ERC20 is Dummy, ERC165, ERC20Events {
36 // @return the name of the token.
37 //
36 // Selector: name() 06fdde0338 // Selector: name() 06fdde03
37 function name() public view returns (string memory) {39 function name() public view returns (string memory) {
38 require(false, stub_error);40 require(false, stub_error);
39 dummy;41 dummy;
40 return "";42 return "";
41 }43 }
4244
45 // @return the symbol of the token.
46 //
43 // Selector: symbol() 95d89b4147 // Selector: symbol() 95d89b41
44 function symbol() public view returns (string memory) {48 function symbol() public view returns (string memory) {
45 require(false, stub_error);49 require(false, stub_error);
46 dummy;50 dummy;
47 return "";51 return "";
48 }52 }
4953
54 // @dev Total number of tokens in existence
55 //
50 // Selector: totalSupply() 18160ddd56 // Selector: totalSupply() 18160ddd
51 function totalSupply() public view returns (uint256) {57 function totalSupply() public view returns (uint256) {
52 require(false, stub_error);58 require(false, stub_error);
53 dummy;59 dummy;
54 return 0;60 return 0;
55 }61 }
5662
63 // @dev Not supported
64 //
57 // Selector: decimals() 313ce56765 // Selector: decimals() 313ce567
58 function decimals() public view returns (uint8) {66 function decimals() public view returns (uint8) {
59 require(false, stub_error);67 require(false, stub_error);
60 dummy;68 dummy;
61 return 0;69 return 0;
62 }70 }
6371
72 // @dev Gets the balance of the specified address.
73 // @param owner The address to query the balance of.
74 // @return An uint256 representing the amount owned by the passed address.
75 //
64 // Selector: balanceOf(address) 70a0823176 // Selector: balanceOf(address) 70a08231
65 function balanceOf(address owner) public view returns (uint256) {77 function balanceOf(address owner) public view returns (uint256) {
66 require(false, stub_error);78 require(false, stub_error);
69 return 0;81 return 0;
70 }82 }
7183
84 // @dev Transfer token for a specified address
85 // @param to The address to transfer to.
86 // @param amount The amount to be transferred.
87 //
72 // Selector: transfer(address,uint256) a9059cbb88 // Selector: transfer(address,uint256) a9059cbb
73 function transfer(address to, uint256 amount) public returns (bool) {89 function transfer(address to, uint256 amount) public returns (bool) {
74 require(false, stub_error);90 require(false, stub_error);
78 return false;94 return false;
79 }95 }
8096
97 // @dev Transfer tokens from one address to another
98 // @param from address The address which you want to send tokens from
99 // @param to address The address which you want to transfer to
100 // @param amount uint256 the amount of tokens to be transferred
101 //
81 // Selector: transferFrom(address,address,uint256) 23b872dd102 // Selector: transferFrom(address,address,uint256) 23b872dd
82 function transferFrom(103 function transferFrom(
83 address from,104 address from,
92 return false;113 return false;
93 }114 }
94115
116 // @dev Approve the passed address to spend the specified amount of tokens on behalf of `msg.sender`.
117 // Beware that changing an allowance with this method brings the risk that someone may use both the old
118 // and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
119 // race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
120 // https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
121 // @param spender The address which will spend the funds.
122 // @param amount The amount of tokens to be spent.
123 //
95 // Selector: approve(address,uint256) 095ea7b3124 // Selector: approve(address,uint256) 095ea7b3
96 function approve(address spender, uint256 amount) public returns (bool) {125 function approve(address spender, uint256 amount) public returns (bool) {
97 require(false, stub_error);126 require(false, stub_error);
101 return false;130 return false;
102 }131 }
103132
133 // @dev Function to check the amount of tokens that an owner allowed to a spender.
134 // @param owner address The address which owns the funds.
135 // @param spender address The address which will spend the funds.
136 // @return A uint256 specifying the amount of tokens still available for the spender.
137 //
104 // Selector: allowance(address,address) dd62ed3e138 // Selector: allowance(address,address) dd62ed3e
105 function allowance(address owner, address spender)139 function allowance(address owner, address spender)
106 public140 public
117151
118// Selector: ab8deb37152// Selector: ab8deb37
119contract ERC20UniqueExtensions is Dummy, ERC165 {153contract ERC20UniqueExtensions is Dummy, ERC165 {
154 // @dev Function that burns an amount of the token of a given account,
155 // deducting from the sender's allowance for said account.
156 // @param from The account whose tokens will be burnt.
157 // @param amount The amount that will be burnt.
158 //
120 // Selector: burnFrom(address,uint256) 79cc6790159 // Selector: burnFrom(address,uint256) 79cc6790
121 function burnFrom(address from, uint256 amount) public returns (bool) {160 function burnFrom(address from, uint256 amount) public returns (bool) {
122 require(false, stub_error);161 require(false, stub_error);
126 return false;165 return false;
127 }166 }
128167
168 // @dev Function that changes total amount of the tokens.
169 // Throws if `msg.sender` doesn't owns all of the tokens.
170 // @param amount New total amount of the tokens.
171 //
129 // Selector: repartition(uint256) d2418ca7172 // Selector: repartition(uint256) d2418ca7
130 function repartition(uint256 amount) public returns (bool) {173 function repartition(uint256 amount) public returns (bool) {
131 require(false, stub_error);174 require(false, stub_error);
addedpallets/unique/CHANGELOG.mddiffbeforeafterboth

no changes

modifiedpallets/unique/Cargo.tomldiffbeforeafterboth
9license = 'GPLv3'9license = 'GPLv3'
10name = 'pallet-unique'10name = 'pallet-unique'
11repository = 'https://github.com/UniqueNetwork/unique-chain'11repository = 'https://github.com/UniqueNetwork/unique-chain'
12version = '0.1.0'12version = '0.1.1'
1313
14[package.metadata.docs.rs]14[package.metadata.docs.rs]
15targets = ['x86_64-unknown-linux-gnu']15targets = ['x86_64-unknown-linux-gnu']
103evm-coder = { default-features = false, path = '../../crates/evm-coder' }103evm-coder = { default-features = false, path = '../../crates/evm-coder' }
104pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }104pallet-evm-coder-substrate = { default-features = false, path = '../../pallets/evm-coder-substrate' }
105pallet-nonfungible = { default-features = false, path = '../../pallets/nonfungible' }105pallet-nonfungible = { default-features = false, path = '../../pallets/nonfungible' }
106pallet-refungible = { default-features = false, path = '../../pallets/refungible' }
106107
modifiedpallets/unique/src/eth/mod.rsdiffbeforeafterboth
17//! Implementation of CollectionHelpers contract.17//! Implementation of CollectionHelpers contract.
1818
19use core::marker::PhantomData;19use core::marker::PhantomData;
20use evm_coder::{execution::*, generate_stubgen, solidity_interface, weight, types::*};20use evm_coder::{execution::*, generate_stubgen, solidity_interface, solidity, weight, types::*};
21use ethereum as _;21use ethereum as _;
22use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};22use pallet_evm_coder_substrate::{SubstrateRecorder, WithRecorder};
23use pallet_evm::{OnMethodCall, PrecompileResult, account::CrossAccountId, PrecompileHandle};23use pallet_evm::{OnMethodCall, PrecompileResult, account::CrossAccountId, PrecompileHandle};
24use up_data_structs::{24use up_data_structs::{
25 CreateCollectionData, MAX_COLLECTION_DESCRIPTION_LENGTH, MAX_TOKEN_PREFIX_LENGTH,25 CollectionName, CollectionDescription, CollectionTokenPrefix, CreateCollectionData,
26 MAX_COLLECTION_NAME_LENGTH,26 CollectionMode, PropertyValue,
27};27};
28use frame_support::traits::Get;28use frame_support::traits::Get;
29use pallet_common::{29use pallet_common::{
30 CollectionById,30 CollectionById,
31 erc::{token_uri_key, CollectionHelpersEvents},31 erc::{
32 static_property::{key, value as property_value},
33 CollectionHelpersEvents,
34 },
35 dispatch::CollectionDispatch,
32};36};
33use crate::{SelfWeightOf, Config, weights::WeightInfo};37use crate::{SelfWeightOf, Config, weights::WeightInfo};
3438
47 }51 }
48}52}
53
54fn convert_data<T: Config>(
55 caller: caller,
56 name: string,
57 description: string,
58 token_prefix: string,
59 base_uri: string,
60) -> Result<(
61 T::CrossAccountId,
62 CollectionName,
63 CollectionDescription,
64 CollectionTokenPrefix,
65 PropertyValue,
66)> {
67 let caller = T::CrossAccountId::from_eth(caller);
68 let name = name
69 .encode_utf16()
70 .collect::<Vec<u16>>()
71 .try_into()
72 .map_err(|_| error_field_too_long(stringify!(name), CollectionName::bound()))?;
73 let description = description
74 .encode_utf16()
75 .collect::<Vec<u16>>()
76 .try_into()
77 .map_err(|_| {
78 error_field_too_long(stringify!(description), CollectionDescription::bound())
79 })?;
80 let token_prefix = token_prefix.into_bytes().try_into().map_err(|_| {
81 error_field_too_long(stringify!(token_prefix), CollectionTokenPrefix::bound())
82 })?;
83 let base_uri_value = base_uri
84 .into_bytes()
85 .try_into()
86 .map_err(|_| error_field_too_long(stringify!(token_prefix), PropertyValue::bound()))?;
87 Ok((caller, name, description, token_prefix, base_uri_value))
88}
89
90fn make_data<T: Config>(
91 name: CollectionName,
92 mode: CollectionMode,
93 description: CollectionDescription,
94 token_prefix: CollectionTokenPrefix,
95 base_uri_value: PropertyValue,
96 add_properties: bool,
97) -> Result<CreateCollectionData<T::AccountId>> {
98 let mut properties = up_data_structs::CollectionPropertiesVec::default();
99 let mut token_property_permissions =
100 up_data_structs::CollectionPropertiesPermissionsVec::default();
101
102 token_property_permissions
103 .try_push(up_data_structs::PropertyKeyPermission {
104 key: key::url(),
105 permission: up_data_structs::PropertyPermission {
106 mutable: false,
107 collection_admin: true,
108 token_owner: false,
109 },
110 })
111 .map_err(|e| Error::Revert(format!("{:?}", e)))?;
112
113 if add_properties {
114 token_property_permissions
115 .try_push(up_data_structs::PropertyKeyPermission {
116 key: key::suffix(),
117 permission: up_data_structs::PropertyPermission {
118 mutable: false,
119 collection_admin: true,
120 token_owner: false,
121 },
122 })
123 .map_err(|e| Error::Revert(format!("{:?}", e)))?;
124
125 properties
126 .try_push(up_data_structs::Property {
127 key: key::schema_name(),
128 value: property_value::erc721(),
129 })
130 .map_err(|e| Error::Revert(format!("{:?}", e)))?;
131
132 if !base_uri_value.is_empty() {
133 properties
134 .try_push(up_data_structs::Property {
135 key: key::base_uri(),
136 value: base_uri_value,
137 })
138 .map_err(|e| Error::Revert(format!("{:?}", e)))?;
139 }
140 }
141
142 let data = CreateCollectionData {
143 name,
144 mode,
145 description,
146 token_prefix,
147 token_property_permissions,
148 properties,
149 ..Default::default()
150 };
151 Ok(data)
152}
49153
50/// @title Contract, which allows users to operate with collections154/// @title Contract, which allows users to operate with collections
51#[solidity_interface(name = "CollectionHelpers", events(CollectionHelpersEvents))]155#[solidity_interface(name = "CollectionHelpers", events(CollectionHelpersEvents))]
52impl<T: Config + pallet_nonfungible::Config> EvmCollectionHelpers<T> {156impl<T> EvmCollectionHelpers<T>
157where
158 T: Config + pallet_nonfungible::Config + pallet_refungible::Config,
159{
53 /// Create an NFT collection160 /// Create an NFT collection
54 /// @param name Name of the collection161 /// @param name Name of the collection
62 name: string,169 name: string,
63 description: string,170 description: string,
64 token_prefix: string,171 token_prefix: string,
65 ) -> Result<address> {172 ) -> Result<address> {
173 let (caller, name, description, token_prefix, _base_uri_value) =
174 convert_data::<T>(caller, name, description, token_prefix, "".into())?;
175 let data = make_data::<T>(
176 name,
177 CollectionMode::NFT,
178 description,
179 token_prefix,
180 Default::default(),
181 false,
182 )?;
183 let collection_id = T::CollectionDispatch::create(caller, data)
184 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;
185
186 let address = pallet_common::eth::collection_id_to_address(collection_id);
187 Ok(address)
188 }
189
66 let caller = T::CrossAccountId::from_eth(caller);190 #[weight(<SelfWeightOf<T>>::create_collection())]
191 #[solidity(rename_selector = "createERC721MetadataCompatibleCollection")]
192 fn create_nonfungible_collection_with_properties(
193 &mut self,
194 caller: caller,
67 let name = name195 name: string,
68 .encode_utf16()196 description: string,
69 .collect::<Vec<u16>>()197 token_prefix: string,
70 .try_into()198 base_uri: string,
71 .map_err(|_| error_feild_too_long(stringify!(name), MAX_COLLECTION_NAME_LENGTH))?;199 ) -> Result<address> {
72 let description = description200 let (caller, name, description, token_prefix, base_uri_value) =
73 .encode_utf16()
74 .collect::<Vec<u16>>()201 convert_data::<T>(caller, name, description, token_prefix, base_uri)?;
75 .try_into()
76 .map_err(|_| {
77 error_feild_too_long(stringify!(description), MAX_COLLECTION_DESCRIPTION_LENGTH)
78 })?;
79 let token_prefix = token_prefix202 let data = make_data::<T>(
80 .into_bytes()203 name,
81 .try_into()204 CollectionMode::NFT,
205 description,
82 .map_err(|_| error_feild_too_long(stringify!(token_prefix), MAX_TOKEN_PREFIX_LENGTH))?;206 token_prefix,
83207 base_uri_value,
208 true,
209 )?;
84 let key = token_uri_key();210 let collection_id = T::CollectionDispatch::create(caller, data)
85 let permission = up_data_structs::PropertyPermission {211 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;
212
213 let address = pallet_common::eth::collection_id_to_address(collection_id);
214 Ok(address)
215 }
216
217 #[weight(<SelfWeightOf<T>>::create_collection())]
218 fn create_refungible_collection(
219 &self,
86 mutable: true,220 caller: caller,
87 collection_admin: true,221 name: string,
88 token_owner: false,222 description: string,
223 token_prefix: string,
224 ) -> Result<address> {
225 let (caller, name, description, token_prefix, _base_uri) =
89 };226 convert_data::<T>(caller, name, description, token_prefix, "".into())?;
90 let mut token_property_permissions =227 let data = make_data::<T>(
228 name,
91 up_data_structs::CollectionPropertiesPermissionsVec::default();229 CollectionMode::ReFungible,
92 token_property_permissions230 description,
231 token_prefix,
232 Default::default(),
233 false,
234 )?;
93 .try_push(up_data_structs::PropertyKeyPermission { key, permission })235 let collection_id = T::CollectionDispatch::create(caller, data)
94 .map_err(|e| Error::Revert(format!("{:?}", e)))?;236 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;
95237
96 let data = CreateCollectionData {238 let address = pallet_common::eth::collection_id_to_address(collection_id);
239 Ok(address)
240 }
241
242 #[weight(<SelfWeightOf<T>>::create_collection())]
243 #[solidity(rename_selector = "createERC721MetadataCompatibleRFTCollection")]
244 fn create_refungible_collection_with_properties(
245 &mut self,
246 caller: caller,
247 name: string,
248 description: string,
249 token_prefix: string,
250 base_uri: string,
251 ) -> Result<address> {
97 name,252 let (caller, name, description, token_prefix, base_uri_value) =
98 description,
99 token_prefix,
100 token_property_permissions,
101 ..Default::default()253 convert_data::<T>(caller, name, description, token_prefix, base_uri)?;
254 let data = make_data::<T>(
255 name,
256 CollectionMode::NFT,
257 description,
258 token_prefix,
259 base_uri_value,
260 true,
102 };261 )?;
103
104 let collection_id =262 let collection_id = T::CollectionDispatch::create(caller, data)
105 <pallet_nonfungible::Pallet<T>>::init_collection(caller.clone(), data, false)
106 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;263 .map_err(pallet_evm_coder_substrate::dispatch_to_evm::<T>)?;
107264
108 let address = pallet_common::eth::collection_id_to_address(collection_id);265 let address = pallet_common::eth::collection_id_to_address(collection_id);
109 Ok(address)266 Ok(address)
110 }267 }
111268
112 /// Check if a collection exists269 /// Check if a collection exists
113 /// @param collection_address Address of the collection in question270 /// @param collection_address Address of the collection in question
124281
125/// Implements [`OnMethodCall`], which delegates call to [`EvmCollectionHelpers`]282/// Implements [`OnMethodCall`], which delegates call to [`EvmCollectionHelpers`]
126pub struct CollectionHelpersOnMethodCall<T: Config>(PhantomData<*const T>);283pub struct CollectionHelpersOnMethodCall<T: Config>(PhantomData<*const T>);
127impl<T: Config + pallet_nonfungible::Config> OnMethodCall<T> for CollectionHelpersOnMethodCall<T> {284impl<T: Config + pallet_nonfungible::Config + pallet_refungible::Config> OnMethodCall<T>
285 for CollectionHelpersOnMethodCall<T>
286{
128 fn is_reserved(contract: &sp_core::H160) -> bool {287 fn is_reserved(contract: &sp_core::H160) -> bool {
152generate_stubgen!(collection_helper_impl, CollectionHelpersCall<()>, true);311generate_stubgen!(collection_helper_impl, CollectionHelpersCall<()>, true);
153generate_stubgen!(collection_helper_iface, CollectionHelpersCall<()>, false);312generate_stubgen!(collection_helper_iface, CollectionHelpersCall<()>, false);
154313
155fn error_feild_too_long(feild: &str, bound: u32) -> Error {314fn error_field_too_long(feild: &str, bound: usize) -> Error {
156 Error::Revert(format!("{} is too long. Max length is {}.", feild, bound))315 Error::Revert(format!("{} is too long. Max length is {}.", feild, bound))
157}316}
158317
modifiedpallets/unique/src/eth/stubs/CollectionHelpers.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/unique/src/eth/stubs/CollectionHelpers.soldiffbeforeafterboth
29 );29 );
30}30}
3131
32// Selector: 20947cd032// Selector: c20653fc
33contract CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {33contract CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {
34 // Selector: createNonfungibleCollection(string,string,string) e34a684434 // Selector: createNonfungibleCollection(string,string,string) e34a6844
35 function createNonfungibleCollection(35 function createNonfungibleCollection(
45 return 0x0000000000000000000000000000000000000000;45 return 0x0000000000000000000000000000000000000000;
46 }46 }
47
48 // Selector: createERC721MetadataCompatibleCollection(string,string,string,string) a634a5f9
49 function createERC721MetadataCompatibleCollection(
50 string memory name,
51 string memory description,
52 string memory tokenPrefix,
53 string memory baseUri
54 ) public returns (address) {
55 require(false, stub_error);
56 name;
57 description;
58 tokenPrefix;
59 baseUri;
60 dummy = 0;
61 return 0x0000000000000000000000000000000000000000;
62 }
63
64 // Selector: createRefungibleCollection(string,string,string) 44a68ad5
65 function createRefungibleCollection(
66 string memory name,
67 string memory description,
68 string memory tokenPrefix
69 ) public view returns (address) {
70 require(false, stub_error);
71 name;
72 description;
73 tokenPrefix;
74 dummy;
75 return 0x0000000000000000000000000000000000000000;
76 }
4777
48 // Selector: isCollectionExist(address) c3de149478 // Selector: isCollectionExist(address) c3de1494
49 function isCollectionExist(address collectionAddress)79 function isCollectionExist(address collectionAddress)
modifiedpallets/unique/src/lib.rsdiffbeforeafterboth
352352
353 // =========353 // =========
354354
355 T::CollectionDispatch::create(T::CrossAccountId::from_sub(sender), data)?;355 let _id = T::CollectionDispatch::create(T::CrossAccountId::from_sub(sender), data)?;
356356
357 Ok(())357 Ok(())
358 }358 }
addedprimitives/data-structs/CHANGELOG.mddiffbeforeafterboth

no changes

modifiedprimitives/data-structs/Cargo.tomldiffbeforeafterboth
6license = 'GPLv3'6license = 'GPLv3'
7homepage = "https://unique.network"7homepage = "https://unique.network"
8repository = 'https://github.com/UniqueNetwork/unique-chain'8repository = 'https://github.com/UniqueNetwork/unique-chain'
9version = '0.1.1'9version = '0.1.2'
1010
11[dependencies]11[dependencies]
12scale-info = { version = "2.0.1", default-features = false, features = [12scale-info = { version = "2.0.1", default-features = false, features = [
deletedprimitives/data-structs/Changelog.mddiffbeforeafterboth

no changes

modifiedprimitives/data-structs/src/lib.rsdiffbeforeafterboth
286 }286 }
287}287}
288
289pub type CollectionName = BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>;
290pub type CollectionDescription = BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>;
291pub type CollectionTokenPrefix = BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>;
288292
289/// Collection parameters, used in storage (see [`RpcCollection`] for the RPC version).293/// Collection parameters, used in storage (see [`RpcCollection`] for the RPC version).
290#[struct_versioning::versioned(version = 2, upper)]294#[struct_versioning::versioned(version = 2, upper)]
294 pub mode: CollectionMode,298 pub mode: CollectionMode,
295 #[version(..2)]299 #[version(..2)]
296 pub access: AccessMode,300 pub access: AccessMode,
297 pub name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,301 pub name: CollectionName,
298 pub description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,302 pub description: CollectionDescription,
299 pub token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,303 pub token_prefix: CollectionTokenPrefix,
300304
301 #[version(..2)]305 #[version(..2)]
302 pub mint_mode: bool,306 pub mint_mode: bool,
350 #[derivative(Default(value = "CollectionMode::NFT"))]354 #[derivative(Default(value = "CollectionMode::NFT"))]
351 pub mode: CollectionMode,355 pub mode: CollectionMode,
352 pub access: Option<AccessMode>,356 pub access: Option<AccessMode>,
353 pub name: BoundedVec<u16, ConstU32<MAX_COLLECTION_NAME_LENGTH>>,357 pub name: CollectionName,
354 pub description: BoundedVec<u16, ConstU32<MAX_COLLECTION_DESCRIPTION_LENGTH>>,358 pub description: CollectionDescription,
355 pub token_prefix: BoundedVec<u8, ConstU32<MAX_TOKEN_PREFIX_LENGTH>>,359 pub token_prefix: CollectionTokenPrefix,
356 pub pending_sponsor: Option<AccountId>,360 pub pending_sponsor: Option<AccountId>,
357 pub limits: Option<CollectionLimits>,361 pub limits: Option<CollectionLimits>,
358 pub permissions: Option<CollectionPermissions>,362 pub permissions: Option<CollectionPermissions>,
modifiedruntime/common/src/dispatch.rsdiffbeforeafterboth
17use frame_support::{dispatch::DispatchResult, ensure};17use frame_support::{dispatch::DispatchResult, ensure};
18use pallet_evm::{PrecompileHandle, PrecompileResult};18use pallet_evm::{PrecompileHandle, PrecompileResult};
19use sp_core::H160;19use sp_core::H160;
20use sp_runtime::DispatchError;
20use sp_std::{borrow::ToOwned, vec::Vec};21use sp_std::{borrow::ToOwned, vec::Vec};
21use pallet_common::{22use pallet_common::{
22 CollectionById, CollectionHandle, CommonCollectionOperations, erc::CommonEvmHandler,23 CollectionById, CollectionHandle, CommonCollectionOperations, erc::CommonEvmHandler,
30};31};
31use up_data_structs::{32use up_data_structs::{
32 CollectionMode, CreateCollectionData, MAX_DECIMAL_POINTS, mapping::TokenAddressMapping,33 CollectionMode, CreateCollectionData, MAX_DECIMAL_POINTS, mapping::TokenAddressMapping,
34 CollectionId,
33};35};
3436
35pub enum CollectionDispatchT<T>37pub enum CollectionDispatchT<T>
51 fn create(53 fn create(
52 sender: T::CrossAccountId,54 sender: T::CrossAccountId,
53 data: CreateCollectionData<T::AccountId>,55 data: CreateCollectionData<T::AccountId>,
54 ) -> DispatchResult {56 ) -> Result<CollectionId, DispatchError> {
55 let _id = match data.mode {57 let id = match data.mode {
56 CollectionMode::NFT => <PalletNonfungible<T>>::init_collection(sender, data, false)?,58 CollectionMode::NFT => <PalletNonfungible<T>>::init_collection(sender, data, false)?,
57 CollectionMode::Fungible(decimal_points) => {59 CollectionMode::Fungible(decimal_points) => {
58 // check params60 // check params
64 }66 }
65 CollectionMode::ReFungible => <PalletRefungible<T>>::init_collection(sender, data)?,67 CollectionMode::ReFungible => <PalletRefungible<T>>::init_collection(sender, data)?,
66 };68 };
67 Ok(())69 Ok(id)
68 }70 }
6971
70 fn destroy(sender: T::CrossAccountId, collection: CollectionHandle<T>) -> DispatchResult {72 fn destroy(sender: T::CrossAccountId, collection: CollectionHandle<T>) -> DispatchResult {
modifiedtests/src/eth/api/CollectionHelpers.soldiffbeforeafterboth
20 );20 );
21}21}
2222
23// Selector: 20947cd023// Selector: c20653fc
24interface CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {24interface CollectionHelpers is Dummy, ERC165, CollectionHelpersEvents {
25 // Selector: createNonfungibleCollection(string,string,string) e34a684425 // Selector: createNonfungibleCollection(string,string,string) e34a6844
26 function createNonfungibleCollection(26 function createNonfungibleCollection(
29 string memory tokenPrefix29 string memory tokenPrefix
30 ) external returns (address);30 ) external returns (address);
31
32 // Selector: createERC721MetadataCompatibleCollection(string,string,string,string) a634a5f9
33 function createERC721MetadataCompatibleCollection(
34 string memory name,
35 string memory description,
36 string memory tokenPrefix,
37 string memory baseUri
38 ) external returns (address);
39
40 // Selector: createRefungibleCollection(string,string,string) 44a68ad5
41 function createRefungibleCollection(
42 string memory name,
43 string memory description,
44 string memory tokenPrefix
45 ) external view returns (address);
3146
32 // Selector: isCollectionExist(address) c3de149447 // Selector: isCollectionExist(address) c3de1494
33 function isCollectionExist(address collectionAddress)48 function isCollectionExist(address collectionAddress)
addedtests/src/eth/api/UniqueRFT.soldiffbeforeafterboth

no changes

addedtests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth

no changes

modifiedtests/src/eth/api/UniqueRefungibleToken.soldiffbeforeafterboth
2424
25// Selector: 942e8b2225// Selector: 942e8b22
26interface ERC20 is Dummy, ERC165, ERC20Events {26interface ERC20 is Dummy, ERC165, ERC20Events {
27 // @return the name of the token.
28 //
27 // Selector: name() 06fdde0329 // Selector: name() 06fdde03
28 function name() external view returns (string memory);30 function name() external view returns (string memory);
2931
32 // @return the symbol of the token.
33 //
30 // Selector: symbol() 95d89b4134 // Selector: symbol() 95d89b41
31 function symbol() external view returns (string memory);35 function symbol() external view returns (string memory);
3236
37 // @dev Total number of tokens in existence
38 //
33 // Selector: totalSupply() 18160ddd39 // Selector: totalSupply() 18160ddd
34 function totalSupply() external view returns (uint256);40 function totalSupply() external view returns (uint256);
3541
42 // @dev Not supported
43 //
36 // Selector: decimals() 313ce56744 // Selector: decimals() 313ce567
37 function decimals() external view returns (uint8);45 function decimals() external view returns (uint8);
3846
47 // @dev Gets the balance of the specified address.
48 // @param owner The address to query the balance of.
49 // @return An uint256 representing the amount owned by the passed address.
50 //
39 // Selector: balanceOf(address) 70a0823151 // Selector: balanceOf(address) 70a08231
40 function balanceOf(address owner) external view returns (uint256);52 function balanceOf(address owner) external view returns (uint256);
4153
54 // @dev Transfer token for a specified address
55 // @param to The address to transfer to.
56 // @param amount The amount to be transferred.
57 //
42 // Selector: transfer(address,uint256) a9059cbb58 // Selector: transfer(address,uint256) a9059cbb
43 function transfer(address to, uint256 amount) external returns (bool);59 function transfer(address to, uint256 amount) external returns (bool);
4460
61 // @dev Transfer tokens from one address to another
62 // @param from address The address which you want to send tokens from
63 // @param to address The address which you want to transfer to
64 // @param amount uint256 the amount of tokens to be transferred
65 //
45 // Selector: transferFrom(address,address,uint256) 23b872dd66 // Selector: transferFrom(address,address,uint256) 23b872dd
46 function transferFrom(67 function transferFrom(
47 address from,68 address from,
48 address to,69 address to,
49 uint256 amount70 uint256 amount
50 ) external returns (bool);71 ) external returns (bool);
5172
73 // @dev Approve the passed address to spend the specified amount of tokens on behalf of `msg.sender`.
74 // Beware that changing an allowance with this method brings the risk that someone may use both the old
75 // and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
76 // race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
77 // https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
78 // @param spender The address which will spend the funds.
79 // @param amount The amount of tokens to be spent.
80 //
52 // Selector: approve(address,uint256) 095ea7b381 // Selector: approve(address,uint256) 095ea7b3
53 function approve(address spender, uint256 amount) external returns (bool);82 function approve(address spender, uint256 amount) external returns (bool);
5483
84 // @dev Function to check the amount of tokens that an owner allowed to a spender.
85 // @param owner address The address which owns the funds.
86 // @param spender address The address which will spend the funds.
87 // @return A uint256 specifying the amount of tokens still available for the spender.
88 //
55 // Selector: allowance(address,address) dd62ed3e89 // Selector: allowance(address,address) dd62ed3e
56 function allowance(address owner, address spender)90 function allowance(address owner, address spender)
57 external91 external
6195
62// Selector: ab8deb3796// Selector: ab8deb37
63interface ERC20UniqueExtensions is Dummy, ERC165 {97interface ERC20UniqueExtensions is Dummy, ERC165 {
98 // @dev Function that burns an amount of the token of a given account,
99 // deducting from the sender's allowance for said account.
100 // @param from The account whose tokens will be burnt.
101 // @param amount The amount that will be burnt.
102 //
64 // Selector: burnFrom(address,uint256) 79cc6790103 // Selector: burnFrom(address,uint256) 79cc6790
65 function burnFrom(address from, uint256 amount) external returns (bool);104 function burnFrom(address from, uint256 amount) external returns (bool);
66105
106 // @dev Function that changes total amount of the tokens.
107 // Throws if `msg.sender` doesn't owns all of the tokens.
108 // @param amount New total amount of the tokens.
109 //
67 // Selector: repartition(uint256) d2418ca7110 // Selector: repartition(uint256) d2418ca7
68 function repartition(uint256 amount) external returns (bool);111 function repartition(uint256 amount) external returns (bool);
69}112}
modifiedtests/src/eth/collectionHelpersAbi.jsondiffbeforeafterboth
18 "name": "CollectionCreated",18 "name": "CollectionCreated",
19 "type": "event"19 "type": "event"
20 },20 },
21 {
22 "inputs": [
23 { "internalType": "string", "name": "name", "type": "string" },
24 { "internalType": "string", "name": "description", "type": "string" },
25 { "internalType": "string", "name": "tokenPrefix", "type": "string" },
26 { "internalType": "string", "name": "baseUri", "type": "string" }
27 ],
28 "name": "createERC721MetadataCompatibleCollection",
29 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
30 "stateMutability": "nonpayable",
31 "type": "function"
32 },
21 {33 {
22 "inputs": [34 "inputs": [
23 { "internalType": "string", "name": "name", "type": "string" },35 { "internalType": "string", "name": "name", "type": "string" },
29 "stateMutability": "nonpayable",41 "stateMutability": "nonpayable",
30 "type": "function"42 "type": "function"
31 },43 },
44 {
45 "inputs": [
46 { "internalType": "string", "name": "name", "type": "string" },
47 { "internalType": "string", "name": "description", "type": "string" },
48 { "internalType": "string", "name": "tokenPrefix", "type": "string" }
49 ],
50 "name": "createRefungibleCollection",
51 "outputs": [{ "internalType": "address", "name": "", "type": "address" }],
52 "stateMutability": "view",
53 "type": "function"
54 },
32 {55 {
33 "inputs": [56 "inputs": [
34 {57 {
deletedtests/src/eth/createCollection.test.tsdiffbeforeafterboth

no changes

addedtests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth

no changes

addedtests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth

no changes

modifiedtests/src/eth/nonFungible.test.tsdiffbeforeafterboth
72 });72 });
73});73});
74
75describe('Check ERC721 token URI for NFT', () => {
76 itWeb3('Empty tokenURI', async ({web3, api, privateKeyWrapper}) => {
77 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
78 const helper = evmCollectionHelpers(web3, owner);
79 let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', '').send();
80 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
81 const receiver = createEthAccount(web3);
82 const contract = evmCollection(web3, owner, collectionIdAddress);
83
84 const nextTokenId = await contract.methods.nextTokenId().call();
85 expect(nextTokenId).to.be.equal('1');
86 result = await contract.methods.mint(
87 receiver,
88 nextTokenId,
89 ).send();
90
91 const events = normalizeEvents(result.events);
92 const address = collectionIdToAddress(collectionId);
93
94 expect(events).to.be.deep.equal([
95 {
96 address,
97 event: 'Transfer',
98 args: {
99 from: '0x0000000000000000000000000000000000000000',
100 to: receiver,
101 tokenId: nextTokenId,
102 },
103 },
104 ]);
105
106 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('');
107 });
108
109 itWeb3('TokenURI from url', async ({web3, api, privateKeyWrapper}) => {
110 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
111 const helper = evmCollectionHelpers(web3, owner);
112 let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', 'BaseURI_').send();
113 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
114 const receiver = createEthAccount(web3);
115 const contract = evmCollection(web3, owner, collectionIdAddress);
116
117 const nextTokenId = await contract.methods.nextTokenId().call();
118 expect(nextTokenId).to.be.equal('1');
119 result = await contract.methods.mint(
120 receiver,
121 nextTokenId,
122 ).send();
123
124 // Set URL
125 await contract.methods.setProperty(nextTokenId, 'url', Buffer.from('Token URI')).send();
126
127 const events = normalizeEvents(result.events);
128 const address = collectionIdToAddress(collectionId);
129
130 expect(events).to.be.deep.equal([
131 {
132 address,
133 event: 'Transfer',
134 args: {
135 from: '0x0000000000000000000000000000000000000000',
136 to: receiver,
137 tokenId: nextTokenId,
138 },
139 },
140 ]);
141
142 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Token URI');
143 });
144
145 itWeb3('TokenURI from baseURI + tokenId', async ({web3, api, privateKeyWrapper}) => {
146 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
147 const helper = evmCollectionHelpers(web3, owner);
148 let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', 'BaseURI_').send();
149 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
150 const receiver = createEthAccount(web3);
151 const contract = evmCollection(web3, owner, collectionIdAddress);
152
153 const nextTokenId = await contract.methods.nextTokenId().call();
154 expect(nextTokenId).to.be.equal('1');
155 result = await contract.methods.mint(
156 receiver,
157 nextTokenId,
158 ).send();
159
160 const events = normalizeEvents(result.events);
161 const address = collectionIdToAddress(collectionId);
162
163 expect(events).to.be.deep.equal([
164 {
165 address,
166 event: 'Transfer',
167 args: {
168 from: '0x0000000000000000000000000000000000000000',
169 to: receiver,
170 tokenId: nextTokenId,
171 },
172 },
173 ]);
174
175 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_' + nextTokenId);
176 });
177
178 itWeb3('TokenURI from baseURI + suffix', async ({web3, api, privateKeyWrapper}) => {
179 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
180 const helper = evmCollectionHelpers(web3, owner);
181 let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', 'BaseURI_').send();
182 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
183 const receiver = createEthAccount(web3);
184 const contract = evmCollection(web3, owner, collectionIdAddress);
185
186 const nextTokenId = await contract.methods.nextTokenId().call();
187 expect(nextTokenId).to.be.equal('1');
188 result = await contract.methods.mint(
189 receiver,
190 nextTokenId,
191 ).send();
192
193 // Set suffix
194 const suffix = '/some/suffix';
195 await contract.methods.setProperty(nextTokenId, 'suffix', Buffer.from(suffix)).send();
196
197 const events = normalizeEvents(result.events);
198 const address = collectionIdToAddress(collectionId);
199
200 expect(events).to.be.deep.equal([
201 {
202 address,
203 event: 'Transfer',
204 args: {
205 from: '0x0000000000000000000000000000000000000000',
206 to: receiver,
207 tokenId: nextTokenId,
208 },
209 },
210 ]);
211
212 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_' + suffix);
213 });
214});
74215
75describe('NFT: Plain calls', () => {216describe('NFT: Plain calls', () => {
76 itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {217 itWeb3('Can perform mint()', async ({web3, api, privateKeyWrapper}) => {
modifiedtests/src/eth/reFungibleToken.test.tsdiffbeforeafterboth
15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.15// along with Unique Network. If not, see <http://www.gnu.org/licenses/>.
1616
17import {approve, createCollection, createRefungibleToken, transfer, transferFrom, UNIQUE} from '../util/helpers';17import {approve, createCollection, createRefungibleToken, transfer, transferFrom, UNIQUE} from '../util/helpers';
18import {createEthAccount, createEthAccountWithBalance, GAS_ARGS, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, tokenIdToAddress, transferBalanceToEth} from './util/helpers';18import {collectionIdToAddress, createEthAccount, createEthAccountWithBalance, evmCollection, evmCollectionHelpers, GAS_ARGS, getCollectionAddressFromResult, itWeb3, normalizeEvents, recordEthFee, recordEvents, subToEth, tokenIdToAddress, transferBalanceToEth} from './util/helpers';
19import reFungibleTokenAbi from './reFungibleTokenAbi.json';19import reFungibleTokenAbi from './reFungibleTokenAbi.json';
2020
21import chai from 'chai';21import chai from 'chai';
73 });73 });
74});74});
75
76// FIXME: Need erc721 for ReFubgible.
77describe.skip('Check ERC721 token URI for ReFungible', () => {
78 itWeb3('Empty tokenURI', async ({web3, api, privateKeyWrapper}) => {
79 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
80 const helper = evmCollectionHelpers(web3, owner);
81 let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', '').send();
82 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
83 const receiver = createEthAccount(web3);
84 const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});
85
86 const nextTokenId = await contract.methods.nextTokenId().call();
87 expect(nextTokenId).to.be.equal('1');
88 result = await contract.methods.mint(
89 receiver,
90 nextTokenId,
91 ).send();
92
93 const events = normalizeEvents(result.events);
94 const address = collectionIdToAddress(collectionId);
95
96 expect(events).to.be.deep.equal([
97 {
98 address,
99 event: 'Transfer',
100 args: {
101 from: '0x0000000000000000000000000000000000000000',
102 to: receiver,
103 tokenId: nextTokenId,
104 },
105 },
106 ]);
107
108 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('');
109 });
110
111 itWeb3('TokenURI from url', async ({web3, api, privateKeyWrapper}) => {
112 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
113 const helper = evmCollectionHelpers(web3, owner);
114 let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', 'BaseURI_').send();
115 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
116 const receiver = createEthAccount(web3);
117 const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});
118
119 const nextTokenId = await contract.methods.nextTokenId().call();
120 expect(nextTokenId).to.be.equal('1');
121 result = await contract.methods.mint(
122 receiver,
123 nextTokenId,
124 ).send();
125
126 // Set URL
127 await contract.methods.setProperty(nextTokenId, 'url', Buffer.from('Token URI')).send();
128
129 const events = normalizeEvents(result.events);
130 const address = collectionIdToAddress(collectionId);
131
132 expect(events).to.be.deep.equal([
133 {
134 address,
135 event: 'Transfer',
136 args: {
137 from: '0x0000000000000000000000000000000000000000',
138 to: receiver,
139 tokenId: nextTokenId,
140 },
141 },
142 ]);
143
144 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('Token URI');
145 });
146
147 itWeb3('TokenURI from baseURI + tokenId', async ({web3, api, privateKeyWrapper}) => {
148 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
149 const helper = evmCollectionHelpers(web3, owner);
150 let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', 'BaseURI_').send();
151 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
152 const receiver = createEthAccount(web3);
153 const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});
154
155 const nextTokenId = await contract.methods.nextTokenId().call();
156 expect(nextTokenId).to.be.equal('1');
157 result = await contract.methods.mint(
158 receiver,
159 nextTokenId,
160 ).send();
161
162 const events = normalizeEvents(result.events);
163 const address = collectionIdToAddress(collectionId);
164
165 expect(events).to.be.deep.equal([
166 {
167 address,
168 event: 'Transfer',
169 args: {
170 from: '0x0000000000000000000000000000000000000000',
171 to: receiver,
172 tokenId: nextTokenId,
173 },
174 },
175 ]);
176
177 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_' + nextTokenId);
178 });
179
180 itWeb3('TokenURI from baseURI + suffix', async ({web3, api, privateKeyWrapper}) => {
181 const owner = await createEthAccountWithBalance(api, web3, privateKeyWrapper);
182 const helper = evmCollectionHelpers(web3, owner);
183 let result = await helper.methods.createERC721MetadataCompatibleCollection('Mint collection', '1', '1', 'BaseURI_').send();
184 const {collectionIdAddress, collectionId} = await getCollectionAddressFromResult(api, result);
185 const receiver = createEthAccount(web3);
186 const contract = evmCollection(web3, owner, collectionIdAddress, {type: 'ReFungible'});
187
188 const nextTokenId = await contract.methods.nextTokenId().call();
189 expect(nextTokenId).to.be.equal('1');
190 result = await contract.methods.mint(
191 receiver,
192 nextTokenId,
193 ).send();
194
195 // Set suffix
196 const suffix = '/some/suffix';
197 await contract.methods.setProperty(nextTokenId, 'suffix', Buffer.from(suffix)).send();
198
199 const events = normalizeEvents(result.events);
200 const address = collectionIdToAddress(collectionId);
201
202 expect(events).to.be.deep.equal([
203 {
204 address,
205 event: 'Transfer',
206 args: {
207 from: '0x0000000000000000000000000000000000000000',
208 to: receiver,
209 tokenId: nextTokenId,
210 },
211 },
212 ]);
213
214 expect(await contract.methods.tokenURI(nextTokenId).call()).to.be.equal('BaseURI_' + suffix);
215 });
216});
75217
76describe('Refungible: Plain calls', () => {218describe('Refungible: Plain calls', () => {
77 itWeb3('Can perform approve()', async ({web3, api, privateKeyWrapper}) => {219 itWeb3('Can perform approve()', async ({web3, api, privateKeyWrapper}) => {
addedtests/src/eth/refungibleAbi.jsondiffbeforeafterboth

no changes

modifiedtests/src/eth/util/helpers.tsdiffbeforeafterboth
25import Web3 from 'web3';25import Web3 from 'web3';
26import config from '../../config';26import config from '../../config';
27import getBalance from '../../substrate/get-balance';27import getBalance from '../../substrate/get-balance';
28import privateKey from '../../substrate/privateKey';
29import usingApi, {submitTransactionAsync} from '../../substrate/substrate-api';28import usingApi, {submitTransactionAsync} from '../../substrate/substrate-api';
30import waitNewBlocks from '../../substrate/wait-new-blocks';29import waitNewBlocks from '../../substrate/wait-new-blocks';
31import {CrossAccountId, getDetailedCollectionInfo, getGenericResult, UNIQUE} from '../../util/helpers';30import {CollectionMode, CrossAccountId, getDetailedCollectionInfo, getGenericResult, UNIQUE} from '../../util/helpers';
32import collectionHelpersAbi from '../collectionHelpersAbi.json';31import collectionHelpersAbi from '../collectionHelpersAbi.json';
32import fungibleAbi from '../fungibleAbi.json';
33import nonFungibleAbi from '../nonFungibleAbi.json';33import nonFungibleAbi from '../nonFungibleAbi.json';
34import refungibleAbi from '../refungibleAbi.json';
34import contractHelpersAbi from './contractHelpersAbi.json';35import contractHelpersAbi from './contractHelpersAbi.json';
3536
36export const GAS_ARGS = {gas: 2500000};37export const GAS_ARGS = {gas: 2500000};
307 * @param caller - eth address308 * @param caller - eth address
308 * @returns 309 * @returns
309 */310 */
310export function evmCollection(web3: Web3, caller: string, collection: string) {311export function evmCollection(web3: Web3, caller: string, collection: string, mode: CollectionMode = {type: 'NFT'}) {
312 let abi;
313 switch (mode.type) {
314 case 'Fungible':
315 abi = fungibleAbi;
316 break;
317
318 case 'NFT':
319 abi = nonFungibleAbi;
320 break;
321
322 case 'ReFungible':
323 abi = refungibleAbi;
324 break;
325
326 default:
327 throw 'Bad collection mode';
328 }
311 return new web3.eth.Contract(nonFungibleAbi as any, collection, {from: caller, ...GAS_ARGS});329 const contract = new web3.eth.Contract(abi as any, collection, {from: caller, ...GAS_ARGS});
330 return contract;
312}331}
313332
314/**333/**