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