[SOLVED] I BUILT AN NFT GAME IN 12 HOURS (Part 5) - getAllTokensForUser returning 0

Working on part 5 of this tutorial and having an issue returning the minted NFTs associated with the address i’m using in Metamask (local dev server).

Token.sol code for the relevant function is as follows:

function getAllTokensForUser(address user) public view returns (uint256[] memory){
        uint256 tokenCount = balanceOf(user);
        if(tokenCount == 0){
            return new uint256[](0);
        }
        else{
            uint256[] memory result = new uint256[](tokenCount); //uint256?
            uint256 totalPets = nextId;
            uint256 resultIndex = 0;
            uint256 i;
            for(i = 0; i < totalPets; i++){
                if(ownerOf(i) == user){
                    result[resultIndex] = i;
                    resultIndex++;
                }
            }
            return result;
        }
    }

Migration code:

const Token = artifacts.require("Token");

module.exports = async function (deployer) {
  await deployer.deploy(Token, "NFT Game", "NFTG");
  let tokenInstance = await Token.deployed();
  await tokenInstance.mint(100, 200, 100000);
  await tokenInstance.mint(200, 100, 200000);
  await tokenInstance.mint(240, 180, 250000);
  await tokenInstance.mint(230, 150, 150000);
  await tokenInstance.mint(220, 180, 220000);
  let pet = await tokenInstance.getTokenDetails(0);
  let pet1 = await tokenInstance.getTokenDetails(1);
  let pet2 = await tokenInstance.getTokenDetails(2);
  let pet3 = await tokenInstance.getTokenDetails(3);
  let pet4 = await tokenInstance.getTokenDetails(4);
  console.log(pet);
};

Function called in Main.js:

    let array = await contract.methods.getAllTokensForUser(ethereum.selectedAddress).call({from: ethereum.selectedAddress});

I think it’s identical to the tutorial code, can’t figure out where i’m going wrong! I’m pretty certain balanceOf(user) is returning 0, as if i replace

if(tokenCount == 0){
            return new uint256[](0);
        }

with

if(tokenCount == 0){
            return new uint256[](2);
        }

it returns a 2 element array with 2 empty elements. with the original code it’s just an empty array.

Would hugely appreciate any advice anyone has! please let me know if i should provide more details.

hey @bakula

Please share the full smart contract code you use

here it is! Token.sol:

pragma solidity 0.8.9;


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

contract Token is ERC721, Ownable {
    struct Pet {
        uint8 damage;
        uint8 magic;
        uint256 lastMeal;
        uint256 endurance;
    }

    uint256 nextId = 0;

    mapping( uint256 => Pet) private _tokenDetails;

    constructor(string memory name, string memory symbol) ERC721(name, symbol){
    }

    function getTokenDetails(uint256 tokenId) public view returns (Pet memory){
        return _tokenDetails[tokenId];
    }

    function mint(uint8 damage, uint8 magic, uint256 endurance) public onlyOwner {
        _tokenDetails[nextId] = Pet(damage, magic, block.timestamp, endurance);
        nextId++;
    }

    function feed(uint256 tokenId) public{
        Pet storage pet = _tokenDetails[tokenId];
        require(pet.lastMeal + pet.endurance > block.timestamp);
        pet.lastMeal = block.timestamp;
    }

    function getAllTokensForUser(address user) public view returns (uint256[] memory){
        uint256 tokenCount = balanceOf(user);
        if(tokenCount == 0){
            return new uint256[](0);
        }
        else{
            uint256[] memory result = new uint256[](tokenCount); //uint256?
            uint256 totalPets = nextId;
            uint256 resultIndex = 0;
            uint256 i;
            for(i = 0; i < totalPets; i++){
                if(ownerOf(i) == user){
                    result[resultIndex] = i;
                    resultIndex++;
                }
            }
            return result;
        }
    }

    function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal override{
        Pet storage pet = _tokenDetails[tokenId];
        require(pet.lastMeal + pet.endurance > block.timestamp);
    }

}
1 Like

At a first look, it looks like you should have:

    function mint(uint8 damage, uint8 magic, uint256 endurance) public onlyOwner {
        _tokenDetails[nextId] = Pet(damage, magic, block.timestamp, endurance);
       _safeMint(msg.sender, nextId);
        nextId++;
    }

instead of

    function mint(uint8 damage, uint8 magic, uint256 endurance) public onlyOwner {
        _tokenDetails[nextId] = Pet(damage, magic, block.timestamp, endurance);
        nextId++;
    }

mainly you should have that _safeMint(msg.sender, nextId); line

THANK YOU!

This was it, i don’t know how i missed it! It’s working now thanks so much!

1 Like