NFT Creation App - Token not appearing after successful minting transaction

NFT Token Not Showing in Wallet After Mint

I built a decentralized application for creating NFTs and deployed it on Polygon Mumbai testnet. The minting process completes successfully and I get a transaction hash, but the NFT token doesn’t appear in my wallet afterward.

Has anyone encountered this problem before? What could be causing the disconnect between successful transaction and token visibility?

Smart Contract Implementation:

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.1;

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

contract CryptoArtTokens is ERC721, Ownable {
    uint256 public constant TOTAL_SUPPLY = 10;
    uint256 public constant MINT_COST = 0.01 ether;
    uint256 public currentTokenId = 1;

    constructor() ERC721("CryptoArtTokens", "CART") {}

    function createNFT() public payable {
        require(currentTokenId <= TOTAL_SUPPLY, "All tokens have been minted");
        require(msg.value >= MINT_COST, "Insufficient payment amount");

        _safeMint(msg.sender, currentTokenId);
        currentTokenId++;
    }

    function withdrawFunds() public onlyOwner {
        uint256 contractBalance = address(this).balance;
        payable(msg.sender).transfer(contractBalance);
    }
}

Frontend React Code:

import React, { useState } from 'react';
import Web3 from 'web3';
import { Container, Row, Col, Button, Navbar } from 'react-bootstrap';
import 'bootstrap/dist/css/bootstrap.css';
import CryptoArtTokens from './contracts/CryptoArtTokens.json';
import artworkImg from './assets/artwork.png';
import './App.css';

function App() {

  const [web3Instance, setWeb3Instance] = useState(null);
  const [smartContract, setSmartContract] = useState(null);
  const [userAddress, setUserAddress] = useState("");
  const [ownedTokens, setOwnedTokens] = useState([]);
  const [errorMessage, setErrorMessage] = useState("");

  const initializeWeb3 = async () => {
    try{
      if(window.ethereum){
        const web3Instance = new Web3(window.ethereum);
        await window.ethereum.request({ method: 'eth_requestAccounts' });
        setWeb3Instance(web3Instance);
        const smartContract = new web3Instance.eth.Contract(
          CryptoArtTokens.abi, "0xD5C6ba7fD9AB133d8CfCE96bF144B152C218B107"
        );
        setSmartContract(smartContract);
        const accounts = await web3Instance.eth.getAccounts();
        setUserAddress(accounts[0]);
        const ownedTokens = await smartContract.methods
          .tokensOfOwner(accounts[0])
          .call();
        setOwnedTokens(ownedTokens);
      }else{
        setErrorMessage("MetaMask extension required!");
      }
    }catch(error) {
      console.error(error);
      setErrorMessage("Connection to blockchain failed!");
    }
  };

  const purchaseNFT = async() => {
    try{
      const transaction = await smartContract.methods.createNFT().send({
        from: userAddress,
        value: web3Instance.utils.toWei("0.01", "ether"),
      });
      console.log(transaction);
      setOwnedTokens([...ownedTokens, transaction]);
    }catch(error){
      console.error(error);
    }
  };

  if(!web3Instance){
    return(
      <div className="connect-wallet">
        <Button variant="primary" onClick={initializeWeb3}>Connect Wallet</Button>
        {errorMessage && <p>{errorMessage}</p>}
      </div>
    );
  }

  return (
    <>
      <Navbar bg="dark" variant="dark">
        <Navbar.Brand>&nbsp; Digital Art Collection </Navbar.Brand>
        <Navbar.Text>{userAddress}</Navbar.Text>
      </Navbar>
      <br/>
      <Container className="nft-gallery">
        <Row className="justify-content-center">
          <Col xs={12} md={8} lg={6}>
            <Row className="justify-content-center">
              {[1,2,3,4,5,6,7,8,9].map((tokenNumber) => (
                <Col xs={12} md={6} lg={4} key={tokenNumber}>
                  <div className="token-card">
                    <img
                      src={artworkImg}
                      alt={`Token #${tokenNumber}`}
                      width={200}
                      style={{marginBottom: "10px"}}
                    />
                  </div>
                </Col>
              ))}
            </Row>
            <br/>
            <div className="text-center">
              <Button variant="success" onClick={purchaseNFT}>Mint Token</Button>
              <p className="mt-2">
                Price: 0.01 MATIC
              </p>
              <p>
                Owned: {ownedTokens.length}/10 tokens
              </p>
            </div>
          </Col>
        </Row>
      </Container>
    </>
  );
}

export default App;

Oh this is interesting! I’ve hit similar issues before - super frustrating when everything seems to work but your NFT just vanishes :thinking:

Few things I’m wondering about your code:

First, are you checking the transaction receipt to confirm the mint actually worked? Sometimes transactions go through but fail internally.

Which wallet are you using to check? MetaMask is notoriously wonky with new NFTs, especially on testnets.

I noticed your frontend calls tokensOfOwner but I don’t see that function in your contract code. Did you implement it separately or could that be the problem?

Have you checked the transaction on PolygonScan to see if it actually minted? And are you manually adding the contract address to your wallet?

What’s your console.log showing when you mint? Does the transaction object look normal? Curious what you’re seeing!

Had this exact problem last month - spent hours pulling my hair out. Your frontend isn’t waiting for the transaction to confirm before updating state. You’re setting ownedTokens with the transaction object instead of the actual token ID. After createNFT() runs, wait for the transaction receipt then fetch the updated balance. Ditch that setOwnedTokens([...ownedTokens, transaction]) line and properly refresh your token data instead. Also, double-check your contract’s tokensOfOwner function - I don’t see it in your code snippet. One more thing - Mumbai testnet’s been acting weird lately. I’ve seen transactions take 10-15 minutes to show up in wallets. Check the actual transaction on polygonscan before assuming it failed.

your contract’s missing a tokenURI function - that’s why wallets can’t display the NFT. minting might work fine, but without metadata, wallets have nothing to show. try refreshing your wallet or manually add the token address. mumbai testnet can be really slow too.