Hello,
for the tutorial in part 7: I believe I deployed everything perfectly, but when I click on âMint NFTâ after paying the metamask, the log shows that I create 2 objects + the âattributesâ section is empty.
Which part of the code do I need to fix/ which function makes the âattributesâ in the logs?
main.js:
ââ"
Moralis.initialize(â3IcvId63X3g2jWHA2t2OCOFDHmfOw3PbF9etB6Mtâ);
Moralis.serverURL = âhttps://k8lq9f7lkimp.moralis.io:2053/serverâ
const TOKEN_CONTRACT_ADDRESS = â0x9fA230c6465ad8ceDa74A97946bDc4Ab2DD29F6eâ
init = async () => {
hideElement(userInfo);
hideElement(CreateItemForm);
window.web3 = await Moralis.Web3.enable();
window.tokenContract = new web3.eth.Contract(tokenContractAbi, TOKEN_CONTRACT_ADDRESS);
initUser();
}
initUser = async () => {
if (await Moralis.User.current()){
hideElement(userConnectButton);
showElement(userProfileButton);
showElement(openCreateItemButton);
}else{
showElement(userConnectButton);
hideElement(userProfileButton);
hideElement(openCreateItemButton);
}
}
login = async () => {
try {
await Moralis.Web3.authenticate();
initUser();
} catch (error) {
alert(error)
}
}
logout = async () => {
await Moralis.User.logOut();
hideElement(userInfo);
initUser();
}
OpenUserInfo = async() =>{
user = await Moralis.User.current();
if (user){
const email = user.get(âemailâ);
if (email){
userEmailField.value = email;
}else{
userEmailField.value = ââ;
}
userUsernameField.value = user.get(âusernameâ);
const userAvatar = user.get('avatar');
if (userAvatar){
userAvatarImage.src = userAvatar.url();
showElement(userAvatarImage);
}else{
hideElement(userAvatarImage);
}
showElement(userInfo);
}else{
login();
}
}
saveUserInfo = async() => {
user.set(âemailâ, userEmailField.value);
user.set(âusernameâ, userUsernameField.value)
if (userAvatarFile.files.length > 0) {
const file = userAvatarFile.files[0];
const name = âavatar.jpgâ;
const avatar = new Moralis.File(name, file);
user.set('avatar',avatar);
}
await user.save();
alert('User info saved successfully!');
OpenUserInfo();
}
createItem = async () => {
if (CreateItemFile.files.length == 0){
alert(âPlease select a fileâ)
return;
} else if (CreateItemNameField.value.length == 0){
alert(âPlease give the item a nameâ)
return;
}
const nftFile = new Moralis.File('NFTfile.jpg', CreateItemFile.files[0]);
await nftFile.saveIPFS();
const nftFilePath = nftFile.ipfs();
const nftFileHash = nftFile.hash();
const metadata = {
name: CreateItemNameField.value,
description: CreateItemDescriptionField.value,
image: nftFilePath,
};
const nftFileMetadataFile = new Moralis.File("metadata.json", {base64 : btoa(JSON.stringify(metadata))});
await nftFileMetadataFile.saveIPFS();
const nftFileMetadataFilePath = nftFileMetadataFile.ipfs();
const nftFileMetadataFileHash = nftFileMetadataFile.hash();
const nftId = await mintNft(nftFileMetadataFilePath);
// Simple syntax to create a new subclass of Moralis.Object.
const Item = Moralis.Object.extend("Item");
// Create a new instance of that class.
const item = new Item();
item.set('name', CreateItemNameField.value);
item.set('description', CreateItemDescriptionField.value);
item.set('nftFilePath', nftFilePath);
item.set('nftFileHash', nftFileHash);
item.set('nftFileMetadataFilePath', nftFileMetadataFilePath);
item.set('nftFileMetadataFileHash', nftFileMetadataFileHash);
item.set('nftId', nftId);
item.set('nftContractAddress', TOKEN_CONTRACT_ADDRESS);
await item.save();
console.log(item);
}
mintNft = async (metadataUrl) => {
const receipt = await tokenContract.methods.createItem(metadataUrl).send({from: ethereum.selectedAddress});
console.log(receipt);
return receipt.events.Transfer.returnValues.tokenId;
}
hideElement = (element) => element.style.display = ânoneâ;
showElement = (element) => element.style.display = âblockâ;
//NavBar
const userConnectButton = document.getElementById(âbtnConnectâ);
userConnectButton.onclick = login;
const userProfileButton = document.getElementById(âbtnUserInfoâ);
userProfileButton.onclick = OpenUserInfo;
const openCreateItemButton = document.getElementById(âbtnOpenCreateItemâ);
openCreateItemButton.onclick = () => showElement(CreateItemForm);
// User Profile
const userInfo = document.getElementById(âuserInfoâ);
const userUsernameField = document.getElementById(âtxtUsernameâ);
const userEmailField = document.getElementById(âtxtEmailâ);
const userAvatarImage = document.getElementById(âimgAvatarâ);
const userAvatarFile = document.getElementById(âfileAvatarâ);
document.getElementById(âbtnCloseUserInfoâ).onclick = () => hideElement(userInfo);
document.getElementById(âbtnLogoutâ).onclick = logout;
document.getElementById(âbtnSaveUserInfoâ).onclick = saveUserInfo;
// Item Creation
const CreateItemForm = document.getElementById(âcreateItemâ);
const CreateItemNameField = document.getElementById(âtxtCreateItemNameâ);
const CreateItemDescriptionField = document.getElementById(âtxtCreateItemDescriptionâ);
const CreateItemPriceField = document.getElementById(ânumCreateItemPriceâ);
const CreateItemStatusField = document.getElementById(âselectCreateItemStatusâ);
const CreateItemFile = document.getElementById(âfileCreateItemFileâ);
document.getElementById(âbtnCloseCreateItemâ).onclick = () => hideElement(CreateItemForm);
document.getElementById(âbtnCreateItemâ).onclick = createItem;
init(); ââ"
index.html:
ââ"
<div id="userInfo">
<h4>User Profile</h4>
<input type="text" id="txtUsername" required placeholder="Enter Username">
<input type="text" id="txtEmail" placeholder="Enter Email">
<small>Optional</small>
<img width="50" height="50" src="" alt="" id="imgAvatar">
<label for="fileAvatar">Select your avatar</label>
<input type="file" id="fileAvatar">
<button id="btnLogout">Log Out</button>
<button id="btnCloseUserInfo">Close</button>
<button id="btnSaveUserInfo">Save</button>
</div>
<div id="createItem">
<h4>Create Item</h4>
<input type="text" id="txtCreateItemName" required placeholder="Enter name">
<textarea id="txtCreateItemDescription" cols="30" rows="5" placeholder="Enter Item Description"></textarea>
<input type="number" min="1" step="1" id="numCreateItemPrice" placeholder="Enter Price" required>
<label for="selectCreateItemStatus">Status</label>
<select id="selectCreateItemStatus">
<option value="0">Not for Sale</option>
<option value="1">Instant Buy</option>
<option value="2">Accept Offers</option>
</select>
<label for="fileCreateItemFile">Select File</label>
<input type="file" id="fileCreateItemFile">
<button id="btnCloseCreateItem">Close</button>
<button id="btnCreateItem">Create NFT!</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script>
<script src="https://unpkg.com/moralis/dist/moralis.js"></script>
<script src="abi.js"></script>
<script src="main.js"></script>
"""
Morarable.sol:
ââ"
pragma solidity ^0.8.0;
import ââŚ/node_modules/@openzeppelin/contracts/token/ERC721/ERC721.solâ;
import ââŚ/node_modules/@openzeppelin/contracts/utils/Counters.solâ;
contract Arktoken is ERC721 {
using Counters for Counters.Counter;
Counters.Counter private _tokenIds;
constructor () ERC721("Arktoken","ARK"){}
struct Item {
uint256 id;
address creator;
string uri;
}
mapping(uint256 => Item) public Items;
function createItem(string memory uri) public returns (uint256){
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_safeMint(msg.sender, newItemId);
Items[newItemId] = Item(newItemId, msg.sender, uri);
return newItemId;
}
function tokenURI(uint256 tokenId) public view override returns (string memory) {
require(_exists(tokenId), âERC721Metadata: URI query for nonexistent tokenâ);
return Items[tokenId].uri;
}
}
ââ"