I want to see all my NFT's that are minted and listed for sale

Hey guys
in the my Items section on morarible it only shows the most recent minted and listed NFT. I did have all my NFT’s showing but now I cant remember how to reverse this. Rookie error. I’ve been playing around with it but somehow haven’t been able to get all the NFT’s to show. can someone help please.
Cheers

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>Moraribles</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="#">Morarible</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="itemsForSale"></div>

    <div id="itemTemplate">

      <img src="" alt="">

      <h5></h5>

      <p></p>

      <input type="number" min="1" step="1">

      <button>Put For Sale</button>

    </div>

    <div id="marketplaceItemTemplate">

      <img src="" alt="">

      <h6></h6>

      <img src="" alt="">

      <h5></h5>

      <p></p>

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

    </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 = "0x5b71C0259d1cFa36DD71A2C308E5A6378db5977f";

Moralis.start({ serverUrl, appId });

init = async () => {

    hideElement(userItemsSection);

    hideElement(userInfo);

    hideElement(createItemForm);

    await Moralis.enableWeb3();

    web3 = new Web3(Moralis.provider);

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

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

        initUser();

        loadUserItems();

        loadItems();

        const soldItemsQuery = new Moralis.Query('SoldItems');

        const soldItemsSubscription = await soldItemsQuery.subscribe();

        soldItemsSubscription.on('create', onItemSold);

   

        const itemsAddedQuery = new Moralis.Query('ItemsForSale');

        const itemsAddedQuerySubscription = await itemsAddedQuery.subscribe();

        itemsAddedQuerySubscription.on('create', onItemAdded);

}

onItemSold = async (item) => {

    const listing = document.getElementById(`item-${item.attributes.uid}`);

    if (listing){

        listing.parentNode.removeChild(listing);

    }

   

    user = await Moralis.User.current();

    if (user){

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

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

        if (soldItem){

            if (user.get('accounts').includes(item.attributes.buyer)){

                getAndRenderItemData(soldItem, renderUserItem);

            }

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

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

         

        }

   

    }

}

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

    }

}

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

}

loadUserItems = async () => {

    const params =  { token_address: TOKEN_CONTRACT_ADDRESS };

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

    ownedItems.forEach(item => {

        getAndRenderItemData(item, renderUserItem);

    });

    console.log(ownedItems);

}

loadItems = async () => {

    const params =  { token_address: TOKEN_CONTRACT_ADDRESS };

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

    items.forEach(item => {

                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;

    }

    mintNFT = async (metadataUri) => {

        console.log("mintNFT :", ethereum.selectedAddress)

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

   

        console.log(receipt);

   

        return receipt.events.Transfer.returnValues.tokenId;

    }

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 = async (item) => {

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

    if (userItemListing) return;

    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;

    userItem.getElementsByTagName("input")[0].value = item.askingPrice ?? 1;

    userItem.getElementsByTagName("input")[0].disbaled = item.askingPrice > 0;

    userItem.getElementsByTagName("button")[0].disbaled = item.askingPrice > 0;

    userItem.getElementsByTagName("button")[0].onclick = async() => {

        user = await Moralis.User.current();

        if(!user){

            login();

            return;

        }

        await ensureMarketplaceIsApproved(item.tokenId, item.tokenAddress);

        await marketplaceContract.methods.addItemToMarket(item.tokenId, item.tokenAddress, userItem.getElementsByTagName("input")[0].value).send({from: user.get('ethAddress') });

    };

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

    userItems.appendChild(userItem);

    console.log(userItems);

}

renderItem = (item) => {

    const itemsForSale = marketplaceItemTemplate.cloneNode(true);

    if (item.sellerAvatar){

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

        itemForSale.getElementsByTagName("img")[0].alt = 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}`;

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

        console.log(item)

    })

   

}

ensureMarketplaceIsApproved = async (tokenId, tokenAddress) => {

    user = await Moralis.User.current();

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

   

    console.log("ensureMarketplaceIsApproved",  userAddress);

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

const marketplaceItemTemplate = initTemplate("marketplaceItemTemplate");

//Items for sale

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

init();

What is the function that adds the NFTs to the UI? Does this function use all the NFT data show NFT’s in the UI.

Hi John
it would be in the mint NFT function which is in the createItem function but I haven’t coded anything about hiding or showing the NFTs. Do i need to write a line that shows the NFT elements?
Cheers

creatItem function looks like a function to mint new NFT.

You want to show all your NFTs here right?
image

Yes im trying to show all my NFT’s

Hey John
I’ve have also been trying to get the buy now feature and the price I put when I minted and listed the instant buy NFT. I’ve done everything the video has done and I’ve done some trial and error but I haven’t been able to get this under the NFT’s yet.
Cheers :slight_smile:

I am still lost at which function is adding the NFT’s in the UI.

Where does the new listed NFT details are saved? Maybe you need to refresh the the data in UI once the newly listed data is saved.

Hi John
all the NFT details are being saved in the moralis database. :slight_smile:

did you try to refresh this data after the new data is saved in database?
image

Hey John
Yes I refresh the page after the new data is in the Moralis database but it will only show the most recent NFT that was minted and listed. I’m not sure why it does this?
Cheers

Hey John
I haven’t changed anything in my code but randomly my minting and listing of NFT’s has stopped working. This exact code was working for this so I’m confused why it has stopped working all of a sudden.

Screenshot Create item error out of no where

Javascript

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

const appId = "z75nQcm3wcoe9xd9MK8c6Lye9akXiMw1QldhfvE6";

const TOKEN_CONTRACT_ADDRESS = "0x99495223da7dFE1A14d5224Bc90bad4a01F0e58A";

const MARKETPLACE_CONTRACT_ADDRESS = "0x5b71C0259d1cFa36DD71A2C308E5A6378db5977f";

Moralis.start({ serverUrl, appId });

init = async () => {

    hideElement(userItemsSection);

    hideElement(userInfo);

    hideElement(createItemForm);

    await Moralis.enableWeb3();

    web3 = new Web3(Moralis.provider);

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

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

        initUser();

        loadUserItems();

        loadItems();

        loadUserItems2();

        loadItems2();

        const soldItemsQuery = new Moralis.Query('SoldItems');

        const soldItemsSubscription = await soldItemsQuery.subscribe();

        soldItemsSubscription.on('create', onItemSold);

   

        const itemsAddedQuery = new Moralis.Query('ItemsForSale');

        const itemsAddedQuerySubscription = await itemsAddedQuery.subscribe();

        itemsAddedQuerySubscription.on('create', onItemAdded);

}

onItemSold = async (item) => {

    const listing = document.getElementById(`item-${item.attributes.uid}`);

    if (listing){

        listing.parentNode.removeChild(listing);

    }

   

    user = await Moralis.User.current();

    if (user){

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

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

        if (soldItem){

            if (user.get('accounts').includes(item.attributes.buyer)){

                getAndRenderItemData(soldItem, renderUserItem);

            }

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

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

         

        }

   

    }

}

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

    }

}

loadUserItems2 = async () => {

    //  user = await Moralis.User.current();

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

    //  const options = { address: TOKEN_CONTRACT_ADDRESS , chain: "ropsten" };

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

    //  console.log(nftOwners);

    //  const tokens = nftOwners.result.filter(x => x.token_id == "2");

    //  console.log(tokens);

    const params =  { token_address: TOKEN_CONTRACT_ADDRESS };

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

    console.log(userItems);

    // const query = await new Moralis.Query("Item");

    // query.equalTo("nftContractAddress", TOKEN_CONTRACT_ADDRESS)

    // const queryResults = await query.find();

    // console.log(typeof queryResults);

    // console.log(queryResults);

}

loadItems2 = async () => {

    const params =  { token_address: TOKEN_CONTRACT_ADDRESS };

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

    console.log(items);

}

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

}

loadUserItems = async () => {

    const params =  { token_address: TOKEN_CONTRACT_ADDRESS };

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

    ownedItems.forEach(item => {

        getAndRenderItemData(item, renderUserItem);

    });

    console.log(ownedItems);

}

loadItems = async () => {

    const params =  { token_address: TOKEN_CONTRACT_ADDRESS };

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

    items.forEach(item => {

                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;

    }

    mintNFT = async (metadataUri) => {

        console.log("mintNFT :", ethereum.selectedAddress)

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

   

        console.log(receipt);

   

        return receipt.events.Transfer.returnValues.tokenId;

    }

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 = async (item) => {

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

    if (userItemListing) return;

    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;

    userItem.getElementsByTagName("input")[0].value = item.askingPrice ?? 1;

    userItem.getElementsByTagName("input")[0].disbaled = item.askingPrice > 0;

    userItem.getElementsByTagName("button")[0].disbaled = item.askingPrice > 0;

    userItem.getElementsByTagName("button")[0].onclick = async() => {

        user = await Moralis.User.current();

        if(!user){

            login();

            return;

        }

        await ensureMarketplaceIsApproved(item.tokenId, item.tokenAddress);

        await marketplaceContract.methods.addItemToMarket(item.tokenId, item.tokenAddress, userItem.getElementsByTagName("input")[0].value).send({from: user.get('ethAddress') });

    };

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

    userItems.appendChild(userItem);

    console.log(userItems);

}

renderItem = (item) => {

    const itemsForSale = marketplaceItemTemplate.cloneNode(true);

    if (item.sellerAvatar){

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

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

    }

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

    itemForSale.getElementsByTagName("img")[1].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}`;

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

        console.log(item)

    })

   

}

ensureMarketplaceIsApproved = async (tokenId, tokenAddress) => {

    user = await Moralis.User.current();

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

   

    console.log("ensureMarketplaceIsApproved",  userAddress);

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

const marketplaceItemTemplate = initTemplate("marketplaceItemTemplate");

//Items for sale

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

init();

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>Moraribles</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="#">Morarible</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="itemsForSale"></div>

    <div id="itemTemplate">

      <img src="" alt="">

      <h5></h5>

      <p></p>

      <input type="number" min="1" step="1">

      <button>Put For Sale</button>

    </div>

    <div id="marketplaceItemTemplate">

      <img src="" alt="">

      <h6></h6>

      <img src="" alt="">

      <h5></h5>

      <p></p>

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

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

Hi John
it randomly fixed itself after a few refreshes. Sorry for that last Post.
Cheers :slight_smile:

Hey guys
I’ve tried console.logging the token Id in the ensureMarketplaceIsApproved function and it comes back as undefined. I think that’s why my put for sale button doesn’t work after I mint and list NFT’s. It doesn’t know what token Id to approve for sale. Would this be something in the Cloud function error or have I written something in my Javascript wrong?
Cheers

Screenshot of tokenid undefined and approvemarketplace error

Cloud function

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.beforeSave("ItemsForSale", async (request) => {
    const query = new Moralis.Query("EthNFTTransfers");
      query.equalTo("token_address", request.object.get('tokenAddress'));
      query.equalTo("token_id", request.object.get('tokenId'));
    const object = await query.first();
    if (object){
        const owner = object.attributes.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);
      }
    }
  });    
  Moralis.Cloud.define("getItems", async (request) => {

    const query = new Moralis.Query("ItemsForSale");
    query.notEqualTo("isSold", true);
      if (request.user){
     query.notContainedIn("token.owner_of", request.user.attributes.accounts);
   }
    query.select("uid", "tokenAddress", "tokenId", "askingPrice", "token_uri", "owner_of", "user.username", "user.avatar");  
    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.username,
        "sellerAvatar": queryResults[i].attributes.user.avatar,
      });
    }

    return results;
  });
  Moralis.Cloud.define("getItem", async (request) => {
    const query = new Moralis.Query("ItemsForSale");
    query.equalTo("uid", request.params.uid);
    query.select("uid","askingPrice","tokenAddress","tokenId", "token_uri", "symbol","owner_of","token.id","user.avatar","user.username");
    const queryResult = await query.first({useMasterKey:true});
    if (!queryResult) return;
    return {
        "uid": queryResult.attributes.uid,
        "tokenId": queryResult.attributes.tokenId,
        "tokenAddress": queryResult.attributes.tokenAddress,
        "askingPrice": queryResult.attributes.askingPrice,
        "symbol": queryResult.attributes.token.attributes.symbol,
        "tokenUri": queryResult.attributes.token.attributes.token_uri,
        "ownerOf": queryResult.attributes.token.attributes.owner_of,
        "tokenObjectId": queryResult.attributes.token.id,
        "sellerUsername": queryResult.attributes.user.attributes.username,
        "sellerAvatar": queryResult.attributes.user.attributes.avatar,
      };
  });

Javascript

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

const appId = "z75nQcm3wcoe9xd9MK8c6Lye9akXiMw1QldhfvE6";

const TOKEN_CONTRACT_ADDRESS = "0x99495223da7dFE1A14d5224Bc90bad4a01F0e58A";

const MARKETPLACE_CONTRACT_ADDRESS = "0x5b71C0259d1cFa36DD71A2C308E5A6378db5977f";

Moralis.start({ serverUrl, appId });

init = async () => {

    hideElement(userItemsSection);

    hideElement(userInfo);

    hideElement(createItemForm);

    await Moralis.enableWeb3();

    web3 = new Web3(Moralis.provider);

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

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

        initUser();

        loadUserItems();

        loadItems();

        loadUserItems2();

        loadItems2();

        const soldItemsQuery = new Moralis.Query('SoldItems');

        const soldItemsSubscription = await soldItemsQuery.subscribe();

        soldItemsSubscription.on('create', onItemSold);

   

        const itemsAddedQuery = new Moralis.Query('ItemsForSale');

        const itemsAddedQuerySubscription = await itemsAddedQuery.subscribe();

        itemsAddedQuerySubscription.on('create', onItemAdded);

}

onItemSold = async (item) => {

    const listing = document.getElementById(`item-${item.attributes.uid}`);

    if (listing){

        listing.parentNode.removeChild(listing);

    }

   

    user = await Moralis.User.current();

    if (user){

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

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

        if (soldItem){

            if (user.get('accounts').includes(item.attributes.buyer)){

                getAndRenderItemData(soldItem, renderUserItem);

            }

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

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

         

        }

   

    }

}

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

    }

}

loadUserItems2 = async () => {

    //  user = await Moralis.User.current();

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

    //  const options = { address: TOKEN_CONTRACT_ADDRESS , chain: "ropsten" };

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

    //  console.log(nftOwners);

    //  const tokens = nftOwners.result.filter(x => x.token_id == "2");

    //  console.log(tokens);

    const params =  { token_address: TOKEN_CONTRACT_ADDRESS };

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

    console.log(userItems);

    // const query = await new Moralis.Query("Item");

    // query.equalTo("nftContractAddress", TOKEN_CONTRACT_ADDRESS)

    // const queryResults = await query.find();

    // console.log(typeof queryResults);

    // console.log(queryResults);

}

loadItems2 = async () => {

    const params =  { token_address: TOKEN_CONTRACT_ADDRESS };

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

    console.log(items);

}

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

}

loadUserItems = async () => {

    const params =  { token_address: TOKEN_CONTRACT_ADDRESS };

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

    ownedItems.forEach(item => {

        getAndRenderItemData(item, renderUserItem);

    });

    console.log(ownedItems);

}

loadItems = async () => {

    const params =  { token_address: TOKEN_CONTRACT_ADDRESS };

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

    items.forEach(item => {

                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;

    }

    mintNFT = async (metadataUri) => {

        console.log("mintNFT :", ethereum.selectedAddress)

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

   

        console.log(receipt);

   

        return receipt.events.Transfer.returnValues.tokenId;

    }

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 = async (item) => {

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

    if (userItemListing) return;

    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;

    userItem.getElementsByTagName("input")[0].value = item.askingPrice ?? 1;

    userItem.getElementsByTagName("input")[0].disbaled = item.askingPrice > 0;

    userItem.getElementsByTagName("button")[0].disbaled = item.askingPrice > 0;

    userItem.getElementsByTagName("button")[0].onclick = async() => {

        user = await Moralis.User.current();

        if(!user){

            login();

            return;

        }

        await ensureMarketplaceIsApproved(item.tokenId, item.tokenAddress);

        await marketplaceContract.methods.addItemToMarket(item.tokenId, item.tokenAddress, userItem.getElementsByTagName("input")[0].value).send({from: user.get('ethAddress') });

    };

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

    userItems.appendChild(userItem);

    console.log(userItems);

}

renderItem = (item) => {

    const itemsForSale = marketplaceItemTemplate.cloneNode(true);

    if (item.sellerAvatar){

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

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

    }

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

    itemForSale.getElementsByTagName("img")[1].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}`;

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

        console.log(item)

    })

   

}

ensureMarketplaceIsApproved = async (tokenId, tokenAddress) => {

    user = await Moralis.User.current();

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

   

    console.log("ensureMarketplaceIsApproved",  userAddress);

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

const marketplaceItemTemplate = initTemplate("marketplaceItemTemplate");

//Items for sale

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

init()

Hey guys
Hope you had a great weekend.
I’m still struggling with getting my NFT’s to all show in the my items section of my Dapp. I’m trying to have my items show but with the buy now button and instant price I chose when creating and listing the NFT’s on my marketplace. I’ve been doing some trial and error with my put for sale button aswell but it wont put a NFT for sale because it cant approve what the token Id for that NFT. I think this is caused by a issue in my getItems cloud function which I’m trying to still correct.
Cheers :slight_smile:

Hey Guys
When I add token. infront of token.uri, token.owner and token.user.username in my getItems cloud function it repopulates the getItems array in networks but I get the error of unexpected token in json. This is because it cant pass the json correctly at my getAndRenderData function in Javascript.
Has anyone done this part of the Rarible NFT marketplace clone?
Thanks in advance. :slight_smile:

Screenshot 2022-07-13

Did you console.log each item at the start of the function as I mentioned? It seems you are still attempting to fetch undefined tokenUris.

Hi Glad
Yes I have console.logged item and all the metadata logs out fine. When I get rid of the token. in my getItems Cloud function this error goes away but when I do f12 on my dapp and go to the network section. The getItems array isnt populated anymore. I’m not sure how to have the getItems array populated without having token. in my Cloud function but then the token.uri thats fetched wont parse to json correctly. I’ve been going in circles with this issue.
Cheers

I have a lot of undefined in the networks section as well but these also disappear if I add token. Infront of the token.uri, token.owner and token.user.username. I might add them back in because then I have no issue with fetching the token.uri.

Hi Glad
I meant when I get rid of token. from Infront of token.uri, token.owner and token.user.username in the getItems cloud function. I’ve just gotten rid of them which gets rid of the json error but my getItems array isn’t populated again in networks section. It must not be fetching the data correctly from the getItems cloud function? I think this is why my put for sale button doesn’t work either. It doesn’t know what token.id to approve for sale because its not getting the item data? I think the few issues I have would all be resolved if my getItems cloud function was grabbing all the data correctly.
Cheers

I think the few issues I have would all be resolved if my getItems cloud function was grabbing all the data correctly.

“The getItems array isnt populated anymore.” You mentioned that this function was working fine before you made the changes? The issue is in your frontend when you try to read/use the data. You can share a repo on GitHub if you still have issues.

1 Like