alpha-wallet-android icon indicating copy to clipboard operation
alpha-wallet-android copied to clipboard

Use ERC721Enumerable Interface if available

Open JamesSmartCell opened this issue 3 years ago • 2 comments

  • Create a new ERC721 type, ERC721_Enumerable (in ContractType).
  • Check if the ERC721 contract has the Enumerable interface (TokenRepository, find the correct value for INTERFACE_ERC721ENUMERABLE). bytes4 private constant _INTERFACE_ID_ERC721_ENUMERABLE = 0x780e9d63;
  • Label the ERC721 which we now know is an Enumerable as ERC721_Enumerable, when we do the determineCommonType()
  • ~~Inherit the ERC721Token class and override the updateBalance method to create the class.~~

Instead of needing to trawl event history we can fetch full TokenId balance with only two calls.

First calling the balanceOf(address) - which is already done by the default ERC721 balance update before updateBalance is called, then crawling the indices {0 -> balance count} up to the balance count by calling the contract function:

uint256 tokenOfOwnerByIndex({wallet address}, index)

This function returns the TokenId at the index eg.

Balance of NFT is 3 tokens, check tokenOfOwnerByIndex for 0,1,2 ->

0 -> 2556 1 -> 3456 2 -> 4431

Then we have all the TokenIds owned by the wallet without needing to trawl the event list, in only 1 extra call.

JamesSmartCell avatar Apr 15 '22 23:04 JamesSmartCell

Note that, we still have to trawl the event list because we want the transfer events (provides better support for chains that don't have etherscan support, and we might in the future be looking for events that Etherscan etc don't report in their APIs).

JamesSmartCell avatar May 20 '22 00:05 JamesSmartCell

This is going to be an addition.

Suggested approach:

  • create new ERC721_ENUMERABLE contract type to ContractType.
  • Detect that new contract type (interface) in determineCommonType().
  • Ensure you add the new contract type to all places where case ERC721: is used.
  • In the updateBalance() method in class ERC721Token call the ethereum function uint256 tokenOfOwnerByIndex({wallet address}, index) something like this:
for (int i = 0; i < balance.intValue(); i++)
{
    tokenIds.add (tokenOfOwnerByIndex(getWallet(), i));
}

updateRealmBalance(realm, tokenIds)

Note that this ethereum function prototype looks like this: tokenOfOwnerByIndex(address,uint256)

see Sourcecode for contract extension

Let me know if you need any help to make the function call prototype, for reference see the ownerOf definition in the ERC721Token class, or the balanceOfBatch call in ERC1155Token

JamesSmartCell avatar May 20 '22 00:05 JamesSmartCell