Clone rarible part 8: Columns for cloud function do not appear

Hey guys
I’ve been following the Moralis tutorial and all is working great until part 8. My issue is I don’t have all the columns in the Moralis database. Is this a issue in the cloud function? I’m not really sure what my problem is. I’ve attached my HTML, Javascript, Solidity and my Cloud function.
Thanks in advance to anyone who can help. :slight_smile:

Screenshot  of Moralis database (Browser)

HTML:

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Morarables</title>

</head>

<body>

    <div>

        <button id="btnConnect">Connect Wallet</button>

        <button id="btnUserInfo">Profile</button>

        <button id="btnOpenCreateItem">Create</button>

        <button id="btnMyItems">My Items</button>

    </div>

    <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="" id="imgAvatar" alt="">

        <label for="fileAvatar">Select 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 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!</button>

    </div>

    <div id="userItems">

        <h4>My Items</h4>

        <div id="userItemsList"></div>

        <button id="btnCloseUserItems">Close</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>

</body>

</html>

Javascript:

const serverUrl = "https://hbrhmupyiqgd.usemoralis.com:2053/server";

const appId = "jSR4OAe7qfcWQYDcYVH0nWdvwOxnhUO1tyxrKGWZ";

const TOKEN_CONTRACT_ADDRESS = "0x9a5B99bAb34FE642Bf4946F7fBA349519E0a7b31";

Moralis.start({ serverUrl, appId });

init = async () => {

    hideElement(userItemsSection);

    hideElement(userInfo);

    hideElement(createItemForm);

    await Moralis.enableWeb3();

    web3 = new Web3(web3.currentProvider);

    window.tokenContract = new web3.eth.Contract(tokenContractAbi, TOKEN_CONTRACT_ADDRESS)

     initUser();

     loadUserItems();

}

initUser = async () => {

    if (await Moralis.User.current()){

        hideElement(userConnectButton);

        showElement(userProfileButton);

        showElement(openCreateItemButton);

        showElement(openUserItemsButton);

    }else{

        showElement(userConnectButton);

        hideElement(userProfileButton);

        hideElement(openCreateItemButton);

        hideElement(createItemForm);

        hideElement(openUserItemsButton);

    }

}

login = async () => {

    try {

        await Moralis.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 = "";

        }

        userNameField.value = user.get('username');

        const userAvatar = user.get('avatar');

        if(userAvatar){

            userAvatarImg.src = userAvatar.url();

            showElement(userAvatarImg);

        }else{

            hideElement(userAvatarImg);

        }

        showElement(userInfo);

    }else{

        login();

    }

}

saveUserInfo = async () => {

    user.set('email', userEmailField.value);

    user.set('username', userNameField.value);

    if (userAvatarFile.files.length > 0) {

        const avatar = new Moralis.File("avatar1.jpg", userAvatarFile.files[0]);

        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.webp", 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);

const Item = Moralis.Object.extend("Item");

const item = new Item();

item.set('name', createItemNameField.value);

item.set('description', createItemDescriptionField.value);

item.set('nftFilePath', nftFilePath);

item.set('nftFileHash', nftFileHash);

item.set('metadataFilePath', nftFileMetadataFilepath);

item.set('metadataFileHash', nftFileMetadataFileHash);

item.set('nftId', nftId)

item.set('nftContractAddres', 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;

}

openUserItems = async () => {

    user = await Moralis.User.current();

    if (user){    

        showElement(userItemsSection);

    }else{

        login();

    }

}

loadUserItems = async () => {

    const ownedItems = await Moralis.Cloud.run("getUserItems");

    console.log(ownedItems);

}

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;

//Userinfo

const userInfo = document.getElementById("userInfo");

const userNameField = document.getElementById("txtUsername");

const userEmailField = document.getElementById("txtEmail");

const userAvatarImg = 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");

const openCreateItemButton = document.getElementById("btnOpenCreateItem");

openCreateItemButton.onclick = () => showElement(createItemForm);

document.getElementById("btnCloseCreateItem").onclick = () => hideElement(createItemForm);

document.getElementById("btnCreateItem").onclick = createItem;

//User items

const userItemsSection = document.getElementById("userItems");

const userItems = document.getElementById("userItemsList");

document.getElementById("btnCloseUserItems").onclick = () => hideElement(userItemsSection)

const openUserItemsButton = document.getElementById("btnMyItems");

openUserItemsButton.onclick = openUserItems;

init();

Cloud Function:

Moralis.Cloud.define("getUserItems", async (request) => {
  
  const query = new Moralis.Query("EthNFTTokenOwners");
  query.equalTo("contract_type", "ERC721");
  query.containedIn("owner_of", request.user.attributes.accounts);
  const queryresults = await query.find();
  
  let sum = 0;
  for(let i = 0; i < results.length; ++i) {
    results.push({
        "tokenObjectId": queryResults[i].id,
        "tokenId": queryResults[i].attributes.token_id,
        "tokenAddress": queryResults[i].attributes.token_address,
        "symbol": queryResults[i].attributes.symbol,
        "tokenUri": queryResults[i].attributes.token_uri,
      });
    }
    return results;
  });

Solidity:

//SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "../node_modules/@openzeppelin/contracts/token/ERC721/ERC721.sol";

import "../node_modules/@openzeppelin/contracts/utils/Counters.sol";

contract MorarableToken is ERC721 {

    using Counters for Counters.Counter;

    Counters.Counter private _tokenIds;

    constructor () ERC721("MorarableToken", "MORA" ){}

    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;

    }

}

Which ones are missing? Some won’t be there due to changes in Moralis servers as the tutorial is outdated. You can read this.

Hi Glad
Do I need Session, EthTokenBalance, EthTokenTransfers and EthTransactions?
Cheers

Screenshot of tutorial database (browser)

Session is provided by default. I am not too sure about the rest as I’m not familiar with the tutorial. The videos should cover which classes/tables are required at each part when they’re being used.

1 Like

Ok thank you
ill go through the videos again and see if anything is said.

Hi
I’m now having these errors and i’ve tried to fix it but have had no luck. Does anyone know how to fix this issue?
Cheers
Screenshot of errors for part 8 Morarable

Hi
I’ve fixed both issues but now I cant get a response from my cloud function. Can anyone help?
Cheers