when i create a new item in my mktplace the item gets minted but when going to be added to the mktplace i get this error in the console: Uncaught (in promise) TypeError: Cannot read property āvalueā of null
at HTMLButtonElement.createItem (main.js:135)
createItem @ main.js:135
async function (async)
createItem @ main.js:97
i think its a really dumb problem but i cant spot it, already did everything again, compare code etc etc and nothing, here is my js file and my marketplace contract :
Moralis.initialize("2S1i7BlfGKjOjjH913O08FZoZ9eZ9SFnCAsGB8Px");
Moralis.serverURL = 'https://hwjejw7sflts.usemoralis.com:2053/server'
const TOKEN_CONTRACT_ADDRESS = "0x820d3Eb7518A3a90AbDb1E724453B715a6E5eC2c";
const MARKETPLACE_CONTRACT_ADDRESS = "0xA84b42e49032e55c32A0E37254Fe042b654Cec8B";
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();
}
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();
}
}
saveUserInfo = async () => {
user.set('email', userEmailField.value);
user.set('username', userUsernameField.value);
if (userAvatarFile.files.length > 0) {
const avatar = new Moralis.File("avatar.jpg", userAvatarFile.files[0]);
user.set('avatar', avatar);
}
await user.save();
alert("User Info saved successfully!");
openUserInfo();
}
createItem = async () => {
if (createItemFile.files.length == 0){
alert("Please select a file!");
return;
} else if (createItemNameField.value.length == 0){
alert("Please give the item a name!");
return
}
const nftFile = new Moralis.File("nftFile.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");
// Create a new instance of that class.
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;
}
}
mintNft = async (metadataUrl) => {
const receipt = await tokenContract.methods.createItem(metadataUrl).send({from: ethereum.selectedAddress});
console.log(receipt);
return receipt.events.Transfer.returnValues.tokenId;
}
openUserItems = async () => {
user = await Moralis.User.current();
if (user){
showElement(userItemsSection);
}else{
login();
}
}
loadUserItems = async () => {
const ownedItems = await Moralis.Cloud.run("getUserItems");
ownedItems.forEach(item => {
getAndRenderItemData(item, renderUserItem);
});
}
initTemplate = (id) => {
const template = document.getElementById(id);
template.id = "";
template.parentNode.removeChild(template);
return template;
}
renderUserItem = (item) => {
const userItem = userItemTemplate.cloneNode(true);
userItem.getElementsByTagName("img")[0].src = item.image;
userItem.getElementsByTagName("img")[0].alt = item.name;
userItem.getElementsByTagName("img")[0].innerText = item.name;
userItem.getElementsByTagName("img")[0].innerText = item.description;
userItems.appendChild(userItem);
}
getAndRenderItemData = (item, renderFunction) => {
fetch(item.tokenUri)
.then(response => response.json())
.then(data => {
data.symbol = item.symbol;
data.tokenId = item.tokenId;
data.tokenAddress = item.tokenAddress;
renderFunction(data);
})
}
ensureMarketplaceIsApproved = async (tokenId, tokenAddress) => {
user = await Moralis.User.current();
const userAddress = user.get('ethAddress');
const contract = window.tokenContract = new web3.eth.Contract(tokenContractAbi, tokenAddress);
const approvedAddress = await contract.methods.getApproved(tokenId).call({from: tokenAddress});
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";
// Navbar
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(userInfo);
const openUserItemsButton = document.getElementById("btnMyItems");
openUserItemsButton.onclick = openUserItems;
const userItemTemplate = initTemplate("itemTemplate")
init();
pragma solidity ^0.8.0;
import "../node_modules/@openzeppelin/contracts/token/ERC721/IERC721.sol";
contract CryptoFansMarketContract {
struct AuctionItem {
uint256 id;
address tokenAddress;
uint256 tokenId;
address payable seller;
uint256 askingPrice;
bool isSold;
}
AuctionItem[] public itemsForSale;
mapping (address => mapping (uint256 => bool)) activeItems;
event itemAdded(uint256 id, uint256 tokenId, address tokenAddress, uint256 askingPrice);
event itemSold(uint256 id, address buyer, uint256 askingPrice);
modifier OnlyItemOwner(address tokenAddress, uint256 tokenId){
IERC721 tokenContract = IERC721(tokenAddress);
require(tokenContract.ownerOf(tokenId) == msg.sender);
_;
}
modifier HasTransferApproval(address tokenAddress, uint256 tokenId){
IERC721 tokenContract = IERC721(tokenAddress);
require(tokenContract.getApproved(tokenId) == address(this));
_;
}
modifier ItemExists(uint256 id){
require(id < itemsForSale.length && itemsForSale[id].id == id, "Could not find item");
_;
}
modifier IsForSale(uint256 id){
require(itemsForSale[id].isSold == false, "Item is already sold!");
_;
}
function addItemToMarket(uint256 tokenId, address tokenAddress, uint256 askingPrice) OnlyItemOwner(tokenAddress,tokenId) HasTransferApproval(tokenAddress,tokenId) external returns (uint256){
require(activeItems[tokenAddress][tokenId] == false, "Item is already up for sale!");
uint256 newItemId = itemsForSale.length;
itemsForSale.push(AuctionItem(newItemId, tokenAddress, tokenId, payable(msg.sender), askingPrice, false));
activeItems[tokenAddress][tokenId] = true;
assert(itemsForSale[newItemId].id == newItemId);
emit itemAdded(newItemId, tokenId, tokenAddress, askingPrice);
return newItemId;
}
function buyItem(uint256 id) payable external ItemExists(id) IsForSale(id) HasTransferApproval(itemsForSale[id].tokenAddress,itemsForSale[id].tokenId){
require(msg.value >= itemsForSale[id].askingPrice, "Not enough funds sent");
require(msg.sender != itemsForSale[id].seller);
itemsForSale[id].isSold = true;
activeItems[itemsForSale[id].tokenAddress][itemsForSale[id].tokenId] = false;
IERC721(itemsForSale[id].tokenAddress).safeTransferFrom(itemsForSale[id].seller, msg.sender, itemsForSale[id].tokenId);
itemsForSale[id].seller.transfer(msg.value);
emit itemSold(id, msg.sender, itemsForSale[id].askingPrice);
}
}