git.delta.rocks / unique-network / refs/commits / 48762e7ec756

difftreelog

Added new call functions - The functions `description`, `crossOwnerOf`, `tokenProperties` to `ERC721UniqueExtensions` to solidity interfaces.

PraetorP2022-11-18parent: #074bf74.patch.diff
in: master

22 files changed

modifiedpallets/fungible/CHANGELOG.mddiffbeforeafterboth
44
5<!-- bureaucrate goes here -->5<!-- bureaucrate goes here -->
66
7## [0.1.8] - 2022-11-18
8
9### Added
10
11- The function `description` to `ERC20UniqueExtensions` interface.
12
7## [0.1.7] - 2022-11-1413## [0.1.7] - 2022-11-14
814
9### Changed15### Changed
1016
11- Added `transfer_cross` in eth functions.17- Added `transfer_cross` in eth functions.
18
19### Changed
20
21- Use named structure `EthCrossAccount` in eth functions.
1222
13## [0.1.6] - 2022-11-0223## [0.1.6] - 2022-11-02
1424
modifiedpallets/fungible/src/erc.rsdiffbeforeafterboth
158where158where
159 T::AccountId: From<[u8; 32]>,159 T::AccountId: From<[u8; 32]>,
160{160{
161 /// @notice A description for the collection.
162 fn description(&self) -> Result<string> {
163 Ok(decode_utf16(self.description.iter().copied())
164 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
165 .collect::<string>())
166 }
167
161 #[weight(<SelfWeightOf<T>>::approve())]168 #[weight(<SelfWeightOf<T>>::approve())]
162 fn approve_cross(169 fn approve_cross(
modifiedpallets/fungible/src/stubs/UniqueFungible.soldiffbeforeafterboth
439439
440/// @dev the ERC-165 identifier for this interface is 0x29f4dcd9440/// @dev the ERC-165 identifier for this interface is 0x29f4dcd9
441contract ERC20UniqueExtensions is Dummy, ERC165 {441contract ERC20UniqueExtensions is Dummy, ERC165 {
442 /// @notice A description for the collection.
443 /// @dev EVM selector for this function is: 0x7284e416,
444 /// or in textual repr: description()
445 function description() public view returns (string memory) {
446 require(false, stub_error);
447 dummy;
448 return "";
449 }
450
442 /// @dev EVM selector for this function is: 0x0ecd0ab0,451 /// @dev EVM selector for this function is: 0x0ecd0ab0,
443 /// or in textual repr: approveCross((address,uint256),uint256)452 /// or in textual repr: approveCross((address,uint256),uint256)
modifiedpallets/nonfungible/CHANGELOG.mddiffbeforeafterboth
44
5<!-- bureaucrate goes here -->5<!-- bureaucrate goes here -->
66
7## [0.1.10] - 2022-11-18
8
9### Added
10
11- The functions `description`, `crossOwnerOf`, `tokenProperties` to `ERC721UniqueExtensions` interface.
12
7## [0.1.9] - 2022-11-1413## [0.1.9] - 2022-11-14
814
9### Changed15### Changed
modifiedpallets/nonfungible/src/erc.rsdiffbeforeafterboth
37use sp_std::vec::Vec;37use sp_std::vec::Vec;
38use pallet_common::{38use pallet_common::{
39 erc::{CommonEvmHandler, PrecompileResult, CollectionCall, static_property::key},39 erc::{CommonEvmHandler, PrecompileResult, CollectionCall, static_property::key},
40 CollectionHandle, CollectionPropertyPermissions,40 CollectionHandle, CollectionPropertyPermissions, CommonCollectionOperations,
41};41};
42use pallet_evm::{account::CrossAccountId, PrecompileHandle};42use pallet_evm::{account::CrossAccountId, PrecompileHandle};
43use pallet_evm_coder_substrate::call;43use pallet_evm_coder_substrate::call;
278#[solidity_interface(name = ERC721Metadata, expect_selector = 0x5b5e139f)]278#[solidity_interface(name = ERC721Metadata, expect_selector = 0x5b5e139f)]
279impl<T: Config> NonfungibleHandle<T>279impl<T: Config> NonfungibleHandle<T>
280where280where
281 T::AccountId: From<[u8; 32]>,281 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,
282{282{
283 /// @notice A descriptive name for a collection of NFTs in this contract283 /// @notice A descriptive name for a collection of NFTs in this contract
284 /// @dev real implementation of this function lies in `ERC721UniqueExtensions`284 /// @dev real implementation of this function lies in `ERC721UniqueExtensions`
686#[solidity_interface(name = ERC721UniqueExtensions)]686#[solidity_interface(name = ERC721UniqueExtensions)]
687impl<T: Config> NonfungibleHandle<T>687impl<T: Config> NonfungibleHandle<T>
688where688where
689 T::AccountId: From<[u8; 32]>,689 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,
690{690{
691 /// @notice A descriptive name for a collection of NFTs in this contract691 /// @notice A descriptive name for a collection of NFTs in this contract
692 fn name(&self) -> Result<string> {692 fn name(&self) -> Result<string> {
700 Ok(string::from_utf8_lossy(&self.token_prefix).into())700 Ok(string::from_utf8_lossy(&self.token_prefix).into())
701 }701 }
702
703 /// @notice A description for the collection.
704 fn description(&self) -> Result<string> {
705 Ok(decode_utf16(self.description.iter().copied())
706 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
707 .collect::<string>())
708 }
709
710 /// Returns the owner (in cross format) of the token.
711 ///
712 /// @param tokenId Id for the token.
713 fn cross_owner_of(&self, token_id: uint256) -> Result<EthCrossAccount> {
714 Self::token_owner(&self, token_id.try_into()?)
715 .map(|o| EthCrossAccount::from_sub_cross_account::<T>(&o))
716 .ok_or(Error::Revert("key too large".into()))
717 }
718
719 /// Returns the token properties.
720 ///
721 /// @param tokenId Id for the token.
722 /// @param keys Properties keys. Empty keys for all propertyes.
723 /// @return Vector of properties key/value pairs.
724 fn token_properties(
725 &self,
726 token_id: uint256,
727 keys: Vec<string>,
728 ) -> Result<Vec<(string, bytes)>> {
729 let keys = keys
730 .into_iter()
731 .map(|key| {
732 <Vec<u8>>::from(key)
733 .try_into()
734 .map_err(|_| Error::Revert("key too large".into()))
735 })
736 .collect::<Result<Vec<_>>>()?;
737
738 <Self as CommonCollectionOperations<T>>::token_properties(
739 &self,
740 token_id.try_into()?,
741 if keys.is_empty() { None } else { Some(keys) },
742 )
743 .into_iter()
744 .map(|p| {
745 let key = string::from_utf8(p.key.to_vec())
746 .map_err(|e| Error::Revert(alloc::format!("{}", e)))?;
747 let value = bytes(p.value.to_vec());
748 Ok((key, value))
749 })
750 .collect::<Result<Vec<_>>>()
751 }
702752
703 /// @notice Set or reaffirm the approved address for an NFT753 /// @notice Set or reaffirm the approved address for an NFT
704 /// @dev The zero address indicates there is no approved address.754 /// @dev The zero address indicates there is no approved address.
modifiedpallets/nonfungible/src/stubs/UniqueNFT.soldiffbeforeafterboth
702 return "";702 return "";
703 }703 }
704
705 /// @notice A description for the collection.
706 /// @dev EVM selector for this function is: 0x7284e416,
707 /// or in textual repr: description()
708 function description() public view returns (string memory) {
709 require(false, stub_error);
710 dummy;
711 return "";
712 }
713
714 /// Returns the owner (in cross format) of the token.
715 ///
716 /// @param tokenId Id for the token.
717 /// @dev EVM selector for this function is: 0x2b29dace,
718 /// or in textual repr: crossOwnerOf(uint256)
719 function crossOwnerOf(uint256 tokenId) public view returns (EthCrossAccount memory) {
720 require(false, stub_error);
721 tokenId;
722 dummy;
723 return EthCrossAccount(0x0000000000000000000000000000000000000000, 0);
724 }
725
726 /// Returns the token properties.
727 ///
728 /// @param tokenId Id for the token.
729 /// @param keys Properties keys. Empty keys for all propertyes.
730 /// @return Vector of properties key/value pairs.
731 /// @dev EVM selector for this function is: 0xefc26c69,
732 /// or in textual repr: tokenProperties(uint256,string[])
733 function tokenProperties(uint256 tokenId, string[] memory keys) public view returns (Tuple8[] memory) {
734 require(false, stub_error);
735 tokenId;
736 keys;
737 dummy;
738 return new Tuple8[](0);
739 }
704740
705 /// @notice Set or reaffirm the approved address for an NFT741 /// @notice Set or reaffirm the approved address for an NFT
706 /// @dev The zero address indicates there is no approved address.742 /// @dev The zero address indicates there is no approved address.
841 string field_1;877 string field_1;
842}878}
879
880/// @dev anonymous struct
881struct Tuple8 {
882 string field_0;
883 bytes field_1;
884}
843885
844/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension886/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
845/// @dev See https://eips.ethereum.org/EIPS/eip-721887/// @dev See https://eips.ethereum.org/EIPS/eip-721
modifiedpallets/refungible/CHANGELOG.mddiffbeforeafterboth
44
5<!-- bureaucrate goes here -->5<!-- bureaucrate goes here -->
66
7## [0.2.9] - 2022-11-18
8
9### Added
10
11- The functions `description`, `crossOwnerOf`, `tokenProperties` to `ERC721UniqueExtensions` interface.
12
7## [0.2.8] - 2022-11-1413## [0.2.8] - 2022-11-14
814
9### Changed15### Changed
modifiedpallets/refungible/src/erc.rsdiffbeforeafterboth
33use pallet_common::{33use pallet_common::{
34 CollectionHandle, CollectionPropertyPermissions,34 CollectionHandle, CollectionPropertyPermissions,
35 erc::{CommonEvmHandler, CollectionCall, static_property::key},35 erc::{CommonEvmHandler, CollectionCall, static_property::key},
36 CommonCollectionOperations,
36};37};
37use pallet_evm::{account::CrossAccountId, PrecompileHandle};38use pallet_evm::{account::CrossAccountId, PrecompileHandle};
38use pallet_evm_coder_substrate::{call, dispatch_to_evm};39use pallet_evm_coder_substrate::{call, dispatch_to_evm};
273#[solidity_interface(name = ERC721Metadata)]274#[solidity_interface(name = ERC721Metadata)]
274impl<T: Config> RefungibleHandle<T>275impl<T: Config> RefungibleHandle<T>
275where276where
276 T::AccountId: From<[u8; 32]>,277 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,
277{278{
278 /// @notice A descriptive name for a collection of NFTs in this contract279 /// @notice A descriptive name for a collection of NFTs in this contract
279 /// @dev real implementation of this function lies in `ERC721UniqueExtensions`280 /// @dev real implementation of this function lies in `ERC721UniqueExtensions`
713#[solidity_interface(name = ERC721UniqueExtensions)]714#[solidity_interface(name = ERC721UniqueExtensions)]
714impl<T: Config> RefungibleHandle<T>715impl<T: Config> RefungibleHandle<T>
715where716where
716 T::AccountId: From<[u8; 32]>,717 T::AccountId: From<[u8; 32]> + AsRef<[u8; 32]>,
717{718{
718 /// @notice A descriptive name for a collection of NFTs in this contract719 /// @notice A descriptive name for a collection of NFTs in this contract
719 fn name(&self) -> Result<string> {720 fn name(&self) -> Result<string> {
727 Ok(string::from_utf8_lossy(&self.token_prefix).into())728 Ok(string::from_utf8_lossy(&self.token_prefix).into())
728 }729 }
729730
731 /// @notice A description for the collection.
732 fn description(&self) -> Result<string> {
733 Ok(decode_utf16(self.description.iter().copied())
734 .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
735 .collect::<string>())
736 }
737
738 /// Returns the owner (in cross format) of the token.
739 ///
740 /// @param tokenId Id for the token.
741 fn cross_owner_of(&self, token_id: uint256) -> Result<EthCrossAccount> {
742 Self::token_owner(&self, token_id.try_into()?)
743 .map(|o| EthCrossAccount::from_sub_cross_account::<T>(&o))
744 .ok_or(Error::Revert("key too large".into()))
745 }
746
747 /// Returns the token properties.
748 ///
749 /// @param tokenId Id for the token.
750 /// @param keys Properties keys. Empty keys for all propertyes.
751 /// @return Vector of properties key/value pairs.
752 fn token_properties(
753 &self,
754 token_id: uint256,
755 keys: Vec<string>,
756 ) -> Result<Vec<(string, bytes)>> {
757 let keys = keys
758 .into_iter()
759 .map(|key| {
760 <Vec<u8>>::from(key)
761 .try_into()
762 .map_err(|_| Error::Revert("key too large".into()))
763 })
764 .collect::<Result<Vec<_>>>()?;
765
766 <Self as CommonCollectionOperations<T>>::token_properties(
767 &self,
768 token_id.try_into()?,
769 if keys.is_empty() { None } else { Some(keys) },
770 )
771 .into_iter()
772 .map(|p| {
773 let key = string::from_utf8(p.key.to_vec())
774 .map_err(|e| Error::Revert(alloc::format!("{}", e)))?;
775 let value = bytes(p.value.to_vec());
776 Ok((key, value))
777 })
778 .collect::<Result<Vec<_>>>()
779 }
730 /// @notice Transfer ownership of an RFT780 /// @notice Transfer ownership of an RFT
731 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`781 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
732 /// is the zero address. Throws if `tokenId` is not a valid RFT.782 /// is the zero address. Throws if `tokenId` is not a valid RFT.
modifiedpallets/refungible/src/stubs/UniqueRefungible.soldiffbeforeafterboth
700 return "";700 return "";
701 }701 }
702
703 /// @notice A description for the collection.
704 /// @dev EVM selector for this function is: 0x7284e416,
705 /// or in textual repr: description()
706 function description() public view returns (string memory) {
707 require(false, stub_error);
708 dummy;
709 return "";
710 }
711
712 /// Returns the owner (in cross format) of the token.
713 ///
714 /// @param tokenId Id for the token.
715 /// @dev EVM selector for this function is: 0x2b29dace,
716 /// or in textual repr: crossOwnerOf(uint256)
717 function crossOwnerOf(uint256 tokenId) public view returns (EthCrossAccount memory) {
718 require(false, stub_error);
719 tokenId;
720 dummy;
721 return EthCrossAccount(0x0000000000000000000000000000000000000000, 0);
722 }
723
724 /// Returns the token properties.
725 ///
726 /// @param tokenId Id for the token.
727 /// @param keys Properties keys. Empty keys for all propertyes.
728 /// @return Vector of properties key/value pairs.
729 /// @dev EVM selector for this function is: 0xefc26c69,
730 /// or in textual repr: tokenProperties(uint256,string[])
731 function tokenProperties(uint256 tokenId, string[] memory keys) public view returns (Tuple8[] memory) {
732 require(false, stub_error);
733 tokenId;
734 keys;
735 dummy;
736 return new Tuple8[](0);
737 }
702738
703 /// @notice Transfer ownership of an RFT739 /// @notice Transfer ownership of an RFT
704 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`740 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
840 string field_1;876 string field_1;
841}877}
878
879/// @dev anonymous struct
880struct Tuple8 {
881 string field_0;
882 bytes field_1;
883}
842884
843/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension885/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
844/// @dev See https://eips.ethereum.org/EIPS/eip-721886/// @dev See https://eips.ethereum.org/EIPS/eip-721
modifiedtests/src/eth/abi/fungible.jsondiffbeforeafterboth
281 "stateMutability": "nonpayable",281 "stateMutability": "nonpayable",
282 "type": "function"282 "type": "function"
283 },283 },
284 {
285 "inputs": [],
286 "name": "description",
287 "outputs": [{ "internalType": "string", "name": "", "type": "string" }],
288 "stateMutability": "view",
289 "type": "function"
290 },
284 {291 {
285 "inputs": [],292 "inputs": [],
286 "name": "hasCollectionPendingSponsor",293 "name": "hasCollectionPendingSponsor",
modifiedtests/src/eth/abi/nonFungible.jsondiffbeforeafterboth
295 "stateMutability": "view",295 "stateMutability": "view",
296 "type": "function"296 "type": "function"
297 },297 },
298 {
299 "inputs": [
300 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
301 ],
302 "name": "crossOwnerOf",
303 "outputs": [
304 {
305 "components": [
306 { "internalType": "address", "name": "eth", "type": "address" },
307 { "internalType": "uint256", "name": "sub", "type": "uint256" }
308 ],
309 "internalType": "struct EthCrossAccount",
310 "name": "",
311 "type": "tuple"
312 }
313 ],
314 "stateMutability": "view",
315 "type": "function"
316 },
298 {317 {
299 "inputs": [318 "inputs": [
300 { "internalType": "string[]", "name": "keys", "type": "string[]" }319 { "internalType": "string[]", "name": "keys", "type": "string[]" }
314 "stateMutability": "nonpayable",333 "stateMutability": "nonpayable",
315 "type": "function"334 "type": "function"
316 },335 },
336 {
337 "inputs": [],
338 "name": "description",
339 "outputs": [{ "internalType": "string", "name": "", "type": "string" }],
340 "stateMutability": "view",
341 "type": "function"
342 },
317 {343 {
318 "inputs": [],344 "inputs": [],
319 "name": "finishMinting",345 "name": "finishMinting",
639 "stateMutability": "view",665 "stateMutability": "view",
640 "type": "function"666 "type": "function"
641 },667 },
668 {
669 "inputs": [
670 { "internalType": "uint256", "name": "tokenId", "type": "uint256" },
671 { "internalType": "string[]", "name": "keys", "type": "string[]" }
672 ],
673 "name": "tokenProperties",
674 "outputs": [
675 {
676 "components": [
677 { "internalType": "string", "name": "field_0", "type": "string" },
678 { "internalType": "bytes", "name": "field_1", "type": "bytes" }
679 ],
680 "internalType": "struct Tuple8[]",
681 "name": "",
682 "type": "tuple[]"
683 }
684 ],
685 "stateMutability": "view",
686 "type": "function"
687 },
642 {688 {
643 "inputs": [689 "inputs": [
644 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }690 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
modifiedtests/src/eth/abi/reFungible.jsondiffbeforeafterboth
277 "stateMutability": "view",277 "stateMutability": "view",
278 "type": "function"278 "type": "function"
279 },279 },
280 {
281 "inputs": [
282 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
283 ],
284 "name": "crossOwnerOf",
285 "outputs": [
286 {
287 "components": [
288 { "internalType": "address", "name": "eth", "type": "address" },
289 { "internalType": "uint256", "name": "sub", "type": "uint256" }
290 ],
291 "internalType": "struct EthCrossAccount",
292 "name": "",
293 "type": "tuple"
294 }
295 ],
296 "stateMutability": "view",
297 "type": "function"
298 },
280 {299 {
281 "inputs": [300 "inputs": [
282 { "internalType": "string[]", "name": "keys", "type": "string[]" }301 { "internalType": "string[]", "name": "keys", "type": "string[]" }
296 "stateMutability": "nonpayable",315 "stateMutability": "nonpayable",
297 "type": "function"316 "type": "function"
298 },317 },
318 {
319 "inputs": [],
320 "name": "description",
321 "outputs": [{ "internalType": "string", "name": "", "type": "string" }],
322 "stateMutability": "view",
323 "type": "function"
324 },
299 {325 {
300 "inputs": [],326 "inputs": [],
301 "name": "finishMinting",327 "name": "finishMinting",
630 "stateMutability": "view",656 "stateMutability": "view",
631 "type": "function"657 "type": "function"
632 },658 },
659 {
660 "inputs": [
661 { "internalType": "uint256", "name": "tokenId", "type": "uint256" },
662 { "internalType": "string[]", "name": "keys", "type": "string[]" }
663 ],
664 "name": "tokenProperties",
665 "outputs": [
666 {
667 "components": [
668 { "internalType": "string", "name": "field_0", "type": "string" },
669 { "internalType": "bytes", "name": "field_1", "type": "bytes" }
670 ],
671 "internalType": "struct Tuple8[]",
672 "name": "",
673 "type": "tuple[]"
674 }
675 ],
676 "stateMutability": "view",
677 "type": "function"
678 },
633 {679 {
634 "inputs": [680 "inputs": [
635 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }681 { "internalType": "uint256", "name": "tokenId", "type": "uint256" }
modifiedtests/src/eth/api/UniqueFungible.soldiffbeforeafterboth
292292
293/// @dev the ERC-165 identifier for this interface is 0x29f4dcd9293/// @dev the ERC-165 identifier for this interface is 0x29f4dcd9
294interface ERC20UniqueExtensions is Dummy, ERC165 {294interface ERC20UniqueExtensions is Dummy, ERC165 {
295 /// @notice A description for the collection.
296 /// @dev EVM selector for this function is: 0x7284e416,
297 /// or in textual repr: description()
298 function description() external view returns (string memory);
299
295 /// @dev EVM selector for this function is: 0x0ecd0ab0,300 /// @dev EVM selector for this function is: 0x0ecd0ab0,
296 /// or in textual repr: approveCross((address,uint256),uint256)301 /// or in textual repr: approveCross((address,uint256),uint256)
modifiedtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth
45 /// @param properties settable properties45 /// @param properties settable properties
46 /// @dev EVM selector for this function is: 0x14ed3a6e,46 /// @dev EVM selector for this function is: 0x14ed3a6e,
47 /// or in textual repr: setProperties(uint256,(string,bytes)[])47 /// or in textual repr: setProperties(uint256,(string,bytes)[])
48 function setProperties(uint256 tokenId, Property[] memory properties) external;48 function setProperties(uint256 tokenId, Tuple21[] memory properties) external;
4949
50 // /// @notice Delete token property value.50 // /// @notice Delete token property value.
51 // /// @dev Throws error if `msg.sender` has no permission to edit the property.51 // /// @dev Throws error if `msg.sender` has no permission to edit the property.
95 /// @param properties Vector of properties key/value pair.95 /// @param properties Vector of properties key/value pair.
96 /// @dev EVM selector for this function is: 0x50b26b2a,96 /// @dev EVM selector for this function is: 0x50b26b2a,
97 /// or in textual repr: setCollectionProperties((string,bytes)[])97 /// or in textual repr: setCollectionProperties((string,bytes)[])
98 function setCollectionProperties(Property[] memory properties) external;98 function setCollectionProperties(Tuple21[] memory properties) external;
9999
100 // /// Delete collection property.100 // /// Delete collection property.
101 // ///101 // ///
127 /// @return Vector of properties key/value pairs.127 /// @return Vector of properties key/value pairs.
128 /// @dev EVM selector for this function is: 0x285fb8e6,128 /// @dev EVM selector for this function is: 0x285fb8e6,
129 /// or in textual repr: collectionProperties(string[])129 /// or in textual repr: collectionProperties(string[])
130 function collectionProperties(string[] memory keys) external view returns (Tuple23[] memory);130 function collectionProperties(string[] memory keys) external view returns (Tuple21[] memory);
131131
132 // /// Set the sponsor of the collection.132 // /// Set the sponsor of the collection.
133 // ///133 // ///
169 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.169 /// @return Tuble with sponsor address and his substrate mirror. If there is no confirmed sponsor error "Contract has no sponsor" throw.
170 /// @dev EVM selector for this function is: 0x6ec0a9f1,170 /// @dev EVM selector for this function is: 0x6ec0a9f1,
171 /// or in textual repr: collectionSponsor()171 /// or in textual repr: collectionSponsor()
172 function collectionSponsor() external view returns (Tuple26 memory);172 function collectionSponsor() external view returns (Tuple24 memory);
173173
174 /// Set limits for the collection.174 /// Set limits for the collection.
175 /// @dev Throws error if limit not found.175 /// @dev Throws error if limit not found.
346}346}
347347
348/// @dev anonymous struct348/// @dev anonymous struct
349struct Tuple26 {349struct Tuple24 {
350 address field_0;350 address field_0;
351 uint256 field_1;351 uint256 field_1;
352}352}
353353
354/// @dev anonymous struct354/// @dev anonymous struct
355struct Tuple23 {355struct Tuple21 {
356 string field_0;356 string field_0;
357 bytes field_1;357 bytes field_1;
358}358}
452}452}
453453
454/// @title Unique extensions for ERC721.454/// @title Unique extensions for ERC721.
455/// @dev the ERC-165 identifier for this interface is 0x0e9fc611455/// @dev the ERC-165 identifier for this interface is 0x244543ee
456interface ERC721UniqueExtensions is Dummy, ERC165 {456interface ERC721UniqueExtensions is Dummy, ERC165 {
457 /// @notice A descriptive name for a collection of NFTs in this contract457 /// @notice A descriptive name for a collection of NFTs in this contract
458 /// @dev EVM selector for this function is: 0x06fdde03,458 /// @dev EVM selector for this function is: 0x06fdde03,
464 /// or in textual repr: symbol()464 /// or in textual repr: symbol()
465 function symbol() external view returns (string memory);465 function symbol() external view returns (string memory);
466
467 /// @notice A description for the collection.
468 /// @dev EVM selector for this function is: 0x7284e416,
469 /// or in textual repr: description()
470 function description() external view returns (string memory);
471
472 /// Returns the owner (in cross format) of the token.
473 ///
474 /// @param tokenId Id for the token.
475 /// @dev EVM selector for this function is: 0x2b29dace,
476 /// or in textual repr: crossOwnerOf(uint256)
477 function crossOwnerOf(uint256 tokenId) external view returns (EthCrossAccount memory);
478
479 /// Returns the token properties.
480 ///
481 /// @param tokenId Id for the token.
482 /// @param keys Properties keys. Empty keys for all propertyes.
483 /// @return Vector of properties key/value pairs.
484 /// @dev EVM selector for this function is: 0xefc26c69,
485 /// or in textual repr: tokenProperties(uint256,string[])
486 function tokenProperties(uint256 tokenId, string[] memory keys) external view returns (Tuple7[] memory);
466487
467 /// @notice Set or reaffirm the approved address for an NFT488 /// @notice Set or reaffirm the approved address for an NFT
468 /// @dev The zero address indicates there is no approved address.489 /// @dev The zero address indicates there is no approved address.
546 // /// @param tokens array of pairs of token ID and token URI for minted tokens567 // /// @param tokens array of pairs of token ID and token URI for minted tokens
547 // /// @dev EVM selector for this function is: 0x36543006,568 // /// @dev EVM selector for this function is: 0x36543006,
548 // /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])569 // /// or in textual repr: mintBulkWithTokenURI(address,(uint256,string)[])
549 // function mintBulkWithTokenURI(address to, Tuple11[] memory tokens) external returns (bool);570 // function mintBulkWithTokenURI(address to, Tuple10[] memory tokens) external returns (bool);
550571
551}572}
552573
553/// @dev anonymous struct574/// @dev anonymous struct
554struct Tuple11 {575struct Tuple10 {
555 uint256 field_0;576 uint256 field_0;
556 string field_1;577 string field_1;
557}578}
579
580/// @dev anonymous struct
581struct Tuple7 {
582 string field_0;
583 bytes field_1;
584}
558585
559/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension586/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
560/// @dev See https://eips.ethereum.org/EIPS/eip-721587/// @dev See https://eips.ethereum.org/EIPS/eip-721
modifiedtests/src/eth/api/UniqueRefungible.soldiffbeforeafterboth
462 /// or in textual repr: symbol()462 /// or in textual repr: symbol()
463 function symbol() external view returns (string memory);463 function symbol() external view returns (string memory);
464
465 /// @notice A description for the collection.
466 /// @dev EVM selector for this function is: 0x7284e416,
467 /// or in textual repr: description()
468 function description() external view returns (string memory);
469
470 /// Returns the owner (in cross format) of the token.
471 ///
472 /// @param tokenId Id for the token.
473 /// @dev EVM selector for this function is: 0x2b29dace,
474 /// or in textual repr: crossOwnerOf(uint256)
475 function crossOwnerOf(uint256 tokenId) external view returns (EthCrossAccount memory);
476
477 /// Returns the token properties.
478 ///
479 /// @param tokenId Id for the token.
480 /// @param keys Properties keys. Empty keys for all propertyes.
481 /// @return Vector of properties key/value pairs.
482 /// @dev EVM selector for this function is: 0xefc26c69,
483 /// or in textual repr: tokenProperties(uint256,string[])
484 function tokenProperties(uint256 tokenId, string[] memory keys) external view returns (Tuple7[] memory);
464485
465 /// @notice Transfer ownership of an RFT486 /// @notice Transfer ownership of an RFT
466 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`487 /// @dev Throws unless `msg.sender` is the current owner. Throws if `to`
555 string field_1;576 string field_1;
556}577}
578
579/// @dev anonymous struct
580struct Tuple7 {
581 string field_0;
582 bytes field_1;
583}
557584
558/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension585/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
559/// @dev See https://eips.ethereum.org/EIPS/eip-721586/// @dev See https://eips.ethereum.org/EIPS/eip-721
modifiedtests/src/eth/base.test.tsdiffbeforeafterboth
117 });117 });
118118
119 itEth('ERC721UniqueExtensions support', async ({helper}) => {119 itEth('ERC721UniqueExtensions support', async ({helper}) => {
120 await checkInterface(helper, '0x0e9fc611', true, true);120 await checkInterface(helper, '0x922a115f', true, true);
121 });121 });
122122
123 itEth('ERC721Burnable - 0x42966c68 - support', async ({helper}) => {123 itEth('ERC721Burnable - 0x42966c68 - support', async ({helper}) => {
modifiedtests/src/eth/createFTCollection.test.tsdiffbeforeafterboth
36 const owner = await helper.eth.createAccountWithBalance(donor);36 const owner = await helper.eth.createAccountWithBalance(donor);
37 const sponsor = await helper.eth.createAccountWithBalance(donor);37 const sponsor = await helper.eth.createAccountWithBalance(donor);
38 const ss58Format = helper.chain.getChainProperties().ss58Format;38 const ss58Format = helper.chain.getChainProperties().ss58Format;
39 const description = 'absolutely anything';
40
39 const {collectionId, collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Sponsor', DECIMALS, 'absolutely anything', 'ENVY');41 const {collectionId, collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Sponsor', DECIMALS, description, 'ENVY');
4042
41 const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner, true);43 const collection = helper.ethNativeContract.collection(collectionAddress, 'ft', owner, true);
42 await collection.methods.setCollectionSponsor(sponsor).send();44 await collection.methods.setCollectionSponsor(sponsor).send();
4345
44 let data = (await helper.rft.getData(collectionId))!;46 let data = (await helper.rft.getData(collectionId))!;
57 const owner = await helper.eth.createAccountWithBalance(donor);59 const owner = await helper.eth.createAccountWithBalance(donor);
58 const sponsor = await helper.eth.createAccountWithBalance(donor);60 const sponsor = await helper.eth.createAccountWithBalance(donor);
59 const ss58Format = helper.chain.getChainProperties().ss58Format;61 const ss58Format = helper.chain.getChainProperties().ss58Format;
62 const description = 'absolutely anything';
60 const {collectionId, collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Sponsor', DECIMALS, 'absolutely anything', 'ENVY');63 const {collectionId, collectionAddress} = await helper.eth.createFungibleCollection(owner, 'Sponsor', DECIMALS, description, 'ENVY');
6164
62 const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);65 const collection = helper.ethNativeContract.collection(collectionAddress, 'rft', owner);
63 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);66 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);
7376
74 data = (await helper.rft.getData(collectionId))!;77 data = (await helper.rft.getData(collectionId))!;
75 expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));78 expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));
79 expect(await collection.methods.description().call()).to.deep.equal(description);
76 });80 });
7781
78 itEth('Set limits', async ({helper}) => {82 itEth('Set limits', async ({helper}) => {
modifiedtests/src/eth/createNFTCollection.test.tsdiffbeforeafterboth
28 });28 });
29 });29 });
3030
31 itEth('Create collection with properties', async ({helper}) => {31 itEth('Create collection with properties & get desctription', async ({helper}) => {
32 const owner = await helper.eth.createAccountWithBalance(donor);32 const owner = await helper.eth.createAccountWithBalance(donor);
3333
34 const name = 'CollectionEVM';34 const name = 'CollectionEVM';
37 const baseUri = 'BaseURI';37 const baseUri = 'BaseURI';
3838
39 const {collectionId, collectionAddress, events} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, name, description, prefix, baseUri);39 const {collectionId, collectionAddress, events} = await helper.eth.createERC721MetadataCompatibleNFTCollection(owner, name, description, prefix, baseUri);
4040 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft');
41
41 expect(events).to.be.deep.equal([42 expect(events).to.be.deep.equal([
42 {43 {
57 expect(data.raw.tokenPrefix).to.be.eq(prefix);58 expect(data.raw.tokenPrefix).to.be.eq(prefix);
58 expect(data.raw.mode).to.be.eq('NFT');59 expect(data.raw.mode).to.be.eq('NFT');
5960
61 expect(await contract.methods.description().call()).to.deep.equal(description);
62
60 const options = await collection.getOptions();63 const options = await collection.getOptions();
61 expect(options.tokenPropertyPermissions).to.be.deep.equal([64 expect(options.tokenPropertyPermissions).to.be.deep.equal([
92 expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));95 expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));
93 });96 });
9497
95 itEth('[cross] Set sponsorship', async ({helper}) => {98 itEth('[cross] Set sponsorship & get description', async ({helper}) => {
96 const owner = await helper.eth.createAccountWithBalance(donor);99 const owner = await helper.eth.createAccountWithBalance(donor);
97 const sponsor = await helper.eth.createAccountWithBalance(donor);100 const sponsor = await helper.eth.createAccountWithBalance(donor);
98 const ss58Format = helper.chain.getChainProperties().ss58Format;101 const ss58Format = helper.chain.getChainProperties().ss58Format;
102 const description = 'absolutely anything';
99 const {collectionId, collectionAddress} = await helper.eth.createNFTCollection(owner, 'Sponsor', 'absolutely anything', 'ROC');103 const {collectionId, collectionAddress} = await helper.eth.createNFTCollection(owner, 'Sponsor', description, 'ROC');
100104
101 const collection = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);105 const collection = helper.ethNativeContract.collection(collectionAddress, 'nft', owner);
102 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);106 const sponsorCross = helper.ethCrossAccount.fromAddress(sponsor);
113 data = (await helper.nft.getData(collectionId))!;117 data = (await helper.nft.getData(collectionId))!;
114 expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));118 expect(data.raw.sponsorship.Confirmed).to.be.equal(evmToAddress(sponsor, Number(ss58Format)));
119
120 expect(await sponsorCollection.methods.description().call()).to.deep.equal(description);
115 });121 });
116122
117 itEth('Set limits', async ({helper}) => {123 itEth('Set limits', async ({helper}) => {
modifiedtests/src/eth/createRFTCollection.test.tsdiffbeforeafterboth
5353
54 54
5555
56 itEth('Create collection with properties', async ({helper}) => {56 itEth('Create collection with properties & get description', async ({helper}) => {
57 const owner = await helper.eth.createAccountWithBalance(donor);57 const owner = await helper.eth.createAccountWithBalance(donor);
5858
59 const name = 'CollectionEVM';59 const name = 'CollectionEVM';
60 const description = 'Some description';60 const description = 'Some description';
61 const prefix = 'token prefix';61 const prefix = 'token prefix';
62 const baseUri = 'BaseURI';62 const baseUri = 'BaseURI';
6363
64 const {collectionId} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner, name, description, prefix, baseUri);64 const {collectionId, collectionAddress} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner, name, description, prefix, baseUri);
65 const contract = helper.ethNativeContract.collection(collectionAddress, 'nft');
6566
66 const collection = helper.rft.getCollectionObject(collectionId);67 const collection = helper.rft.getCollectionObject(collectionId);
67 const data = (await collection.getData())!;68 const data = (await collection.getData())!;
71 expect(data.raw.tokenPrefix).to.be.eq(prefix);72 expect(data.raw.tokenPrefix).to.be.eq(prefix);
72 expect(data.raw.mode).to.be.eq('ReFungible');73 expect(data.raw.mode).to.be.eq('ReFungible');
74
75 expect(await contract.methods.description().call()).to.deep.equal(description);
7376
74 const options = await collection.getOptions();77 const options = await collection.getOptions();
75 expect(options.tokenPropertyPermissions).to.be.deep.equal([78 expect(options.tokenPropertyPermissions).to.be.deep.equal([
modifiedtests/src/eth/nonFungible.test.tsdiffbeforeafterboth
17import {itEth, usingEthPlaygrounds, expect, EthUniqueHelper} from './util';17import {itEth, usingEthPlaygrounds, expect, EthUniqueHelper} from './util';
18import {IKeyringPair} from '@polkadot/types/types';18import {IKeyringPair} from '@polkadot/types/types';
19import {Contract} from 'web3-eth-contract';19import {Contract} from 'web3-eth-contract';
20import exp from 'constants';
2021
2122
22describe('NFT: Information getting', () => {23describe('NFT: Information getting', () => {
149 });150 });
150 });151 });
151152
152 itEth('Can perform mint()', async ({helper}) => {153 itEth('Can perform mint() & get crossOwner()', async ({helper}) => {
153 const owner = await helper.eth.createAccountWithBalance(donor);154 const owner = await helper.eth.createAccountWithBalance(donor);
154 const receiver = helper.eth.createAccount();155 const receiver = helper.eth.createAccount();
155156
166 expect(event.returnValues.to).to.be.equal(receiver);167 expect(event.returnValues.to).to.be.equal(receiver);
167168
168 expect(await contract.methods.tokenURI(tokenId).call()).to.be.equal('Test URI');169 expect(await contract.methods.tokenURI(tokenId).call()).to.be.equal('Test URI');
169170 console.log(await contract.methods.crossOwnerOf(tokenId).call());
171 expect(await contract.methods.crossOwnerOf(tokenId).call()).to.be.like([receiver, '0']);
170 // TODO: this wont work right now, need release 919000 first172 // TODO: this wont work right now, need release 919000 first
171 // await helper.methods.setOffchainSchema(collectionIdAddress, 'https://offchain-service.local/token-info/{id}').send();173 // await helper.methods.setOffchainSchema(collectionIdAddress, 'https://offchain-service.local/token-info/{id}').send();
172 // const tokenUri = await contract.methods.tokenURI(nextTokenId).call();174 // const tokenUri = await contract.methods.tokenURI(nextTokenId).call();
modifiedtests/src/eth/reFungible.test.tsdiffbeforeafterboth
117 });117 });
118 });118 });
119119
120 itEth('Can perform mint()', async ({helper}) => {120 itEth('Can perform mint() & crossOwnerOf()', async ({helper}) => {
121 const owner = await helper.eth.createAccountWithBalance(donor);121 const owner = await helper.eth.createAccountWithBalance(donor);
122 const receiver = helper.eth.createAccount();122 const receiver = helper.eth.createAccount();
123 const {collectionAddress} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner, 'Minty', '6', '6', '');123 const {collectionAddress} = await helper.eth.createERC721MetadataCompatibleRFTCollection(owner, 'Minty', '6', '6', '');
132 const tokenId = event.returnValues.tokenId;132 const tokenId = event.returnValues.tokenId;
133 expect(tokenId).to.be.equal('1');133 expect(tokenId).to.be.equal('1');
134134
135 expect(await contract.methods.crossOwnerOf(tokenId).call()).to.be.like([receiver, '0']);
135 expect(await contract.methods.tokenURI(tokenId).call()).to.be.equal('Test URI');136 expect(await contract.methods.tokenURI(tokenId).call()).to.be.equal('Test URI');
136 });137 });
137138
modifiedtests/src/eth/tokenProperties.test.tsdiffbeforeafterboth
14// You should have received a copy of the GNU General Public License14// You should have received a copy of the GNU General Public License
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 {itEth, usingEthPlaygrounds, expect} from './util';17import {itEth, usingEthPlaygrounds, expect, EthUniqueHelper} from './util';
18import {IKeyringPair} from '@polkadot/types/types';18import {IKeyringPair} from '@polkadot/types/types';
19import {ITokenPropertyPermission} from '../util/playgrounds/types';19import {ITokenPropertyPermission, TCollectionMode} from '../util/playgrounds/types';
20import {Pallets} from '../util';20import {Pallets} from '../util';
21import {UniqueNFTCollection, UniqueRFTCollection} from '../util/playgrounds/unique';
2122
22describe('EVM token properties', () => {23describe('EVM token properties', () => {
23 let donor: IKeyringPair;24 let donor: IKeyringPair;
95 expect(value).to.equal('testValue');96 expect(value).to.equal('testValue');
96 });97 });
97 98
98 itEth('Can be multiple set for NFT ', async({helper}) => {99 async function checkProps(helper: EthUniqueHelper, mode: TCollectionMode) {
99 const caller = await helper.eth.createAccountWithBalance(donor);100 const caller = await helper.eth.createAccountWithBalance(donor);
100 101
101 const properties = Array(5).fill(0).map((_, i) => { return {key: `key_${i}`, value: Buffer.from(`value_${i}`)}; });102 const properties = Array(5).fill(0).map((_, i) => { return {key: `key_${i}`, value: Buffer.from(`value_${i}`)}; });
102 const permissions: ITokenPropertyPermission[] = properties.map(p => { return {key: p.key, permission: {tokenOwner: true,103 const permissions: ITokenPropertyPermission[] = properties.map(p => { return {key: p.key, permission: {tokenOwner: true,
103 collectionAdmin: true,104 collectionAdmin: true,
104 mutable: true}}; });105 mutable: true}}; });
105 106
106 const collection = await helper.nft.mintCollection(alice, {107 const collection = await helper[mode].mintCollection(alice, {
107 tokenPrefix: 'ethp',108 tokenPrefix: 'ethp',
108 tokenPropertyPermissions: permissions,109 tokenPropertyPermissions: permissions,
109 });110 }) as UniqueNFTCollection | UniqueRFTCollection;
110 111
111 const token = await collection.mintToken(alice);112 const token = await collection.mintToken(alice);
112 113
116 await collection.addAdmin(alice, {Ethereum: caller});118 await collection.addAdmin(alice, {Ethereum: caller});
117119
118 const address = helper.ethAddress.fromCollectionId(collection.collectionId);120 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
119 const contract = helper.ethNativeContract.collection(address, 'nft', caller);121 const contract = helper.ethNativeContract.collection(address, mode, caller);
122
123 expect(await contract.methods.tokenProperties(token.tokenId, []).call()).to.be.deep.equal([]);
120124
121 await contract.methods.setProperties(token.tokenId, properties).send({from: caller});125 await contract.methods.setProperties(token.tokenId, properties).send({from: caller});
122126
123 const values = await token.getProperties(properties.map(p => p.key));127 const values = await token.getProperties(properties.map(p => p.key));
124 expect(values).to.be.deep.equal(properties.map(p => { return {key: p.key, value: p.value.toString()}; }));128 expect(values).to.be.deep.equal(properties.map(p => { return {key: p.key, value: p.value.toString()}; }));
129
130 expect(await contract.methods.tokenProperties(token.tokenId, []).call()).to.be.like(properties
131 .map(p => { return helper.ethProperty.property(p.key, p.value.toString()); }));
132
133 expect(await contract.methods.tokenProperties(token.tokenId, [properties[0].key]).call())
134 .to.be.like([helper.ethProperty.property(properties[0].key, properties[0].value.toString())]);
125 });135 }
126 136
137 itEth('Can be multiple set/read for NFT ', async({helper}) => {
138 await checkProps(helper, 'nft');
139 });
140
127 itEth.ifWithPallets('Can be multiple set for RFT ', [Pallets.ReFungible], async({helper}) => {141 itEth.ifWithPallets('Can be multiple set/read for RFT ', [Pallets.ReFungible], async({helper}) => {
128 const caller = await helper.eth.createAccountWithBalance(donor);
129
130 const properties = Array(5).fill(0).map((_, i) => { return {key: `key_${i}`, value: Buffer.from(`value_${i}`)}; });
131 const permissions: ITokenPropertyPermission[] = properties.map(p => { return {key: p.key, permission: {tokenOwner: true,
132 collectionAdmin: true,
133 mutable: true}}; });
134
135 const collection = await helper.rft.mintCollection(alice, {142 await checkProps(helper, 'rft');
136 tokenPrefix: 'ethp',
137 tokenPropertyPermissions: permissions,
138 });
139
140 const token = await collection.mintToken(alice);
141
142 const valuesBefore = await token.getProperties(properties.map(p => p.key));
143 expect(valuesBefore).to.be.deep.equal([]);
144
145 await collection.addAdmin(alice, {Ethereum: caller});
146
147 const address = helper.ethAddress.fromCollectionId(collection.collectionId);
148 const contract = helper.ethNativeContract.collection(address, 'rft', caller);
149
150 await contract.methods.setProperties(token.tokenId, properties).send({from: caller});
151
152 const values = await token.getProperties(properties.map(p => p.key));
153 expect(values).to.be.deep.equal(properties.map(p => { return {key: p.key, value: p.value.toString()}; }));
154 });143 });
155144
156 itEth('Can be deleted', async({helper}) => {145 itEth('Can be deleted', async({helper}) => {