I am using openzeppelin erc721 library to create an NFT and need to list all the tokens of a user. The most obvious way is to iterate through all the tokens in the contract and check if the owner of the token is same as the address I have sent.
function tokensOfOwner(address _owner) external view returns(uint256[] ownerTokens) {
uint256 tokenCount = balanceOf(_owner);
if (tokenCount == 0) {
// Return an empty array
return new uint256[](0);
} else {
uint256[] memory result = new uint256[](tokenCount);
uint256 totalCats = totalSupply();
uint256 resultIndex = 0;
// We count on the fact that all cats have IDs starting at 1 and increasing
// sequentially up to the totalCat count.
uint256 catId;
for (catId = 1; catId <= totalCats; catId++) {
if (kittyIndexToOwner[catId] == _owner) {
result[resultIndex] = catId;
resultIndex++;
}
}
return result;
}
}
Another solution that I am thinking of implementing is to have a mapping where I map the user address to an array or another mapping which includes all the tokens the user owns. Upon transferring the token to another address, I would need to remove the token from seller list and add it to buyers list. This solution sounds more reasonable but I dont know how cost efficient it will be. What are the disadvantages of this method?
Best Answer
This can be achieved by the following:
Declare storage variables at the contract level
To get all user tokens without loop, all you have to do is, this is possible as the access specifier for userOwnedTokens is public
In case of transfer of tokens, change tokenIsAtIndex[tokenId] to -1
Next time when
userOwnedTokens
is called you can keep a check wherever the tokenId is 000, those tokens have already been transferred and you can decide not to show it to the user on the frontend.I hope it helps!!!!!