ourzora / zdk

MIT License
107 stars 42 forks source link

[Feature Request] Enable pagination for querying tokens by owner #62

Open jf2978 opened 2 years ago

jf2978 commented 2 years ago

Background & Context

Hey Zora peeps πŸ‘‹ , I have a question/feature request about tokens and pagination.

I want to surface token collector data for a given set of collectionAddresses. Using the tokens query, I can definitely fetch all these tokens, further filter the results (e.g. by specifying ownerAdddresses) or limit the page size to some number less than 500, but paginating through these results in a way that gives complete data for each owner within a page has proved to be trickier than I expected.

Expected Behavior

Be able to query tokens with some limit and sort/group results by owner addresses. The endCursor returned could then be used to fetch the next set of owned tokens when the client needs it.

Actual Behavior

We have no guarantee that tokens for the same owner don't exist across page breaks. e.g.

  query MyQuery {
     tokens(where: {collectionAddresses: ["0x29d8C82ADbA12c822c37090FC1Cf7F430bbC1A60"]}, pagination: {limit: 50}) {
      nodes {
        token {
          tokenId
          owner
        }
      }
      pageInfo {
        endCursor
        hasNextPage
        limit
      }
  }

One would need to paginate through the resulting set and group tokens manually to confidently return token data for a given owner. Also, the main workarounds I can think of kind of defeat the purpose of cursor pagination 😒 (see below).

Potential Workarounds

Option A: Don't paginate on the graphQL level -- i.e. exhaustively query for all tokens & map owners to their NFTs on the client-side as mentioned above.

Works, but wouldn't scale well for collections with lots of holders/tokens.

Option B: Get all owner count data first (e.g using ownersByCount), for most cases query tokens with a subset of ownerAddresses that we can be sure are less than our limit and for cases where a single owner has >500 tokens owned, paginate through all of those results before returning our result.

Seems better, but I think sort of defeats the purpose of cursor pagination. Rather than giving the client the chance to fetch more data when it needs it via the endCursor, this kind of batches the owners we query with instead πŸ€”


Am I missing something? Would it be possible to incorporate this sort of behavior in the future? I'm all ears!

iainnash commented 2 years ago

Option B seems reasonable at this point to me (Better perf than #a). I am forwarding this to the indexer team :).