NFT's wont list on marketplace or add into the database

Hey Everyone
I’ve finished part 11 of the Rarible clone NFT marketplace tutorial.
I have no errors in the terminal or console but my NFT’s wont list for sale or appear in the database.
In part 11 of the video the Metamask wallet opens up 3 times when minting and listing the NFT’s.
I only have it open twice.

  1. When minting my NFT’s
  2. When its giving permission to access the Morarible Token.
    Has anyone come across this issue?
    Thanks in advance :slight_smile:

HTML

<!DOCTYPE html>

<html lang="en">

<head>

    <link rel="shortcut icon" href="">

    <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>

    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">

    <link rel="stylesheet" href="main.css">

 

</head>

<body class="bg-dark">

    <nav class="navbar navbar-expand-lg navbar-dark bg-transparent border-bottom border-light">

       

          <a class="navbar-brand btn btn-outline-moralis" href="#">Morarable</a>

          <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">

            <span class="navbar-toggler-icon"></span>

          </button>

          <div class="collapse navbar-collapse" id="navbarNav">

            <form class="mx-2 d-inline flex-md-fill">

              <input type="search" class="bg-transparent border-light form-control text-light mr-sm-2 rounded-pill" placeholder="search by item or creator">

            </form>

            <ul class="navbar-nav mr-auto">

              <li class="nav-item">

                <a class="nav-link" id="btnMyItems" href="#">My Items</a>

              </li>

            </ul>

            <div class="d-flex">

              <button class="btn btn-primary rounded-pill my-2 my-sm-0 mr-md-2" id="btnOpenCreateItem">Create</button>

              <button class="btn btn-outline-moralis rounded-pill my-2 my-sm-0" id="btnConnect">Connect Wallet</button>

              <button class="btn btn-outline-moralis rounded-pill my-2 my-sm-0" id="btnUserInfo">Profile</button>

   

            </div>

           </div>

      </nav>

  <div class="container"></div>

      <div class="row row-cols-1 row-cols-md-4 mt-5" id="itemsForSale">

 </div>

<div class="col mb-4" id="marketplaceItemTemplate">

  <div class="card h-100 border-light  bg-transparent text-light">

    <nav class="card-header navbar navbar-dark text-light p-1">

        <img src="" alt="">

        <span></span>

     </nav>  

     <img src="..." class="card-img-top" alt="...">

     <div class="card-body d-flex align-items-end">

          <div class="w-100">

            <h5 class="card-title"></h5>

            <p class="card-text"></p>

            <button class="btn btn-primary">

          </div>

        <h5 class="card-title"></h5>

       <p class="card-text"></p>

       <button class="btn btn-primary"></button>

     </div>

  </div>

</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>

    <div id="itemTemplate">

      <img src="" alt="">

      <h5></h5>

      <p></p>

    </div>

       

    <script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script>

    <script src="https://unpkg.com/moralis@latest/dist/moralis.js"></script>

    <script src="main.js"></script>

    <script src="abi.js"></script>

    <script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script>

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script>

</body>

</html>

Javascript

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

const appId = "z75nQcm3wcoe9xd9MK8c6Lye9akXiMw1QldhfvE6";

const TOKEN_CONTRACT_ADDRESS = "0x99495223da7dFE1A14d5224Bc90bad4a01F0e58A";

const MARKETPLACE_CONTRACT_ADDRESS = "0xb94bb1b53ab68465cEB10b89E3B67Eae2Db003BA";

Moralis.start({ serverUrl, appId });

init = async () => {

    hideElement(userItemsSection);

    hideElement(userInfo);

    hideElement(createItemForm);

    await Moralis.enableWeb3();

    web3 = new Web3(Moralis.provider);

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

    marketplaceContract = new web3.eth.Contract(marketplaceContractAbi, MARKETPLACE_CONTRACT_ADDRESS);

        initUser();

        loadUserItems();

           

}

initUser = async () => {

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

        hideElement(userConnectButton);

        showElement(userProfileButton);

        showElement(openCreateItemButton);

        showElement(openUserItemsButton);

        loadItems();

    }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();

}

onItemAdded = async (item) => {

    const params = {uid: `${item.attributes.uid}`};

    const addedItem = await Moralis.Cloud.run('getItem', params);

    if (addedItem){

        user = await Moralis.User.current();

        if (user){

            if (user.get('accounts').includes(addedItem.ownerOf)){

                const userItemListing = document.getElementById(`user-item-${item.tokenObjectId}`);

                if (userItemListing) userItemListing.parentNode.removeChild(userItemListing);

                getAndRenderItemData(addedItem, renderUserItem);

                return;

            }

        }

        getAndRenderItemData(addedItem, renderItem);

    }

}

loadUserItems = async () => {

    const params =  { token_address: TOKEN_CONTRACT_ADDRESS };

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

    ownedItems.forEach(item => {

        const userItemListing = document.getElementById(`user-item-${item.tokenObjectId}`);

        if (userItemListing) return;

        getAndRenderItemData(item, renderUserItem);

    });

}

loadItems = async () => {

    const params =  { token_address: TOKEN_CONTRACT_ADDRESS };

    const items = await Moralis.Cloud.run("getItems", params);

    user = await Moralis.User.current();

    items.forEach(item => {

        if(user){

            if(user.attributes.accounts.includes(item.ownerOf)) {

                const userItemListing = document.getElementById(`user-item-${item.tokenObjectId}`);

                if (userItemListing) userItemListing.parentNode.removeChild(userItemListing);

                getAndRenderItemData(item, renderUserItem);

                return;

            }

        }

        getAndRenderItemData(item, renderItem);

    });

}

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);

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('nftContractAddress', TOKEN_CONTRACT_ADDRESS);

await item.save();

console.log(item);

user = await Moralis.User.current();

const userAddress = user.get('ethaddress');

switch(createItemStatusField.value){

    case "0":

        return;

        case "1":

            await ensureMarketplaceIsApproved(nftId, TOKEN_CONTRACT_ADDRESS);

            await marketplaceContract.methods.addItemToMarket(nftId, TOKEN_CONTRACT_ADDRESS, createItemPriceField.value);

            break;

            case "2":

                alert("Not yet supported!");

                return;

}

buyItem = async (item) => {

    user = await Moralis.User.current();

    const userAddress = user.get("ethAddress")

    if(!user)

    {

        login();

        return;

    }

    await marketplaceContract.methods.buyItem(item.uid).send({from: user.get('ethAddress'), value: item.askingPrice});

}

}

initTemplate = (id) => {

    const template = document.getElementById(id);

    template.id = "";

    template.parentNode.removeChild(template);

    return template;

}

renderUserItem = (item) => {

    const userItem = userItemTemplate.cloneNode(true);

    userItem.getElementsByTagName("img")[0].src = item.image;

    userItem.getElementsByTagName("img")[0].alt = item.name;

    userItem.getElementsByTagName("h5")[0].innerText = item.name;

    userItem.getElementsByTagName("p")[0].innerText = item.description;

    userItems.appendChild(userItem);

    userItems.id = `user-item-${item.tokenObjectId}`

    userItems.appendChild(userItem);

   

    console.log(userItem);

}

renderItem = (item) => {

    const itemForSale = marketplaceItemTemplate.cloneNode(true);

    if (item.sellerAvatar){

        //itemForSale.getElementsByTagName("img")[0].src = item.sellerAvatar.url();

        //itemForSale.getElementsByTagName("img")[0].alt = item.sellerUsername;

        itemForSale.getElementsByTagName("span")[0].innerText = item.sellerUsername;

    }

    itemForSale.getElementsByTagName("img")[0].src = item.image;

    itemForSale.getElementsByTagName("img")[0].alt = item.name;

    itemForSale.getElementsByTagName("h5")[0].innerText = item.name;

    itemForSale.getElementsByTagName("p")[0].innerText = item.description;

    itemForSale.getElementsByTagName("button")[0].innerText = `Buy for ${item.askingPrice}`;

    itemForSale.getElementsByTagName("button")[0].onclick = ()  => buyItem(item);;

    itemForSale.id = `item-${item.uid}`;

    itemForSale.appendChild(itemForSale);

}

getAndRenderItemData = (item, renderFunction) => {

    fetch(item.tokenUri)

    .then(response => response.json())

    .then(data => {

        item.name = data.name;

        item.description = data.description;

        item.image = data.image;

        renderFunction(item);

    })

}

mintNFT = async (metadataUri) => {

    const receipt = await tokenContract.methods.createItem(metadataUri).send({from: ethereum.selectedAddress});;

    console.log(receipt);

    return receipt.events.Transfer.returnValues.tokenId;

}

ensureMarketplaceIsApproved = async (tokenId, tokenAddress) => {

    user = await Moralis.User.current();

    const userAddress = user.get('ethAddress');

    const contract = new web3.eth.Contract(tokenContractAbi, tokenAddress);

    const approvedAddress = await contract.methods.getApproved(tokenId).call({from: userAddress});

    if (approvedAddress != MARKETPLACE_CONTRACT_ADDRESS){

        await contract.methods.approve(MARKETPLACE_CONTRACT_ADDRESS,tokenId).send({from: userAddress});

    }

}

ensureMarketplaceIsApproved = async (tokenId, tokenAddress) => {

    console.log(tokenId);

    user = await Moralis.User.current();

    const userAddress = user.get('ethAddress');

    const contract = new web3.eth.Contract(tokenContractAbi, tokenAddress);

    const approvedAddress = await contract.methods.getApproved(tokenId).call({from: userAddress});

    if (approvedAddress != MARKETPLACE_CONTRACT_ADDRESS){

        await contract.methods.approve(MARKETPLACE_CONTRACT_ADDRESS,tokenId).send({from: userAddress});

    }

}

hideElement = (element) => element.style.display = "none";

showElement = (element) => element.style.display = "block";

openUserItems = async () => {

    user = await Moralis.User.current();

    if (user){    

        showElement(userItemsSection);

    }else{

        login();

    }

}

//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;

const userItemTemplate = initTemplate("itemTemplate");

init();

Marketplace smart contract

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

contract MoraribleMarketContract {

    struct AuctionItem {

        uint256 id;

        address tokenAddress;

        uint256 tokenId;

        address payable seller;

        uint256 askingPrice;

        bool isSold;

    }

    AuctionItem[] public itemsForSale;

    mapping (address => mapping (uint256 => bool)) activeItems;

    event itemAdded(uint256 id, uint256 tokenId, address tokenAddress, uint256 askingPrice);

    event itemSold(uint256 id, address buyer, uint256 askingPrice);

    modifier OnlyItemOwner(address tokenAddress, uint256 tokenId){

        IERC721 tokenContract = IERC721(tokenAddress);

        require(tokenContract.ownerOf(tokenId) == msg.sender);

        _;

    }

     modifier HasTransferApproval(address tokenAddress, uint256 tokenId) {

        IERC721 tokenContract = IERC721(tokenAddress);

        require(tokenContract.getApproved(tokenId) == address(this));

        _;

    }

    modifier ItemExists(uint256 id){

        require(id < itemsForSale.length && itemsForSale[id].id == id, "Could not find item");

        _;

    }

     modifier isForSale(uint256 id){

        require(itemsForSale[id].isSold == false, "Item is already sold!");

        _;

    }

    function addItemsToMarket(uint256 tokenId, address tokenAddress, uint256 askingPrice) OnlyItemOwner(tokenAddress,tokenId) HasTransferApproval(tokenAddress,tokenId) external returns (uint256){

        require(activeItems[tokenAddress][tokenId] == false, "Item is already for sale!");

        uint256 newItemId = itemsForSale.length;

        itemsForSale.push(AuctionItem(newItemId, tokenAddress, tokenId, payable(msg.sender), askingPrice, false));

        activeItems[tokenAddress][tokenId] = true;

        assert(itemsForSale[newItemId].id == newItemId);

        emit itemAdded(newItemId, tokenId, tokenAddress, askingPrice);

        return newItemId;

    }  

    function buyItem(uint256 Id) payable external ItemExists(Id) isForSale(Id) HasTransferApproval(itemsForSale[Id].tokenAddress,itemsForSale[Id].tokenId){

        require(msg.value >= itemsForSale[Id].askingPrice, "Not enough funds sent");

        require(msg.sender != itemsForSale[Id].seller);

        itemsForSale[Id].isSold = true;

        activeItems[itemsForSale[Id].tokenAddress][itemsForSale[Id].tokenId] = false;

        IERC721(itemsForSale[Id].tokenAddress).safeTransferFrom(itemsForSale[Id].seller, msg.sender, itemsForSale[Id].tokenId);

        itemsForSale[Id].seller.transfer(msg.value);

        emit itemSold(Id, msg.sender,itemsForSale[Id].askingPrice);

    }

}

Morarible Token smart contract

// 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;

    }

}

Hi guys
Im still having this issue if anyone can help please.
Thanks in advance.

Hey
I’ve changed my JavaScript a little and now I’m getting this error but I have defined the from address.

Javascript

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

const appId = "z75nQcm3wcoe9xd9MK8c6Lye9akXiMw1QldhfvE6";

const TOKEN_CONTRACT_ADDRESS = "0x99495223da7dFE1A14d5224Bc90bad4a01F0e58A";

const MARKETPLACE_CONTRACT_ADDRESS = "0xb94bb1b53ab68465cEB10b89E3B67Eae2Db003BA";

Moralis.start({ serverUrl, appId });

init = async () => {

    hideElement(userItemsSection);

    hideElement(userInfo);

    hideElement(createItemForm);

    await Moralis.enableWeb3();

    web3 = new Web3(Moralis.provider);

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

    marketplaceContract = new web3.eth.Contract(marketplaceContractAbi, MARKETPLACE_CONTRACT_ADDRESS);

        initUser();

        loadUserItems();

           

}

initUser = async () => {

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

        hideElement(userConnectButton);

        showElement(userProfileButton);

        showElement(openCreateItemButton);

        showElement(openUserItemsButton);

        loadItems();

    }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();

}

onItemAdded = async (item) => {

    const params = {uid: `${item.attributes.uid}`};

    const addedItem = await Moralis.Cloud.run('getItem', params);

    if (addedItem){

        user = await Moralis.User.current();

        if (user){

            if (user.get('accounts').includes(addedItem.ownerOf)){

                const userItemListing = document.getElementById(`user-item-${item.tokenObjectId}`);

                if (userItemListing) userItemListing.parentNode.removeChild(userItemListing);

                getAndRenderItemData(addedItem, renderUserItem);

                return;

            }

        }

        getAndRenderItemData(addedItem, renderItem);

    }

}

loadUserItems = async () => {

    const params =  { token_address: TOKEN_CONTRACT_ADDRESS };

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

    ownedItems.forEach(item => {

        const userItemListing = document.getElementById(`user-item-${item.tokenObjectId}`);

        if (userItemListing) return;

        getAndRenderItemData(item, renderUserItem);

    });

}

loadItems = async () => {

    const params =  { token_address: TOKEN_CONTRACT_ADDRESS };

    const items = await Moralis.Cloud.run("getItems", params);

    user = await Moralis.User.current();

    items.forEach(item => {

        if(user){

            if(user.attributes.accounts.includes(item.ownerOf)) {

                const userItemListing = document.getElementById(`user-item-${item.tokenObjectId}`);

                if (userItemListing) userItemListing.parentNode.removeChild(userItemListing);

                getAndRenderItemData(item, renderUserItem);

                return;

            }

        }

        getAndRenderItemData(item, renderItem);

    });

}

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);

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('nftContractAddress', TOKEN_CONTRACT_ADDRESS);

await item.save();

console.log(item);

user = await Moralis.User.current();

const userAddress = user.get("ethaddress");

switch(createItemStatusField.value){

    case "0":

        return;

        case "1":

            await ensureMarketplaceIsApproved(nftId, TOKEN_CONTRACT_ADDRESS);

            await marketplaceContract.methods.addItemToMarket(nftId, TOKEN_CONTRACT_ADDRESS, createItemPriceField.value).send({from: userAddress});

            break;

            case "2":

                alert("Not yet supported!");

                return;

}

buyItem = async (item) => {

    user = await Moralis.User.current();

    const userAddress = user.get("ethAddress")

    if(!user)

    {

        login();

        return;

    }

    await marketplaceContract.methods.buyItem(item.uid).send({from: user.get("ethAddress"), value: item.askingPrice});

}

}

initTemplate = (id) => {

    const template = document.getElementById(id);

    template.id = "";

    template.parentNode.removeChild(template);

    return template;

}

renderUserItem = (item) => {

    const userItem = userItemTemplate.cloneNode(true);

    userItem.getElementsByTagName("img")[0].src = item.image;

    userItem.getElementsByTagName("img")[0].alt = item.name;

    userItem.getElementsByTagName("h5")[0].innerText = item.name;

    userItem.getElementsByTagName("p")[0].innerText = item.description;

    userItems.appendChild(userItem);

    userItems.id = `user-item-${item.tokenObjectId}`

    userItems.appendChild(userItem);

   

    console.log(userItem);

}

renderItem = (item) => {

    const itemForSale = marketplaceItemTemplate.cloneNode(true);

    if (item.sellerAvatar){

        //itemForSale.getElementsByTagName("img")[0].src = item.sellerAvatar.url();

        //itemForSale.getElementsByTagName("img")[0].alt = item.sellerUsername;

        itemForSale.getElementsByTagName("span")[0].innerText = item.sellerUsername;

    }

    itemForSale.getElementsByTagName("img")[0].src = item.image;

    itemForSale.getElementsByTagName("img")[0].alt = item.name;

    itemForSale.getElementsByTagName("h5")[0].innerText = item.name;

    itemForSale.getElementsByTagName("p")[0].innerText = item.description;

    itemForSale.getElementsByTagName("button")[0].innerText = `Buy for ${item.askingPrice}`;

    itemForSale.getElementsByTagName("button")[0].onclick = ()  => buyItem(item);;

    itemForSale.id = `item-${item.uid}`;

    itemForSale.appendChild(itemForSale);

}

getAndRenderItemData = (item, renderFunction) => {

    fetch(item.tokenUri)

    .then(response => response.json())

    .then(data => {

        item.name = data.name;

        item.description = data.description;

        item.image = data.image;

        renderFunction(item);

    })

}

loadItems2 = async () => {

    const params =  { token_address: TOKEN_CONTRACT_ADDRESS };

    const items = await Moralis.Cloud.run("getItems", params);

    console.log(items);

}

mintNFT = async (metadataUri) => {

    const receipt = await tokenContract.methods.createItem(metadataUri).send({from: ethereum.selectedAddress});;

    console.log(receipt);

    return receipt.events.Transfer.returnValues.tokenId;

}

ensureMarketplaceIsApproved = async (tokenId, tokenAddress) => {

    user = await Moralis.User.current();

    const userAddress = user.get("ethAddress");

    const contract = new web3.eth.Contract(tokenContractAbi, tokenAddress);

    const approvedAddress = await contract.methods.getApproved(tokenId).call({from: userAddress});

    if (approvedAddress != MARKETPLACE_CONTRACT_ADDRESS){

        await contract.methods.approve(MARKETPLACE_CONTRACT_ADDRESS,tokenId).send({from: userAddress});

    }

}

hideElement = (element) => element.style.display = "none";

showElement = (element) => element.style.display = "block";

openUserItems = async () => {

    user = await Moralis.User.current();

    if (user){    

        showElement(userItemsSection);

    }else{

        login();

    }

}

//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;

const userItemTemplate = initTemplate("itemTemplate");

init();

What is the error? Which function are you running?

Hi Glad
I’m having a error that says there isn’t a from address specified in the createItem function.
I thought the part where I’ve written const userAddress = user.get(‘ethaddress’); and then put useraddress into case 1 of the switch would do it. I’ve been trying a few different things but I end up creating more issues and errors when I do. Can you see where I have gone wrong?
Cheers

Screenshot 2022 No from address

This is my cloud functions aswell.

cloud functions

Moralis.Cloud.define("getUserItems", async (request) => {

  const options = { address: request.params.token_address, chain: "ropsten" };

  const NFTowners = await Moralis.Web3API.token.getNFTOwners(options);

  const queryResults = NFTowners.result.filter(x => x.owner_of == request.user.attributes.accounts);

const results = [];

 for (let i = 0; i < queryResults.length; ++i) {

  results.push({

    "tokenObjectId": queryResults[i].id,

    "tokenid": queryResults[i].token_id,

    "tokenAddress": queryResults[i].token_address,

    "symbol": queryResults[i].symbol,

    "tokenUri": queryResults[i].token_uri,

  });

}

return results;

});

  Moralis.Cloud.define("getItems", async (request) => {

     

    const query = new Moralis.Query("ItemsForSale");

    query.notEqualTo("isSold", true);

    query.select("uid","askingPrice","tokenAddress","tokenId", "token.token_uri", "token.symbol","token.owner_of","token.id", "user.avatar","user.username");

 

    const queryResults = await query.find({useMasterKey:true});

    const results = [];

 

    for (let i = 0; i < queryResults.length; ++i) {

 

      if (!queryResults[i].attributes.token || !queryResults[i].attributes.user) continue;

 

      results.push({

        "uid": queryResults[i].attributes.uid,

        "tokenId": queryResults[i].attributes.tokenId,

        "tokenAddress": queryResults[i].attributes.tokenAddress,

        "askingPrice": queryResults[i].attributes.askingPrice,

 

        "symbol": queryResults[i].attributes.token.attributes.symbol,

        "tokenUri": queryResults[i].attributes.token.attributes.token_uri,

        "ownerOf": queryResults[i].attributes.token.attributes.owner_of,

        "tokenObjectId": queryResults[i].attributes.token.id,

       

        "sellerUsername": queryResults[i].attributes.user.attributes.username,

        "sellerAvatar": queryResults[i].attributes.user.attributes.avatar,

      });

    }

 

    return results;

  });

 

  Moralis.Cloud.beforeSave("ItemsForSale", async (request) => {

 

    const options = { address: "0xF276579917F17F5a157251C02d46993c1c7E2e42", chain: "ropsten" };

    const NFTowners = await Moralis.Web3API.token.getNFTOwners(options);

    const queryResults = NFTowners.result.filter(x => x.token_address == request.object.get('tokenAddress') && x.token_id == request.object.get('tokenId'));

    query.equalTo("token_address", request.object.get('tokenAddress'));

    query.equalTo("token_id", request.object.get('tokenId'));

    const object = queryResults[0];

    if (object){

      const owner = object.owner_of;

        const userQuery = new Moralis.Query(Moralis.User);

        userQuery.equalTo("accounts", owner);

        const userObject = await userQuery.first({useMasterKey:true});

        if (userObject){

            request.object.set('user', userObject);

        }

        request.object.set('token', object);

    }

  });

Moralis.Cloud.beforeSave("SoldItems", async (request) => {

 

    const query = new Moralis.Query("ItemsForSale");

    query.equalTo("uid", request.object.get('uid'));

    const item = await query.first();

    if (item){

      request.object.set('item', item);

      item.set('isSold', true);

      await item.save();

         

      const userQuery = new Moralis.Query(Moralis.User);

        userQuery.equalTo("accounts", request.object.get('buyer'));

      const userObject = await userQuery.first({useMasterKey:true});

      if (userObject){

          request.object.set('user', userObject);

      }

    }

  });

Hey Glad
I’ve been able to get a “from” address specified but now I’m getting a error involving the EVM. I also get a error on the third pop up of Metamask for not being able to estimate gas. I’m thinking the EVM issue might have something to do with the gas issue. I’m not completey sure.
Cheers

Screenshot gas issue for NFT marketplace

This error may occur when you are calling the function on the wrong chain or when you are trying to call a function which is private or internal.

Hi John
Is there anything else it could be?
I’m calling the function to the right chain and I’ve checked to see if there are any private or internals that I have to change to public or external but I’m continuing to get the same issue about the EVM.

What does the function do?

You can test it in remix to check if it is working.

The function is listing NFT’s to the marketplace and ok ill see if its the smart contract or not.
Cheers

My imports don’t work on remix but they work out of remix. Do you know a way to make them work in remix? I’m doing some trial and error now.
Cheers

Replace with this

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/IERC721.sol";
1 Like

Ok Ill try that now.
Thank you

Hi John
everything works on remix fine and deploys. Ill keep doing some trouble shooting if you have no other suggestions.
I appreciate your help.
Cheers

I think it is a typo here. Function name should be addItemsToMarket

Is that the function which you are calling?

1 Like

Yes
That is the function I’m calling.
I’ve just changed it but I get the EVM error again now once that’s changed .

can you share the contract address, ABI, and function attributes? Maybe I can try from my side.

Ok Thank you John.
Marketplace contract address: 0xb94bb1b53ab68465cEB10b89E3B67Eae2Db003BA
Token Contract address: 0x99495223da7dFE1A14d5224Bc90bad4a01F0e58A
Function attributes:

1. description: "Description"
2. metadataFileHash: "QmWzvnPWAWKgUwU6RQF2ozGYfVC7LtT5KbqrWDvhF7xz6k"
3. metadataFilePath: "https://ipfs.moralis.io:2053/ipfs/QmWzvnPWAWKgUwU6RQF2ozGYfVC7LtT5KbqrWDvhF7xz6k"
4. name: "Name"
5. nftContractAddress: "0x99495223da7dFE1A14d5224Bc90bad4a01F0e58A"
6. nftFileHash: "QmSBhuJjpk89RSfVDYvQMhrRoMNUbQmgF6bUPFf8WvxK7a"
7. nftFilePath: "https://ipfs.moralis.io:2053/ipfs/QmSBhuJjpk89RSfVDYvQMhrRoMNUbQmgF6bUPFf8WvxK7a"

Abi

var tokenContractAbi = [

  {

    "inputs": [],

    "stateMutability": "nonpayable",

    "type": "constructor"

  },

  {

    "anonymous": false,

    "inputs": [

      {

        "indexed": true,

        "internalType": "address",

        "name": "owner",

        "type": "address"

      },

      {

        "indexed": true,

        "internalType": "address",

        "name": "approved",

        "type": "address"

      },

      {

        "indexed": true,

        "internalType": "uint256",

        "name": "tokenId",

        "type": "uint256"

      }

    ],

    "name": "Approval",

    "type": "event"

  },

  {

    "anonymous": false,

    "inputs": [

      {

        "indexed": true,

        "internalType": "address",

        "name": "owner",

        "type": "address"

      },

      {

        "indexed": true,

        "internalType": "address",

        "name": "operator",

        "type": "address"

      },

      {

        "indexed": false,

        "internalType": "bool",

        "name": "approved",

        "type": "bool"

      }

    ],

    "name": "ApprovalForAll",

    "type": "event"

  },

  {

    "anonymous": false,

    "inputs": [

      {

        "indexed": true,

        "internalType": "address",

        "name": "from",

        "type": "address"

      },

      {

        "indexed": true,

        "internalType": "address",

        "name": "to",

        "type": "address"

      },

      {

        "indexed": true,

        "internalType": "uint256",

        "name": "tokenId",

        "type": "uint256"

      }

    ],

    "name": "Transfer",

    "type": "event"

  },

  {

    "inputs": [

      {

        "internalType": "uint256",

        "name": "",

        "type": "uint256"

      }

    ],

    "name": "Items",

    "outputs": [

      {

        "internalType": "uint256",

        "name": "id",

        "type": "uint256"

      },

      {

        "internalType": "address",

        "name": "creator",

        "type": "address"

      },

      {

        "internalType": "string",

        "name": "uri",

        "type": "string"

      }

    ],

    "stateMutability": "view",

    "type": "function",

    "constant": true

  },

  {

    "inputs": [

      {

        "internalType": "address",

        "name": "to",

        "type": "address"

      },

      {

        "internalType": "uint256",

        "name": "tokenId",

        "type": "uint256"

      }

    ],

    "name": "approve",

    "outputs": [],

    "stateMutability": "nonpayable",

    "type": "function"

  },

  {

    "inputs": [

      {

        "internalType": "address",

        "name": "owner",

        "type": "address"

      }

    ],

    "name": "balanceOf",

    "outputs": [

      {

        "internalType": "uint256",

        "name": "",

        "type": "uint256"

      }

    ],

    "stateMutability": "view",

    "type": "function",

    "constant": true

  },

  {

    "inputs": [

      {

        "internalType": "uint256",

        "name": "tokenId",

        "type": "uint256"

      }

    ],

    "name": "getApproved",

    "outputs": [

      {

        "internalType": "address",

        "name": "",

        "type": "address"

      }

    ],

    "stateMutability": "view",

    "type": "function",

    "constant": true

  },

  {

    "inputs": [

      {

        "internalType": "address",

        "name": "owner",

        "type": "address"

      },

      {

        "internalType": "address",

        "name": "operator",

        "type": "address"

      }

    ],

    "name": "isApprovedForAll",

    "outputs": [

      {

        "internalType": "bool",

        "name": "",

        "type": "bool"

      }

    ],

    "stateMutability": "view",

    "type": "function",

    "constant": true

  },

  {

    "inputs": [],

    "name": "name",

    "outputs": [

      {

        "internalType": "string",

        "name": "",

        "type": "string"

      }

    ],

    "stateMutability": "view",

    "type": "function",

    "constant": true

  },

  {

    "inputs": [

      {

        "internalType": "uint256",

        "name": "tokenId",

        "type": "uint256"

      }

    ],

    "name": "ownerOf",

    "outputs": [

      {

        "internalType": "address",

        "name": "",

        "type": "address"

      }

    ],

    "stateMutability": "view",

    "type": "function",

    "constant": true

  },

  {

    "inputs": [

      {

        "internalType": "address",

        "name": "from",

        "type": "address"

      },

      {

        "internalType": "address",

        "name": "to",

        "type": "address"

      },

      {

        "internalType": "uint256",

        "name": "tokenId",

        "type": "uint256"

      }

    ],

    "name": "safeTransferFrom",

    "outputs": [],

    "stateMutability": "nonpayable",

    "type": "function"

  },

  {

    "inputs": [

      {

        "internalType": "address",

        "name": "from",

        "type": "address"

      },

      {

        "internalType": "address",

        "name": "to",

        "type": "address"

      },

      {

        "internalType": "uint256",

        "name": "tokenId",

        "type": "uint256"

      },

      {

        "internalType": "bytes",

        "name": "_data",

        "type": "bytes"

      }

    ],

    "name": "safeTransferFrom",

    "outputs": [],

    "stateMutability": "nonpayable",

    "type": "function"

  },

  {

    "inputs": [

      {

        "internalType": "address",

        "name": "operator",

        "type": "address"

      },

      {

        "internalType": "bool",

        "name": "approved",

        "type": "bool"

      }

    ],

    "name": "setApprovalForAll",

    "outputs": [],

    "stateMutability": "nonpayable",

    "type": "function"

  },

  {

    "inputs": [

      {

        "internalType": "bytes4",

        "name": "interfaceId",

        "type": "bytes4"

      }

    ],

    "name": "supportsInterface",

    "outputs": [

      {

        "internalType": "bool",

        "name": "",

        "type": "bool"

      }

    ],

    "stateMutability": "view",

    "type": "function",

    "constant": true

  },

  {

    "inputs": [],

    "name": "symbol",

    "outputs": [

      {

        "internalType": "string",

        "name": "",

        "type": "string"

      }

    ],

    "stateMutability": "view",

    "type": "function",

    "constant": true

  },

  {

    "inputs": [

      {

        "internalType": "address",

        "name": "from",

        "type": "address"

      },

      {

        "internalType": "address",

        "name": "to",

        "type": "address"

      },

      {

        "internalType": "uint256",

        "name": "tokenId",

        "type": "uint256"

      }

    ],

    "name": "transferFrom",

    "outputs": [],

    "stateMutability": "nonpayable",

    "type": "function"

  },

  {

    "inputs": [

      {

        "internalType": "string",

        "name": "uri",

        "type": "string"

      }

    ],

    "name": "createItem",

    "outputs": [

      {

        "internalType": "uint256",

        "name": "",

        "type": "uint256"

      }

    ],

    "stateMutability": "nonpayable",

    "type": "function"

  },

  {

    "inputs": [

      {

        "internalType": "uint256",

        "name": "tokenId",

        "type": "uint256"

      }

    ],

    "name": "tokenURI",

    "outputs": [

      {

        "internalType": "string",

        "name": "",

        "type": "string"

      }

    ],

    "stateMutability": "view",

    "type": "function",

    "constant": true

  }

];

var marketplaceContractAbi = [

  {

    "anonymous": false,

    "inputs": [

      {

        "indexed": false,

        "internalType": "uint256",

        "name": "id",

        "type": "uint256"

      },

      {

        "indexed": false,

        "internalType": "uint256",

        "name": "tokenId",

        "type": "uint256"

      },

      {

        "indexed": false,

        "internalType": "address",

        "name": "tokenAddress",

        "type": "address"

      },

      {

        "indexed": false,

        "internalType": "uint256",

        "name": "askingPrice",

        "type": "uint256"

      }

    ],

    "name": "itemAdded",

    "type": "event"

  },

  {

    "anonymous": false,

    "inputs": [

      {

        "indexed": false,

        "internalType": "uint256",

        "name": "id",

        "type": "uint256"

      },

      {

        "indexed": false,

        "internalType": "address",

        "name": "buyer",

        "type": "address"

      },

      {

        "indexed": false,

        "internalType": "uint256",

        "name": "askingPrice",

        "type": "uint256"

      }

    ],

    "name": "itemSold",

    "type": "event"

  },

  {

    "inputs": [

      {

        "internalType": "uint256",

        "name": "",

        "type": "uint256"

      }

    ],

    "name": "itemsForSale",

    "outputs": [

      {

        "internalType": "uint256",

        "name": "id",

        "type": "uint256"

      },

      {

        "internalType": "address",

        "name": "tokenAddress",

        "type": "address"

      },

      {

        "internalType": "uint256",

        "name": "tokenId",

        "type": "uint256"

      },

      {

        "internalType": "address payable",

        "name": "seller",

        "type": "address"

      },

      {

        "internalType": "uint256",

        "name": "askingPrice",

        "type": "uint256"

      },

      {

        "internalType": "bool",

        "name": "isSold",

        "type": "bool"

      }

    ],

    "stateMutability": "view",

    "type": "function",

    "constant": true

  },

  {

    "inputs": [

      {

        "internalType": "uint256",

        "name": "tokenId",

        "type": "uint256"

      },

      {

        "internalType": "address",

        "name": "tokenAddress",

        "type": "address"

      },

      {

        "internalType": "uint256",

        "name": "askingPrice",

        "type": "uint256"

      }

    ],

    "name": "addItemToMarket",

    "outputs": [

      {

        "internalType": "uint256",

        "name": "",

        "type": "uint256"

      }

    ],

    "stateMutability": "nonpayable",

    "type": "function"

  },

  {

    "inputs": [

      {

        "internalType": "uint256",

        "name": "id",

        "type": "uint256"

      }

    ],

    "name": "buyItem",

    "outputs": [],

    "stateMutability": "payable",

    "type": "function",

    "payable": true

  }

];