[SOLVED] getNFTs 400 error

Hello,

I just completed the “Ethereum Programming for Beginners - How to Create Your First dApp (FULL COURSE)” video tutorial and I am running into an error with the getNFTs() function. The NFT metadata is being called into my app I can see it in the console and my NFT cards with name load on the page, however the pictures will not load. I am getting an http 400 error. I copied and pasted the individual NFT url’s into my browser and I see that they load individually, they just don’t appear in my app.

I have updated my server and tried the web3api already, as well as searched through this forum for answers. I cant seem to figure out what’s up. Is this an issue happening on the backend of the moralis client? Any help would be greatly appreciated.

Server URL : https://tgnvrdpsp6md.moralishost.com:2053/server
Test Wallet Address: 0xF991c5E03642F8e5EeE63039f6804B9b1e035F91

Javascript Code Below:

// Connection to Moralis Mainnet Server
Moralis.initialize("meVwdLkTtD9g88SkbxCvVBlpeQiM2l5dz1IKrd8Q");
Moralis.serverURL = "https://tgnvrdpsp6md.moralishost.com:2053/server";

// TO DO: CHANGE WHEN LIVE 
//User Log In Check
let homepage = "http://127.0.0.1:5500/index.html";
if (Moralis.User.current() == null && window.location.href != homepage) {
    document.querySelector('body').style.display = 'none';
    window.location.href = "index.html";
}
//User Authentication/Log In 
login = async () => {
    await Moralis.authenticate().then(async function (user) {
        console.log('Logged In');
        user.set("name", document.getElementById('user-username').value);
        user.set("email", document.getElementById('user-email').value);
        await user.save();
        window.location.href = "dashboard.html";
    })
}
//User Log Out
logout = async () => {
    await Moralis.User.logOut();
    window.location.href = "index.html";
}
//TO DO: CHANGE WHEN LIVE
//Get Transactions Function
getTransactions = async () => {
    console.log('get transactions clicked');
    const options = { chain: 'rinkeby', address: "0xF991c5E03642F8e5EeE63039f6804B9b1e035F91" };
    const transactions = await Moralis.Web3API.account.getTransactions(options);
    console.log(transactions);
//Table Variable
    if (transactions.total > 0) {
        let table = `
        <table class="table">
        <thead>
            <tr>
                <th scope="col">Transaction</th>
                <th scope="col">Block Number</th>
                <th scope="col">Age</th>
                <th scope="col">Type</th>
                <th scope="col">Fee</th>
                <th scope="col">Value</th>
            </tr>
        </thead>
        <tbody id="theTransactions">
        </tbody>
        </table>
        `
        document.querySelector('#tableOfTransactions').innerHTML = table;
//Transactions Array       
        transactions.result.forEach(t => {
            let content = `
            <tr>
                <td><a href='https://rinkeby.etherscan.io/tx/${t.hash}' target="_blank" rel="noopener noreferrer">${t.hash}</a></td>
                <td><a href='https://rinkeby.etherscan.io/block/${t.block_number}' target="_blank" rel="noopener noreferrer">${t.block_number}</a></td>
                <td>${millisecondsToTime(Date.parse(new Date()) - Date.parse(t.block_timestamp))}</td>
                <td>${t.from_address == Moralis.User.current().get('ethAddress') ? 'Outgoing' : 'Incoming'}</td>
                <td>${((t.gas * t.gas_price) / 1e18).toFixed(5)} ETH</td>
                <td>${(t.value / 1e18).toFixed(5)} ETH</td>
            </tr>
            `
            theTransactions.innerHTML += content;
        })
    }
}
//Balances Array    
getBalances = async () => {
    console.log('Get Balances Clicked');
    const ethBalance = await Moralis.Web3API.account.getNativeBalance();
    const ropstenBalance = await Moralis.Web3API.account.getNativeBalance({ chain: "ropsten"});
    const rinkebyBalance = await Moralis.Web3API.account.getNativeBalance({ chain: "rinkeby"});
    console.log( (ethBalance.balance / 1e18).toFixed(5) + "ETH");
    console.log( (ropstenBalance.balance / 1e18).toFixed(5) + "ETH");
    console.log( (rinkebyBalance.balance / 1e18).toFixed(5) + "ETH");

    let content = document.querySelector('#userBalances').innerHTML = `
    <table class="table">
        <thead>
            <tr>
                <th scope="col">Chain</th>
                <th scope="col">Balance</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <th>Ether</th>
                <td>${(ethBalance.balance / 1e18).toFixed(5)} ETH</td>
            </tr>
            <tr>
                <th>Ropsten</th>
                <td>${(ropstenBalance.balance / 1e18).toFixed(5)} ETH</td>
            </tr>
            <tr>
                <th>Rinkeby</th>
                <td>${(rinkebyBalance.balance / 1e18).toFixed(5)} ETH</td>
            </tr>
        </tbody>
    </table>
    `
}

//NFT Array/Display
getNFTs = async () => {
    console.log('Get NFTs Clicked');
    let nfts = await Moralis.Web3API.account.getNFTs({ chain: 'rinkeby' });
    console.log(nfts);
    let tableOfNFTs = document.querySelector('#tableOfNFTs');

    if(nfts.result.length >= 0){
        nfts.result.forEach(n =>{
            let metadata = JSON.parse(n.metadata);
            let content = `
            <div class="card col-md-3">
                <img src="${fixURL(metadata.image)}" class="card-img-top" height=300>
                <div class="card-body">
                    <h5 class="card-title">${metadata.name}</h5>
                    <p class="card-text"${metadata.description}</p>
                </div>
            </div>
            `
            tableOfNFTs.innerHTML += content;
        })
    }
}
//IPFS URL conversion for moralis
fixURL = (url) => {
    if (url.startsWith("ipfs")) {
        return "https://ipfs.moralis.io:2053/ipfs/" + url.split("ipfs://").slice(-1)
    }
    else {
        return url + "?format=json"
    }
}


//Milliseconds to Time Function
millisecondsToTime = (ms) => {
    let minutes = Math.floor(ms / (1000 * 60));
    let hours = Math.floor(ms / (1000 * 60 * 60));
    let days = Math.floor(ms / (1000 * 60 * 60 * 24));
    if(days < 1){
        if(hours < 1){
            if(minutes < 1){
                return `less than a minute ago`
            } else return `${minutes} minute(s) ago`
        } else return `${hours} hour(s) ago`
    } else return `${days} day(s) ago`
}

if(document.querySelector('#btn-login') != null){
    document.querySelector('#btn-login').onclick = login;
}
if(document.querySelector('#btn-logout') != null){
    document.querySelector('#btn-logout').onclick = logout;
}
if(document.querySelector('#get-transactions-link') != null){
    document.querySelector('#get-transactions-link').onclick = getTransactions;
}
if(document.querySelector('#get-balances-link') != null){
    document.querySelector('#get-balances-link').onclick = getBalances;
}
if(document.querySelector('#get-nfts-link') != null){
    document.querySelector('#get-nfts-link').onclick = getNFTs;
}

Dashboard HTML Code Below:

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="description" content="">
  <meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors">
  <meta name="generator" content="Hugo 0.84.0">
  <title>NwarFolio | Dashboard</title>

  <link rel="canonical" href="https://getbootstrap.com/docs/5.0/examples/dashboard/">
  <link href="css/bootstrap.min.css" rel="stylesheet">
  <link href="dashboard.css" rel="stylesheet">
  <link href="style.css" rel="stylesheet">

  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/web3.min.js"></script>
  <script src="https://unpkg.com/[email protected]/dist/moralis.js"></script> 
 
  <!-- Custom styles for this template -->

</head>

<body>

  <header class="navbar navbar-dark sticky-top bg-dark flex-md-nowrap p-0 shadow">
    <a class="navbar-brand col-md-3 col-lg-2 me-0 px-3" href="#">NwarFolio</a>
    <button class="navbar-toggler position-absolute d-md-none collapsed" type="button" data-bs-toggle="collapse"
      data-bs-target="#sidebarMenu" aria-controls="sidebarMenu" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <input class="form-control form-control-dark w-100" type="text" placeholder="Search" aria-label="Search">
    <div class="navbar-nav">
      <div class="nav-item text-nowrap">
        <a id="btn-logout" class="nav-link px-3" href="http://127.0.0.1:5500/index.html">Sign out</a>
      </div>
    </div>
  </header>

  <div class="container-fluid">
    <div class="row">
      <nav id="sidebarMenu" class="col-md-3 col-lg-2 d-md-block bg-light sidebar collapse">
        <div class="position-sticky pt-3">
          <ul class="nav flex-column">
            <li class="nav-item">
              <a class="nav-link active" aria-current="page" href="#">
                <span data-feather="home"></span>
                Dashboard
              </a>
            </li>
            <li class="nav-item">
              <a id="get-transactions-link" class="nav-link" href="#">
                <span data-feather="file"></span>
                Transactions
              </a>
            </li>
            <li class="nav-item">
              <a id="get-balances-link" class="nav-link" href="#">
                <span data-feather="shopping-cart"></span>
                Balances
              </a>
            </li>
            <li class="nav-item">
              <a id="get-nfts-link" class="nav-link" href="#">
                <span data-feather="users"></span>
                NFTs
              </a>
            </li>

          </ul>


        </div>
      </nav>

      <main class="col-md-9 ms-sm-auto col-lg-10 px-md-4">
        <div
          class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
          <h1 class="h2">Dashboard</h1>

        </div>
        <h2>Transactions</h2>
        <div id="tableOfTransactions" class="table-responsive">

        </div>
        
        <h2>Balances</h2>
        <div id="userBalances" class="table-responsive">

        </div>
        
        <h2>NFTs</h2>
        <div id="tableOfNFTs" class="table-responsive d-flex flex-wrap">

        </div>
      </main>
    </div>
  </div>


  <script src="js/bootstrap.bundle.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/feather.min.js"
    integrity="sha384-uO3SXW5IuS1ZpFPKugNNWqTZRRglnUJK6UAZ/gxOX80nxEkN9NcGZTftn6RzhGWE"
    crossorigin="anonymous"></script>
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/Chart.min.js"
    integrity="sha384-zNy6FEbO50N+Cg5wap8IKA4M/ZnLJgzc6w2NqACZaK0u0FXfOWRRJOnQtpZun8ha"
    crossorigin="anonymous"></script>
  <script src="dashboard.js"></script>
  <script src="main.js"></script>
  


</body>

</html>

Index HTML Code Below:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors">
    <meta name="generator" content="Hugo 0.84.0">
    <title> NwarFolio | Login In</title>

    <link rel="canonical" href="https://getbootstrap.com/docs/5.0/examples/sign-in/">
    <link href="css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="signin.css">
    <link rel="stylesheet" href="style.css"> 

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/web3.min.js"></script>
    <script src="https://unpkg.com/[email protected]/dist/moralis.js"></script>

    <!-- Custom styles for this template -->
   
  </head>
  <body class="text-center">
    
<main class="form-signin">
  
    <img class="mb-4" src="LogIn.png" alt="" width="72" height="57">
    <h1 class="h3 mb-3 fw-normal">Please sign in</h1>

    
    <div class="form-floating">
      <input type="text" class="form-control" id="user-username" placeholder="Username">
      <label for="user-username">Username</label>
    </div>
    <div class="form-floating">
      <input type="email" class="form-control" id="user-email" placeholder="[email protected]">
      <label for="user-email">Email address</label>
    </div>

    <div class="checkbox mb-3">
      <label>
        <input type="checkbox" value="remember-me"> Remember me
      </label>
    </div>
    <button id="btn-login" class="w-100 btn btn-lg btn-primary" type="submit">Sign in</button>
    <p class="mt-5 mb-3 text-muted">&copy; 2017–2021</p>
  
</main>


    <script src="main.js"></script>
  </body>
</html>

Thank you for the assistance,
Jah

NFT’s loading in browser seperate from app:

Problem solved. I added an extra ‘ipfs’ after the 2053/ in the ipfs.moralis url. Just in case anyone else runs into the same issue the correct code is below:

fixURL = (url) => {
    if (url.startsWith("ipfs")) {
        return "https://ipfs.moralis.io:2053/" + url.split("ipfs://").slice(-1)
    }
    else {
        return url + "?format=json"
    }
}

hi there, I’m not sure whether the problem I’m having is the same or similar.I’m getting a 404 error when trying to view my nft images, I think I’m missing something as the json text shows up when I search the URL but when I try searching the image the 404 error comes up, which means, I think I haven’t loaded the images my moralis server. What have I missed? I was going to watch cloud function but I thinking it maybe something else, I’m new and learning through mistakes and searching through the forum for answers. I’m also following the moralis ultimate nft tutorial. Would you have any idea on a process I need to complete to add these images please? Thanks in advance in any case. Cheers

error 404 usually means a Not Found error, meaning that the link may not be the correct one. What is the link that you are trying to access when you get that 404 error?

https://uzqkqggilapz.bigmoralis.com/Quinoinconcert.jpg, I think I will go back and try and get back to the status I was in, as now when trying to deploy the cli again I’m not getting the normal questions after ApiSecret. It just asks which server but doesn’t actually list my server and option of 0. Thanks for replying if you have an idea of what I may done to not get the image into the server, that would be great, but I have to retrace my steps I think. I hate being a hassle. Cheers cryptokid.