1

I'm using GraphQL/express/express-graphql/axios to retrieve specific coin data from the CryptoCompare API.

I have two endpoints:

1) https://min-api.cryptocompare.com/data/pricemultifull?fsyms=BTC,ETH,LTC,BCH,NEO,ETC,XMR&tsyms=USD

From endpoint 1, I want to retrieve the following in USD for 8 coins:
  - FROMSYMBOL, CHANGEPCT24HOUR, PRICE, MKTCAP, TOTALVOLUME24HTO

2) https://min-api.cryptocompare.com/data/coin/generalinfo?fsyms=BTC&tsym=USD

From endpoint 2, I want to retrieve the following just for Bitcoin/BTC:
  - Id, FullName, ImageUrl

I have setup my backend server with two files, as well as testing queries using graphiql.

File 1 - server.js

const express = require("express")
const graphqlHTTP = require("express-graphql")
const cors = require("cors")
const schema = require("./schema")

const app = express()

app.use(cors())

app.use(
  "/graphql",
  graphqlHTTP({
    schema,
    graphiql: true
  })
)

const PORT = process.env.PORT || 4000

app.listen(PORT, console.log(`✅  Listening to port ${PORT}`))

File 2 - schema.js

const {
  GraphQLObjectType,
  GraphQLList,
  GraphQLID,
  GraphQLInt,
  GraphQLString,
  GraphQLSchema
} = require("graphql")
const axios = require("axios")

const CoinDataType = new GraphQLObjectType({
  name: "CoinData",
  fields: () => ({
    FROMSYMBOL: { type: GraphQLString },
    CHANGEPCT24HOUR: { type: GraphQLInt },
    PRICE: { type: GraphQLInt },
    MKTCAP: { type: GraphQLInt },
    TOTALVOLUME24HTO: { type: GraphQLInt }
  })
})

const CoinInfoType = new GraphQLObjectType({
  name: "CoinInfo",
  fields: () => ({
    Id: { type: GraphQLID },
    FullName: { type: GraphQLString },
    ImageUrl: { type: GraphQLString }
  })
})

const Query = new GraphQLObjectType({
  name: "Query",
  fields: {
    CoinData: {
      type: new GraphQLList(CoinDataType),
      resolve(parent, args) {
        return axios
          .get(
            "https://min-api.cryptocompare.com/data/pricemultifull?fsyms=BTC,ETH,LTC,BCH,NEO,ETC,XMR&tsyms=USD"
          )
          .then(res => res.data)
      }
    },
    CoinInfo: {
      type: new GraphQLList(CoinInfoType),
      resolve(parent, args) {
        return axios
          .get(
            "https://min-api.cryptocompare.com/data/coin/generalinfo?fsyms=BTC&tsym=USD"
          )
          .then(res => res.data)
      }
    }
  }
})

module.exports = new GraphQLSchema({ query: Query })

When I use graphiql to test my queries with this:

{
  CoinData {
    FROMSYMBOL
  }
  CoinInfo {
    Id
  }
}

...I get this error:

{
  "errors": [
    {
      "message": "Expected Iterable, but did not find one for field Query.CoinInfo.",
      "locations": [
        {
          "line": 5,
          "column": 3
        }
      ],
      "path": [
        "CoinInfo"
      ]
    },
    {
      "message": "Expected Iterable, but did not find one for field Query.CoinData.",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "CoinData"
      ]
    }
  ],
  "data": {
    "CoinData": null,
    "CoinInfo": null
  }
}

How do I get around this error? Thanks.

  • Duplicate of [GraphQL Expected Iterable, but did not find one for field xxx.yyy](https://stackoverflow.com/questions/46513476/graphql-expected-iterable-but-did-not-find-one-for-field-xxx-yyy). What's returned in your resolver needs to match the type for the field. – Daniel Rearden Mar 22 '19 at 17:36
  • Ah, I see, that makes sense. For example, in CoinInfoType, I have three fields I want to retrieve: Id/FullName/ImageUrl, but from the endpoint https://min-api.cryptocompare.com/data/coin/generalinfo?fsyms=BTC&tsym=USD, those fields are nested within the Data array -> CoinData object. How can I rewrite my schema to access the data? Thanks. –  Mar 22 '19 at 17:44
  • No need to rewrite your schema -- just manipulate the data returned by the API before returning it inside your resolver – Daniel Rearden Mar 22 '19 at 17:55
  • CoinInfo: { type: new GraphQLList(CoinInfoType), resolve(parent, args) { return axios .get( "https://min-api.cryptocompare.com/data/coin/generalinfo?fsyms=BTC&tsym=USD" ) .then(res => res.data) .then(res => res.Data.map(coin => { return { Id: coin.CoinInfo.Id, FullName: coin.CoinInfo.FullName, ImageUrl: coin.CoinInfo.ImageUrl } }) ) } } This worked, but is there a more concise way? –  Mar 22 '19 at 18:16

0 Answers0