1

Let's say that I have an ERC721 (NFT) contract that represents a set of playing cards.

Is there sample code out there that shows listing all of the tokens of that ERC721 contract that a user owns on a web page so that the user could select one?

  • The sample code for this would be the cryptokitties web page. – Nulik Jul 23 '18 at 14:27
1

The current draft of the ERC721 standard calls for contracts adhering to that standard to have a totalSupply attribute, as well as balanceOf(address _owner) and ownerOf(uint256 _tokenId) functions.

To find all items a given address owns, the front-end DApp would need to query for the totalSupply (say, 52 playing cards), and then loop from zero to that number and call the ownerOf method on that ID, looking for the result to match the target address being searched for. When a match is found, that item can be added to a list of known assets for that account, and if the length of that list is now equal to the result of a balanceOf call for that user, the looping can stop since all assets have been found.

The ERC721 standard optionally calls for a tokenOfOwnerByIndex(address _owner, uint256 _index) call that can make the looping shorter, but that is an optional function to implement for an ERC721 token. If the token you've created has such a function, then you can use that to loop through the results more efficiently.

|improve this answer|||||
  • The tokenId might not be consecutive numbers, and iterating over possible uint256 values is a no go. A better approach is to listen for Transfer events. – Ismael Jul 25 '18 at 16:53
  • That assumes that Transfer events are fired for token minting as well as moving existing tokens. And it requires parsing all Transfer events for the contract for the entire length of time since the contract's creation. So, still some caveats. If an ERC721 contract uses non-sequential IDs, hopefully it also provides some other means to iterate over them – MidnightLightning Jul 25 '18 at 17:06
  • 1
    From the spec: This emits when ownership of any NFT changes by any mechanism. This event emits when NFTs are created (from == 0) and destroyed (to == 0). Exception: during contract creation, any number of NFTs may be created and assigned without emitting Transfer. You are correct listen for Transfer will work but not in all cases. – Ismael Jul 25 '18 at 17:49
1

You could add a function to your smart contract that mimics what the CryptoKitties contract does in function tokensOfOwner, which

Returns a list of all Kitty IDs assigned to an address

/// @title The facet of the CryptoKitties core contract that manages ownership, ERC-721 (draft) compliant.
/// @author Axiom Zen (https://www.axiomzen.co)
/// @dev Ref: https://github.com/ethereum/EIPs/issues/721
///  See the KittyCore contract documentation to understand how the various contract facets are arranged.
contract KittyOwnership is KittyBase, ERC721 {

[...]

/// @notice Returns a list of all Kitty IDs assigned to an address.
    /// @param _owner The owner whose Kitties we are interested in.
    /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly
    ///  expensive (it walks the entire Kitty array looking for cats belonging to owner),
    ///  but it also returns a dynamic array, which is only supported for web3 calls, and
    ///  not contract-to-contract calls.
    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;
        }
    }
|improve this answer|||||

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.