graphprotocol / graph-client

The Graph library for building GraphQL-based dapps in a decentralized way.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Question: query same Entity in two different sources?

cazala opened this issue · comments

If I have two exact subgraphs deployed on different chains, is it possible to query a single entity that returns a list of results from both sources?

The two sources have the same schema for the Entity, but the records don't share a unique identifier.

For examle, I have an entity Token on both subgraphs:

type Token @entity {
  id: ID! #address
  name: String
}

And this query when executed on each subgraph:

query {
  tokens {
    id
    name
  }
}

Return the following on the Ethereum subgraph:

{
  "tokens": [
    {
      "id": "0x1",
      "name": "FOO"
    }
  ]
}

And this on the Polygon one:

{
  "tokens": [
    {
      "id": "0x2",
      "name": "BAR"
    }
  ]
}

And I want to be able to run that same query and get this result:

{
  "tokens": [
    {
      "id": "0x1",
      "name": "FOO"
    },
    {
      "id": "0x2",
      "name": "BAR"
    }
  ]
}

And be able to apply sorting/filtering on top of it. Is that possible with the current state of the graph-client?

I tried this already using some of our Ethereum/Polygon subgraphs but I'm only getting results from the first source and the other one is completely ignored. If I comment the first one then I start getting the results from the other. I don't know if I'm missing some configuration to tell the graph mesh to treat both entities as the same (even tho they are already called the same).

It sounds like the cross-chain feature (see https://github.com/graphprotocol/graph-client/tree/main/examples/cross-chain-sdk), but with different sources?
I mean, it is possible to merge responses easily with Graph Client, and it is possible to orchestrate calls to 2 different Subgraphs, so I think it might be possible with some adjustments.
@ardatan what do you think?

You can overwrite tokens as an additional resolver;

export const resolvers: Resolvers = {
   Query: {
      async tokens(root, args, context, info) {
         const tokensNonFlat = await Promise.all([
           context.Ethereum.Query.tokens({ root, args, context, info }),
           context.Polygon.Query.tokens({ root, args, context, info })
         ]);
         return tokenNonFlat.flat();
      }
   }
}

You can overwrite tokens as an additional resolver;

export const resolvers: Resolvers = {
   Query: {
      async tokens(root, args, context, info) {
         const tokensNonFlat = await Promise.all([
           context.Ethereum.Query.tokens({ root, args, context, info }),
           context.Polygon.Query.tokens({ root, args, context, info })
         ]);
         return tokenNonFlat.flat();
      }
   }
}

Thanks for the resposne @dotansimha @ardatan. Would that work for sorting/pagintation tho? Or would the results be ordered as [...ethereum, ...polygon]? Sorting/filtering/pagination of the results is key for our use case.

For example, if I'm fetching NFTs in a marketplace and sorting the results by price, and the Ethereum ones are an order of magnitude more expensive than the Polygon ones, if the results are always [...ethereum, ...polygon] even if I orderBy: price (from cheaper to more expensive) I will always see the Ethereum results in the first page even tho the Polygon results should show up first.

const [ethResults, polygonResults] = await Promise.all([
           context.Ethereum.Query.tokens({ root, args, context, info }),
           context.Polygon.Query.tokens({ root, args, context, info })
         ]);
         return [...ethResults, ...polygonResults];
      }

You can do this to change priority (it is just JavaScript, nothing with Graph Client).
I don't think Graph Client can handle the pagination in total results but send the same arguments to them.
@dotansimha

You can do this to change priority (it is just JavaScript, nothing with Graph Client). I don't think Graph Client can handle the pagination in total results but send the same arguments to them. @dotansimha

Yeah, I agree that this is a tricky one to handle with a magic config...