hereās my error
Hereās my cloud function
Moralis.Cloud.define("getUserItems", async (request) => {
const query = new Moralis.Query("EthNFTOwners");
query.equalTo("contract_type", "ERC721");
query.containedIn("owner_of", request.user.attributes.accounts);
const queryResults = await query.find();
const results = [];
for (let i = 0; i < queryResults.length; ++i) {
results.push({
"tokenObjectId": queryResults[i].id,
"tokenid": queryResults[i].attributes.token_id,
"tokenAddress": queryResults[i].attributes.token_address,
"symbol": queryResults[i].attributes.symbol,
"tokenUri": queryResults[i].attributes.token_uri,
});
}
return results;
});
Moralis.Cloud.beforeSave("itemsForSale", async (request) => {
const query = new Moralis.Query("EthNFTOwners");
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);
query.select("uid", "tokenAddress", "tokenId", "askingPrice", "token.token_uri", "token.symbol", "token.owner_of","token.id", "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.token_id,
"tokenAddress": queryResults[i].attributes.token_address,
"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.define("getItem", async (request) => {
const query = new Moralis.Query("itemsForSale");
query.equalTo("uid", request.params.uid);
query.select("uid", "tokenAddress", "tokenId", "askingPrice", "token.token_uri", "token.symbol", "token.owner_of","token.id", "user.username","user.avatar");
const queryResult = await query.first({useMasterKey: true});
if(!queryResult)return;
return {
"uid": queryResult.attributes.uid,
"tokenId": queryResult.attributes.token_id,
"tokenAddress": queryResult.attributes.token_address,
"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,
};
});
Hereās my main.js
Moralis.initialize("ujvcezKVDZh4LKebB0EEsBMzO4Ac0BJIjEYQR7Ix");
Moralis.serverURL = 'https://lbgxuu4enm7h.bigmoralis.com:2053/server'
const TOKEN_CONTRACT_ADDRESS = "0x397Ec0554F9B05128bb133946e28e2Cea46a4663";
const MARKETPLACE_CONTRACT_ADDRESS = "0x53Edc2F72324f314d7FBaD87c27643A435de95d4";
init = async () => {
hideElement(userItemsSection);
hideElement(userInfo);
hideElement(createItemForm);
window.web3 = await Moralis.Web3.enable();
window.tokenContract = new web3.eth.Contract(tokenContractAbi, TOKEN_CONTRACT_ADDRESS);
window.marketplaceContract = new web3.eth.Contract(marketplaceContractAbi, MARKETPLACE_CONTRACT_ADDRESS);
initUser();
loadItems();
const soldItemsQuery = new Moralis.Query('Solditems');
const soldItemsSubscription = await soldItemsQuery.subscribe();
soldItemsSubscription.on("create", onItemSold);
const itemsAddedQuery = new Moralis.Query('ItemsForSale');
const itemsAddedSubscription = await itemsAddedQuery.subscribe();
itemsAddedSubscription.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);
loadUserItems();
} else {
showElement(userConnectButton);
hideElement(userProfileButton);
hideElement(openCreateItemButton);
hideElement(openUserItemsButton);
}
}
login = async () => {
try {
await Moralis.Web3.authenticate();
initUser();
} catch (error) {
alert(error);
}
}
logout = async () => {
await Moralis.User.logOut();
hideElement(userInfo);
initUser();
}
openUserInfo = async () => {
user = await Moralis.User.current();
if (user) {
const email = user.get('email');
if (email) {
userEmailField.value = email;
} else {
userEmailField.value = "";
}
userUsernameField.value = user.get('username')
const userAvatar = user.get('avatar');
if (userAvatar) {
userAvatarImg.src = userAvatar.url();
showElement(userAvatarImg);
} else {
hideElement(userAvatarImg);
}
showElement(userInfo);
} else{
login();
}
}
openUserItems = async () => {
user = await Moralis.User.current();
if (user) {
showElement(userItemsSection);
} else{
login();
}
}
saveUserInfo = async () => {
user.set('email', userEmailField.value);
user.set('username', userUsernameField.value);
if (userAvatarFile.files.length > 0) {
const avatar = new Moralis.File("avatar.png", userAvatarFile.files[0]);
user.set('avatar', avatar);
}
await user.save();
alert("User info saved successfully!");
openUserInfo();
}
createItem = async () => {
if (createItemFile.files.length == 0){
alert("please select a file!")
return;
} else if (createItemNameField.value.length == 0){
alert("please provide a name!")
return;
}
const nftFile = new Moralis.File("nftFile.png", createItemFile.files[0] );
await nftFile.saveIPFS();
const nftFilePath = nftFile.ipfs();
//CAN REMOVE THIS
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();
//CAN REMOVE THIS
const nftId = await mintNft(nftFileMetadataFilePath);
//USELESS CODE
/// END HERE
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;
}
}
mintNft = async (metadataUrl) => {
const receipt = await tokenContract.methods.createItem(metadataUrl).send({from: ethereum.selectedAddress});
console.log(receipt);
return receipt.events.Transfer.returnValues.tokenId;
}
loadUserItems = async () => {
const ownedItems = await Moralis.Cloud.run("getUserItems");
ownedItems.forEach(item => {
const userItemListing = document.getElementById(`user-item-${item.tokenObjectId}`);
if(userItemListing) return;
getAndRenderItemData(item, renderUserItem);
});
}
loadItems = async () => {
const items = await Moralis.Cloud.run("getItems");
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);
});
}
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].disabled = item.askingPrice > 0;
userItem.getElementsByTagName("button")[0].disabled = 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')});
};
userItem.id =`user-item-${item.tokenObjectId}`
userItems.appendChild(userItem);
}
renderItem = (item) => {
const itemForSale = marketplaceItemTemplate.cloneNode(true);
if (item.avatar){
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);
})
}
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});
}
}
buyItem = async (item)=> {
const user = await Moralis.User.current();
if(!user){
login();
return;
}
await marketplaceContract.methods.buyItem(item.uid).send({from: user.get('ethAddress'), value: item.askingPrice});
}
hideElement = (element) => element.style.display = "none";
showElement = (element) => element.style.display = "block";
//Nav bar
const userConnectButton = document.getElementById("btnConnect");
userConnectButton.onclick = login;
const userProfileButton = document.getElementById("btnUserInfo");
userProfileButton.onclick = openUserInfo;
const openCreateItemButton = document.getElementById("btnOpenCreateItem");
openCreateItemButton.onclick = () => showElement(createItemForm);
//user profile
const userInfo = document.getElementById("userInfo");
const userUsernameField = document.getElementById("txtUsername");
const userEmailField = document.getElementById("txtEmail");
const 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");
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();
Hereās my index.html file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MarketPlace</title>
</head>
<body>
<div>
<button id="btnConnect">Connect Wallet</button>
<button id="btnUserInfo">Profile</button>
<button id="btnOpenCreateItem">CreateItem</button>
<button id="btnMyItems">My Items</button>
</div>
<div id="userInfo">
<h4>User Profile</h4>
<input type="text" id="txtUsername" required placeholder="Enter username">
<input type="text" id="txtEmail" placeholder="Enter email">
<small>Optional</small>
<img width="50" height="50" src="" id="imgAvatar" alt="">
<label for="fileAvatar"> Select Avatar</label>
<input type="file" id="fileAvatar">
<button id="btnLogout"> Log out</button>
<button id="btnCloseUserInfo"> Close</button>
<button id="btnSaveUserInfo"> Save</button>
</div>
<div id="createItem">
<h4>Create Item</h4>
<input type="text" id="txtCreateItemName" required placeholder="Enter name">
<textarea id="txtCreateItemDescription" cols="30" rows="5" placeholder="Enter Description"></textarea>
<input type="number" min="1" step="1" id="numCreateItemPrice" placeholder="Enter price" required>
<label for="SelectCreateItemStatus"> Status</label>
<select id="SelectCreateItemStatus">
<option value="0">Not for sale </option>
<option value="1">Instant Buy</option>
<option value="2">Accept offers</option>
</select>
<label for="fileCreateItemFile"> Select File</label>
<input type="file" id="fileCreateItemFile">
<button id="btnCloseCreateItem"> Close</button>
<button id="btnCreateItem"> Create!</button>
</div>
<div id="userItems">
<h4> My items</h4>
<div id="userItemsList"></div>
<button id="btnCloseUserItems"> Close</button>
</div>
<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></button>
</div>
<script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script>
<script src="https://unpkg.com/moralis/dist/moralis.js"></script>
<script src="abi.js"></script>
<script src="main.js"></script>
</body>
</html>
hereās my error