machinebox / graphql

Simple low-level GraphQL HTTP client for Go
https://blog.machinebox.io/a-graphql-client-library-for-go-5bffd0455878
Apache License 2.0
933 stars 217 forks source link

bug: parse response from graph query failed(some success, some failed) and no error returns #64

Closed huahuayu closed 3 years ago

huahuayu commented 3 years ago

question

when execute below query in thegraph for uniswap online explorer

all of them have result

but when invoke it from program, only first query (tokenDaydata query) have result, the second & thrid failed parse

program api endpoint: https://api.thegraph.com/subgraphs/name/uniswap/uniswap-v2

program code: https://github.com/huahuayu/graphql commitId: 1c05c8d0ac16f934d431b319f9b9ac666d1d90f3

the three queries

tokenDaydata query

        {
         tokenDayDatas(orderBy: date, orderDirection: asc,
          where: {
            token: "0x6b175474e89094c44da98b954eedeac495271d0f"
          }
         ) {
            id
            date
            priceUSD
            totalLiquidityToken
            totalLiquidityUSD
            totalLiquidityETH
            dailyVolumeETH
            dailyVolumeToken
            dailyVolumeUSD
             }
            }

global stat query

 {
 uniswapFactory(id: "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f"){
   totalVolumeUSD
   totalLiquidityUSD
   txCount
 }
}

pair query data

{
 pair(id: "0xa478c2975ab1ea89e8196811f51a7b7ade33eb11"){
     token0 {
       id
       symbol
       name
       derivedETH
     }
     token1 {
       id
       symbol
       name
       derivedETH
     }
     reserve0
     reserve1
     reserveUSD
     trackedReserveETH
     token0Price
     token1Price
     volumeUSD
     txCount
 }
}

output of program

{0 0 0 1589328000 0x6b175474e89094c44da98b954eedeac495271d0f-18395 0 0 220 0} # first query
&{{{   {   }  {   }    }}} # second query
&{{{  }}} # third query

root cause

The parser of response have problem, the query is success but the second & third response is not parsed.

The res is not parsed correctly when it is a struct.

    if err := graphqlClient.Run(context.Background(), graphqlRequest, &res); err != nil {
        panic(err.Error())
    }

If it's a interface{} passed in as response, then it will be ok, but it's in map[string]interface{} format.

huahuayu commented 3 years ago

I think I made a mistake

thegraph query

https://thegraph.com/explorer/subgraph/uniswap/uniswap-v2

{
 pair(id: "0xa478c2975ab1ea89e8196811f51a7b7ade33eb11"){
     token0 {
       id
       symbol
       name
       derivedETH
     }
     token1 {
       id
       symbol
       name
       derivedETH
     }
     reserve0
     reserve1
     reserveUSD
     trackedReserveETH
     token0Price
     token1Price
     volumeUSD
     txCount
 }
}

thegraph query return

{
  "data": {
    "pair": {
      "reserve0": "190651294.418853627152317556",
      "reserve1": "417043.184916624363019388",
      "reserveUSD": "383689046.4339356902012161557851996",
      "token0": {
        "derivedETH": "0.002187465792917179892754396137996332",
        "id": "0x6b175474e89094c44da98b954eedeac495271d0f",
        "name": "Dai Stablecoin",
        "symbol": "DAI"
      },
      "token0Price": "457.1500058368506851026842115431232",
      "token1": {
        "derivedETH": "1",
        "id": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
        "name": "Wrapped Ether",
        "symbol": "WETH"
      },
      "token1Price": "0.002187465792917179892754396137996332",
      "trackedReserveETH": "834086.3698332487260387760000000001",
      "txCount": "466788",
      "volumeUSD": "2214704218.33944568058873488229681"
    }
  }
}

map it to go struct

thru this site, json to go struct: https://mholt.github.io/json-to-go/

type PairData struct {
    Data struct {
        Pair struct {
            Reserve0   string `json:"reserve0"`
            Reserve1   string `json:"reserve1"`
            ReserveUSD string `json:"reserveUSD"`
            Token0     struct {
                DerivedETH string `json:"derivedETH"`
                ID         string `json:"id"`
                Name       string `json:"name"`
                Symbol     string `json:"symbol"`
            } `json:"token0"`
            Token0Price string `json:"token0Price"`
            Token1      struct {
                DerivedETH string `json:"derivedETH"`
                ID         string `json:"id"`
                Name       string `json:"name"`
                Symbol     string `json:"symbol"`
            } `json:"token1"`
            Token1Price       string `json:"token1Price"`
            TrackedReserveETH string `json:"trackedReserveETH"`
            TxCount           string `json:"txCount"`
            VolumeUSD         string `json:"volumeUSD"`
        } `json:"pair"`
    } `json:"data"`
}

actually the struct should be

the data layer is the actual data!

type PairData struct {
    Pair struct {
        Reserve0   string `json:"reserve0"`
        Reserve1   string `json:"reserve1"`
        ReserveUSD string `json:"reserveUSD"`
        Token0     struct {
            DerivedETH string `json:"derivedETH"`
            ID         string `json:"id"`
            Name       string `json:"name"`
            Symbol     string `json:"symbol"`
        } `json:"token0"`
        Token0Price string `json:"token0Price"`
        Token1      struct {
            DerivedETH string `json:"derivedETH"`
            ID         string `json:"id"`
            Name       string `json:"name"`
            Symbol     string `json:"symbol"`
        } `json:"token1"`
        Token1Price       string `json:"token1Price"`
        TrackedReserveETH string `json:"trackedReserveETH"`
        TxCount           string `json:"txCount"`
        VolumeUSD         string `json:"volumeUSD"`
    } `json:"pair"`
}