I cloned rarible in 24h

error
Hey. When creating an NFT, i only get one Transaction and then i get this error. Please let me know what code you need to help me with my problem. Thanks

Hi,

Please let us know what video you are on for the Rarible series. Could you post your JS code and also your index.html.

For more reference on common problems and their solutions , you can check out this post over here -

I finished the tutorial. It stopped working in the last episodes of the tutorial, before that it worked already.

Moralis.initialize("4Z3hIFknTeFiZfsUlNdhwhU6aQLlUGta2FEZSFyK");

Moralis.serverURL = 'https://polsovuzsdll.bigmoralis.com:2053/server'

const TOKEN_CONTRACT_ADDRESS = "0x0645a5a0d64BfDD2CFddfC2Ba3EBee1f27Fca729";

const MARKETPLACE_CONTRACT_ADDRESS = "0x311701AA9E6C202f87F545fc9998A8ec571AE094";

init = async () => {

    hideElement(userItemsSection);

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

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

        }

        $('#userInfo').modal('show');

    }else{

        login();

    }

}

saveUserInfo = async () => {

    user.set('email', userEmailField.value);

    user.set('username', userUsernameField.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();

}

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 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 nftId = await mintNft(nftFileMetadataFilePath);

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

        $('#userItems').modal('show');

    }else{

        login();

    }

}

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.sellerAvatar){

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

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

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

    }

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

    itemsSale.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) => {

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

// Navbar

const userConnectButton = document.getElementById("btnConnect");

userConnectButton.onclick = login;

const userProfileButton = document.getElementById("btnUserInfo");

userProfileButton.onclick = openUserInfo;

const openCreateItemButton = document.getElementById("btnOpenCreateItem");

openCreateItemButton.onclick = () => $("#createItem").modal('show');

//  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 itemsSale = document.getElementById("itemsSale");

init();
<!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">

    

    <link rel="stylesheet" href="css/bootstrap.css">

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

    <title>Monkey NFT</title>

</head>

<body class="bg-dark">

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

        <a class="navbar-brand btn-logo rounded-pill" href="index.html"><img src="img/logo.png" alt="MonkeyNFT" width="212,625" height="41,77"> </a>

        <button class="navbar-toggler" type="button" data-toggle="collapse" data-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="flex-md-fill">

                <input type="search" class="bg-transparent form-control text-light rounded-pill" placeholder="Search">

            </form>

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

            <li class="nav-item">

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

            </li>

          </ul>

          <div class="d-flex">

            <button class="btn btn-primary rounded-pill" id = "btnOpenCreateItem">Create</button>

            <button class="btn btn-outline rounded-pill text-dark" id = "btnConnect">Connect wallet</button>

            <button class="btn btn-outline rounded-pill text-dark" id = "btnUserInfo">Profile</button>

            

        </div>

        </div>

      </nav>

   

     <div class="container">

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

        </div>

    </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 width="30" height="30" class="d-inline-block align-top rounded-circle" 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 btn-block"></button>

                </div>

        

            </div>

          </div>

    </div>

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

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

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

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

                <div class="w-100">

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

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

                    <div class="input-group mb-3">

                        <input type="number" min="1" step="1" class="form-control" placeholder="Price">

                        <div class="input-group-append">

                          <button class="btn btn-outline-secondary" type="button">Put for sale</button>

                        </div>

                      </div>

                </div>            

            </div>

          </div>

    </div>

  <!-- Modal -->

  <div class="modal fade" id="userInfo" tabindex="-1">

    <div class="modal-dialog">

    <div class="modal-content bg-dark text-light">

        <div class="modal-header">

        <h5 class="modal-title" >User Profile</h5>

        <button type="button" class="close" data-dismiss="modal" aria-label="Close">

            <span aria-hidden="true">&times;</span>

        </button>

        </div>

        <div class="modal-body">

            <div class="form-group">

                <label for="txtUsername">Username</label>

                <input type="text" class="form-control" id="txtUsername" required placeholder="Enter username">

            </div>

            <div class="form-group">

                <label for="txtEmail">Email address</label>

                <input type="email" class="form-control" id="txtEmail" aria-describedby="emailHelp" placeholder="Enter email">

                <small id="emailHelp" class="form-text text-muted">Optional</small>

            </div>

    

            <img width="50" height="50" src="" id="imgAvatar" alt="">

            <div class="form-group">

                <label for="fileAvatar">Select Avatar</label>

                <input type="file" class="form-control-file" id="fileAvatar">

            </div>

        </div>

        <div class="modal-footer">

        <button type="button" id="btnLogout" class="btn btn-secondary" data-dismiss="modal">Log out</button>

        <button type="button" id="btnCloseUserInfo" class="btn btn-secondary" data-dismiss="modal">Close</button>

        <button type="button" id="btnSaveUserInfo" class="btn btn-primary">Save</button>

        </div>

    </div>

    </div>

</div>

<div class="modal fade" id="createItem" tabindex="-1">

    <div class="modal-dialog">

    <div class="modal-content bg-dark text-light">

        <div class="modal-header">

        <h5 class="modal-title" >Create Item</h5>

        <button type="button" class="close" data-dismiss="modal" aria-label="Close">

            <span aria-hidden="true">&times;</span>

        </button>

        </div>

        <div class="modal-body">

            <div class="form-group">

                <label for="txtUsername">Name</label>

                <input type="text" class="form-control" id="txtCreateItemName" required placeholder="Enter name">

            </div>

            <div class="form-group">

                <label for="txtCreateItemDescription">Description</label>

                <textarea class="form-control" id="txtCreateItemDescription" cols="30" rows="5" placeholder="Enter description"></textarea>

            </div>

            <div class="form-group">

                <label for="txtUsername">Price</label>

                <input type="number" min="1" step="1" id="numCreateItemPrice" placeholder="Enter price" required class="form-control">

            </div>

            <div class="form-group">

                <label for="selectCreateItemStatus">Status</label>

                <select class="form-control" id="selectCreateItemStatus">        

                    <option value="0">Not for sale</option>

                    <option value="1">Instant buy</option>

                </select>

            </div>

            <div class="form-group">

                <label for="fileCreateItemFile">Select file</label>

                <input type="file" class="form-control-file" id="fileCreateItemFile">

            </div>

        </div>

        <div class="modal-footer">

        <button type="button" id="btnCloseCreateItem" class="btn btn-secondary" data-dismiss="modal">Close</button>

        <button type="button" id="btnCreateItem" class="btn btn-primary">Create</button>

        </div>

    </div>

    </div>

</div>

<div class="modal fade" id="userItems" tabindex="-1">

    <div class="modal-dialog modal-xl">

    <div class="modal-content bg-dark text-light">

        <div class="modal-header">

        <h5 class="modal-title" >My Items</h5>

        <button type="button" class="close" data-dismiss="modal" aria-label="Close">

            <span aria-hidden="true">&times;</span>

        </button>

        </div>

        <div class="modal-body row row-cols-1 row-cols-md-4 mt-5" id="userItemsList">

        </div>

        <div class="modal-footer">

            <button type="button" id="btnCloseUserItems" class="btn btn-secondary" data-dismiss="modal">Close</button>

        </div>

    </div>

    </div>

</div>

    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>

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

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

Will run and check from my side. Will get back to you regarding this.

Thanks

Hi,
You say that you are able to mint once and then you get an error on the following mints?

You can try to use various Moralis SDK versions to see if it is something related to a recent SDK update with <script src="https://npmcdn.com/[email protected]/dist/moralis.js"></script> instead of <script src="https://unpkg.com/moralis/dist/moralis.js"></script>

You can try to put a console.log before calling mint with what parameters you send to mint function (before const receipt = await tokenContract.methods.createItem(metadataUrl).send({from: ethereum.selectedAddress});) , including the from that it is an address, to see what values you have there.

Ok i think it works now. I think the problem was because of my cloud functions. Thanks

1 Like

Hello,
I have finished this tutorial “I Clonde Rarible In 24H”.
Everything works on my side but i still have 2 major questions because i think the tutorial is not complete :
1- how do we setup fees for the marketplace (a money commission percentage for the owner of the marketplace). Should i put this extra code in the solidity contract or on the client side (in the frontend loading main.js) ?
2- how do we setup the search engine to allow visitors look for items on criterias : NFT address, user profile, by any keyword in the NFT description and/or any other property of the NFT. Impossible for me to use the MySQL logic in my cloud function on Moralis server.

Thank you for any explanation or links you may provide !