git.delta.rocks / unique-network / refs/commits / db24b2b07444

difftreelog

feat bulk mint/get/set metadata

Yaroslav Bolyukin2021-09-01parent: #742db63.patch.diff
in: master

5 files changed

modifiedpallets/nft/src/eth/erc.rsdiffbeforeafterboth
--- a/pallets/nft/src/eth/erc.rs
+++ b/pallets/nft/src/eth/erc.rs
@@ -8,6 +8,7 @@
 };
 use frame_support::storage::{StorageMap, StorageDoubleMap};
 use pallet_evm::AddressMapping;
+use pallet_evm_coder_substrate::dispatch_to_evm;
 use super::account::CrossAccountId;
 use sp_std::{vec, vec::Vec};
 
@@ -299,6 +300,90 @@
 			.ok_or("item id overflow")?
 			.into())
 	}
+
+	fn set_variable_metadata(
+		&mut self,
+		caller: caller,
+		token_id: uint256,
+		data: bytes,
+	) -> Result<void> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let token_id = token_id.try_into().map_err(|_| "token id overflow")?;
+
+		<Module<T>>::set_variable_meta_data_internal(&caller, self, token_id, data)
+			.map_err(dispatch_to_evm::<T>)?;
+		Ok(())
+	}
+
+	fn get_variable_metadata(&self, token_id: uint256) -> Result<bytes> {
+		let token_id = token_id.try_into().map_err(|_| "token id overflow")?;
+
+		<Module<T>>::get_variable_metadata(self, token_id).map_err(dispatch_to_evm::<T>)
+	}
+
+	fn mint_bulk(&mut self, caller: caller, to: address, token_ids: Vec<uint256>) -> Result<bool> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let to = T::CrossAccountId::from_eth(to);
+		let mut expected_index = <ItemListIndex>::get(self.id)
+			.checked_add(1)
+			.ok_or("item id overflow")?;
+
+		let total_tokens = token_ids.len();
+		for id in token_ids.into_iter() {
+			let id: u32 = id.try_into().map_err(|_| "token id overflow")?;
+			if id != expected_index {
+				return Err("item id should be next".into());
+			}
+			expected_index = expected_index.checked_add(1).ok_or("item id overflow")?;
+		}
+
+		let data = (0..total_tokens)
+			.map(|_| {
+				CreateItemData::NFT(CreateNftData {
+					const_data: vec![].try_into().unwrap(),
+					variable_data: vec![].try_into().unwrap(),
+				})
+			})
+			.collect();
+
+		<Module<T>>::create_multiple_items_internal(&caller, self, &to, data)
+			.map_err(dispatch_to_evm::<T>)?;
+		Ok(true)
+	}
+
+	#[solidity(rename_selector = "mintBulkWithTokenURI")]
+	fn mint_bulk_with_token_uri(
+		&mut self,
+		caller: caller,
+		to: address,
+		tokens: Vec<(uint256, string)>,
+	) -> Result<bool> {
+		let caller = T::CrossAccountId::from_eth(caller);
+		let to = T::CrossAccountId::from_eth(to);
+		let mut expected_index = <ItemListIndex>::get(self.id)
+			.checked_add(1)
+			.ok_or("item id overflow")?;
+
+		let mut data = Vec::with_capacity(tokens.len());
+		for (id, token_uri) in tokens {
+			let id: u32 = id.try_into().map_err(|_| "token id overflow")?;
+			if id != expected_index {
+				panic!("item id should be next ({}) but got {}", expected_index, id);
+			}
+			expected_index = expected_index.checked_add(1).ok_or("item id overflow")?;
+
+			data.push(CreateItemData::NFT(CreateNftData {
+				const_data: Vec::<u8>::from(token_uri)
+					.try_into()
+					.map_err(|_| "token uri is too long")?,
+				variable_data: vec![].try_into().unwrap(),
+			}));
+		}
+
+		<Module<T>>::create_multiple_items_internal(&caller, self, &to, data)
+			.map_err(dispatch_to_evm::<T>)?;
+		Ok(true)
+	}
 }
 
 #[solidity_interface(
modifiedpallets/nft/src/eth/stubs/UniqueNFT.rawdiffbeforeafterboth

binary blob — no preview

modifiedpallets/nft/src/eth/stubs/UniqueNFT.soldiffbeforeafterboth
before · pallets/nft/src/eth/stubs/UniqueNFT.sol
1// SPDX-License-Identifier: OTHER2// This code is automatically generated34pragma solidity >=0.8.0 <0.9.0;56// Common stubs holder7contract Dummy {8	uint8 dummy;9	string stub_error = "this contract is implemented in native";10}1112// Inline13contract ERC721Events {14	event Transfer(15		address indexed from,16		address indexed to,17		uint256 indexed tokenId18	);19	event Approval(20		address indexed owner,21		address indexed approved,22		uint256 indexed tokenId23	);24	event ApprovalForAll(25		address indexed owner,26		address indexed operator,27		bool approved28	);29}3031// Inline32contract ERC721MintableEvents {33	event MintingFinished();34}3536// Inline37contract InlineNameSymbol is Dummy {38	function name() public view returns (string memory) {39		require(false, stub_error);40		dummy;41		return "";42	}4344	function symbol() public view returns (string memory) {45		require(false, stub_error);46		dummy;47		return "";48	}49}5051// Inline52contract InlineTotalSupply is Dummy {53	function totalSupply() public view returns (uint256) {54		require(false, stub_error);55		dummy;56		return 0;57	}58}5960contract ERC165 is Dummy {61	function supportsInterface(uint32 interfaceId) public view returns (bool) {62		require(false, stub_error);63		interfaceId;64		dummy;65		return false;66	}67}6869contract ERC721 is Dummy, ERC165, ERC721Events {70	function balanceOf(address owner) public view returns (uint256) {71		require(false, stub_error);72		owner;73		dummy;74		return 0;75	}7677	function ownerOf(uint256 tokenId) public view returns (address) {78		require(false, stub_error);79		tokenId;80		dummy;81		return 0x0000000000000000000000000000000000000000;82	}8384	function safeTransferFromWithData(85		address from,86		address to,87		uint256 tokenId,88		bytes memory data89	) public {90		require(false, stub_error);91		from;92		to;93		tokenId;94		data;95		dummy = 0;96	}9798	function safeTransferFrom(99		address from,100		address to,101		uint256 tokenId102	) public {103		require(false, stub_error);104		from;105		to;106		tokenId;107		dummy = 0;108	}109110	function transferFrom(111		address from,112		address to,113		uint256 tokenId114	) public {115		require(false, stub_error);116		from;117		to;118		tokenId;119		dummy = 0;120	}121122	function approve(address approved, uint256 tokenId) public {123		require(false, stub_error);124		approved;125		tokenId;126		dummy = 0;127	}128129	function setApprovalForAll(address operator, bool approved) public {130		require(false, stub_error);131		operator;132		approved;133		dummy = 0;134	}135136	function getApproved(uint256 tokenId) public view returns (address) {137		require(false, stub_error);138		tokenId;139		dummy;140		return 0x0000000000000000000000000000000000000000;141	}142143	function isApprovedForAll(address owner, address operator)144		public145		view146		returns (address)147	{148		require(false, stub_error);149		owner;150		operator;151		dummy;152		return 0x0000000000000000000000000000000000000000;153	}154}155156contract ERC721Burnable is Dummy {157	function burn(uint256 tokenId) public {158		require(false, stub_error);159		tokenId;160		dummy = 0;161	}162}163164contract ERC721Enumerable is Dummy, InlineTotalSupply {165	function tokenByIndex(uint256 index) public view returns (uint256) {166		require(false, stub_error);167		index;168		dummy;169		return 0;170	}171172	function tokenOfOwnerByIndex(address owner, uint256 index)173		public174		view175		returns (uint256)176	{177		require(false, stub_error);178		owner;179		index;180		dummy;181		return 0;182	}183}184185contract ERC721Metadata is Dummy, InlineNameSymbol {186	function tokenURI(uint256 tokenId) public view returns (string memory) {187		require(false, stub_error);188		tokenId;189		dummy;190		return "";191	}192}193194contract ERC721Mintable is Dummy, ERC721MintableEvents {195	function mintingFinished() public view returns (bool) {196		require(false, stub_error);197		dummy;198		return false;199	}200201	function mint(address to, uint256 tokenId) public returns (bool) {202		require(false, stub_error);203		to;204		tokenId;205		dummy = 0;206		return false;207	}208209	function mintWithTokenURI(210		address to,211		uint256 tokenId,212		string memory tokenUri213	) public returns (bool) {214		require(false, stub_error);215		to;216		tokenId;217		tokenUri;218		dummy = 0;219		return false;220	}221222	function finishMinting() public returns (bool) {223		require(false, stub_error);224		dummy = 0;225		return false;226	}227}228229contract ERC721UniqueExtensions is Dummy {230	function transfer(address to, uint256 tokenId) public {231		require(false, stub_error);232		to;233		tokenId;234		dummy = 0;235	}236237	function nextTokenId() public view returns (uint256) {238		require(false, stub_error);239		dummy;240		return 0;241	}242}243244contract UniqueNFT is245	Dummy,246	ERC165,247	ERC721,248	ERC721Metadata,249	ERC721Enumerable,250	ERC721UniqueExtensions,251	ERC721Mintable,252	ERC721Burnable253{}
after · pallets/nft/src/eth/stubs/UniqueNFT.sol
1// SPDX-License-Identifier: OTHER2// This code is automatically generated34pragma solidity >=0.8.0 <0.9.0;56// Anonymous struct7struct Tuple0 {8	uint256 field_0;9	string field_1;10}1112// Common stubs holder13contract Dummy {14	uint8 dummy;15	string stub_error = "this contract is implemented in native";16}1718// Inline19contract ERC721Events {20	event Transfer(21		address indexed from,22		address indexed to,23		uint256 indexed tokenId24	);25	event Approval(26		address indexed owner,27		address indexed approved,28		uint256 indexed tokenId29	);30	event ApprovalForAll(31		address indexed owner,32		address indexed operator,33		bool approved34	);35}3637// Inline38contract ERC721MintableEvents {39	event MintingFinished();40}4142// Inline43contract InlineNameSymbol is Dummy {44	function name() public view returns (string memory) {45		require(false, stub_error);46		dummy;47		return "";48	}4950	function symbol() public view returns (string memory) {51		require(false, stub_error);52		dummy;53		return "";54	}55}5657// Inline58contract InlineTotalSupply is Dummy {59	function totalSupply() public view returns (uint256) {60		require(false, stub_error);61		dummy;62		return 0;63	}64}6566contract ERC165 is Dummy {67	function supportsInterface(uint32 interfaceId) public view returns (bool) {68		require(false, stub_error);69		interfaceId;70		dummy;71		return false;72	}73}7475contract ERC721 is Dummy, ERC165, ERC721Events {76	function balanceOf(address owner) public view returns (uint256) {77		require(false, stub_error);78		owner;79		dummy;80		return 0;81	}8283	function ownerOf(uint256 tokenId) public view returns (address) {84		require(false, stub_error);85		tokenId;86		dummy;87		return 0x0000000000000000000000000000000000000000;88	}8990	function safeTransferFromWithData(91		address from,92		address to,93		uint256 tokenId,94		bytes memory data95	) public {96		require(false, stub_error);97		from;98		to;99		tokenId;100		data;101		dummy = 0;102	}103104	function safeTransferFrom(105		address from,106		address to,107		uint256 tokenId108	) public {109		require(false, stub_error);110		from;111		to;112		tokenId;113		dummy = 0;114	}115116	function transferFrom(117		address from,118		address to,119		uint256 tokenId120	) public {121		require(false, stub_error);122		from;123		to;124		tokenId;125		dummy = 0;126	}127128	function approve(address approved, uint256 tokenId) public {129		require(false, stub_error);130		approved;131		tokenId;132		dummy = 0;133	}134135	function setApprovalForAll(address operator, bool approved) public {136		require(false, stub_error);137		operator;138		approved;139		dummy = 0;140	}141142	function getApproved(uint256 tokenId) public view returns (address) {143		require(false, stub_error);144		tokenId;145		dummy;146		return 0x0000000000000000000000000000000000000000;147	}148149	function isApprovedForAll(address owner, address operator)150		public151		view152		returns (address)153	{154		require(false, stub_error);155		owner;156		operator;157		dummy;158		return 0x0000000000000000000000000000000000000000;159	}160}161162contract ERC721Burnable is Dummy {163	function burn(uint256 tokenId) public {164		require(false, stub_error);165		tokenId;166		dummy = 0;167	}168}169170contract ERC721Enumerable is Dummy, InlineTotalSupply {171	function tokenByIndex(uint256 index) public view returns (uint256) {172		require(false, stub_error);173		index;174		dummy;175		return 0;176	}177178	function tokenOfOwnerByIndex(address owner, uint256 index)179		public180		view181		returns (uint256)182	{183		require(false, stub_error);184		owner;185		index;186		dummy;187		return 0;188	}189}190191contract ERC721Metadata is Dummy, InlineNameSymbol {192	function tokenURI(uint256 tokenId) public view returns (string memory) {193		require(false, stub_error);194		tokenId;195		dummy;196		return "";197	}198}199200contract ERC721Mintable is Dummy, ERC721MintableEvents {201	function mintingFinished() public view returns (bool) {202		require(false, stub_error);203		dummy;204		return false;205	}206207	function mint(address to, uint256 tokenId) public returns (bool) {208		require(false, stub_error);209		to;210		tokenId;211		dummy = 0;212		return false;213	}214215	function mintWithTokenURI(216		address to,217		uint256 tokenId,218		string memory tokenUri219	) public returns (bool) {220		require(false, stub_error);221		to;222		tokenId;223		tokenUri;224		dummy = 0;225		return false;226	}227228	function finishMinting() public returns (bool) {229		require(false, stub_error);230		dummy = 0;231		return false;232	}233}234235contract ERC721UniqueExtensions is Dummy {236	function transfer(address to, uint256 tokenId) public {237		require(false, stub_error);238		to;239		tokenId;240		dummy = 0;241	}242243	function nextTokenId() public view returns (uint256) {244		require(false, stub_error);245		dummy;246		return 0;247	}248249	// Selector: setVariableMetadata(uint256,bytes) d4eac26d250	function setVariableMetadata(uint256 tokenId, bytes memory data) public {251		require(false, stub_error);252		tokenId;253		data;254		dummy = 0;255	}256257	// Selector: getVariableMetadata(uint256) e6c5ce6f258	function getVariableMetadata(uint256 tokenId)259		public260		view261		returns (bytes memory)262	{263		require(false, stub_error);264		tokenId;265		dummy;266		return hex"";267	}268269	// Selector: mintBulk(address,uint256[]) 44a9945e270	function mintBulk(address to, uint256[] memory tokenIds)271		public272		returns (bool)273	{274		require(false, stub_error);275		to;276		tokenIds;277		dummy = 0;278		return false;279	}280281	// Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006282	function mintBulkWithTokenURI(address to, Tuple0[] memory tokens)283		public284		returns (bool)285	{286		require(false, stub_error);287		to;288		tokens;289		dummy = 0;290		return false;291	}292}293294contract UniqueNFT is295	Dummy,296	ERC165,297	ERC721,298	ERC721Metadata,299	ERC721Enumerable,300	ERC721UniqueExtensions,301	ERC721Mintable,302	ERC721Burnable303{}
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -1501,6 +1501,14 @@
 		Ok(())
 	}
 
+	pub fn get_variable_metadata(collection: &CollectionHandle<T>, item_id: TokenId) -> Result<Vec<u8>, DispatchError> {
+		Ok(match collection.mode {
+			CollectionMode::NFT => <NftItemList<T>>::get(collection.id, item_id).ok_or(Error::<T>::TokenNotFound)?.variable_data,
+			CollectionMode::ReFungible => <ReFungibleItemList<T>>::get(collection.id, item_id).ok_or(Error::<T>::TokenNotFound)?.variable_data,
+			_ => fail!(Error::<T>::UnexpectedCollectionType),
+		})
+	}
+
 	pub fn create_multiple_items_internal(
 		sender: &T::CrossAccountId,
 		collection: &CollectionHandle<T>,
modifiedtests/src/eth/api/UniqueNFT.soldiffbeforeafterboth
--- a/tests/src/eth/api/UniqueNFT.sol
+++ b/tests/src/eth/api/UniqueNFT.sol
@@ -3,6 +3,12 @@
 
 pragma solidity >=0.8.0 <0.9.0;
 
+// Anonymous struct
+struct Tuple0 {
+	uint256 field_0;
+	string field_1;
+}
+
 // Common stubs holder
 interface Dummy {
 
@@ -119,6 +125,25 @@
 	function transfer(address to, uint256 tokenId) external;
 
 	function nextTokenId() external view returns (uint256);
+
+	// Selector: setVariableMetadata(uint256,bytes) d4eac26d
+	function setVariableMetadata(uint256 tokenId, bytes memory data) external;
+
+	// Selector: getVariableMetadata(uint256) e6c5ce6f
+	function getVariableMetadata(uint256 tokenId)
+		external
+		view
+		returns (bytes memory);
+
+	// Selector: mintBulk(address,uint256[]) 44a9945e
+	function mintBulk(address to, uint256[] memory tokenIds)
+		external
+		returns (bool);
+
+	// Selector: mintBulkWithTokenURI(address,(uint256,string)[]) 36543006
+	function mintBulkWithTokenURI(address to, Tuple0[] memory tokens)
+		external
+		returns (bool);
 }
 
 interface UniqueNFT is