coinmarketcap-api
Version:
CoinMarketCap API wrapper for node
229 lines (200 loc) • 8.26 kB
JavaScript
const fetch = require('node-fetch')
const qs = require('qs')
const BASE_URL = 'https://pro-api.coinmarketcap.com'
class CoinMarketCap {
/**
*
* @param {String} apiKey API key for accessing the CoinMarketCap API
* @param {Object=} Options Options for the CoinMarketCap instance
* @param {String=} options.version Version of API. Defaults to 'v2'
* @param {Function=} options.fetcher fetch function to use. Defaults to node-fetch
* @param {Object=} options.config = Configuration for fetch request
*
*/
constructor (apiKey, { version = 'v1', fetcher = fetch, config = {} } = {}) {
this.apiKey = apiKey
this.config = Object.assign({}, {
method: 'GET',
headers: {
'X-CMC_PRO_API_KEY': this.apiKey,
Accept: 'application/json',
'Accept-Charset': 'utf-8',
'Accept-Encoding': 'deflate, gzip'
}
}, config)
this.fetcher = fetcher
this.url = `${BASE_URL}/${version}`
}
/**
* Get a paginated list of all cryptocurrencies by CoinMarketCap ID.
*
* @param {Object=} options Options for the request:
* @param {String=} [options.listingStatus="active"] active or inactive coins
* @param {Number|String=} [options.start=1] Return results from rank start and above
* @param {Number|String=} options.limit Only returns limit number of results
* @param {String[]|String=} options.symbol Comma separated list of symbols, will ignore the other options
* @param {String=} [options.sort="id"] Sort results by the options at https://coinmarketcap.com/api/documentation/v1/#operation/getV1CryptocurrencyMap
*
* @example
* const client = new CoinMarketCap('api key')
* client.getIdMap().then(console.log).catch(console.error)
* client.getIdMap({listingStatus: 'inactive', limit: 10}).then(console.log).catch(console.error)
* client.getIdMap({symbol: 'BTC,ETH'}).then(console.log).catch(console.error)
* client.getIdMap({symbol: ['BTC', 'ETH']}).then(console.log).catch(console.error)
* client.getIdMap({sort: 'cmc_rank'}).then(console.log).catch(console.error)
*/
getIdMap (args = {}) {
let { listingStatus, start, limit, symbol, sort } = args
if (symbol instanceof Array) {
symbol = symbol.join(',')
}
return createRequest({
fetcher: this.fetcher,
url: `${this.url}/cryptocurrency/map`,
config: this.config,
query: { listing_status: listingStatus, start, limit, symbol, sort }
})
}
/**
* Get static metadata for one or more cryptocurrencies.
* Either id or symbol is required, but passing in both is not allowed.
*
* @param {Object=} options Options for the request:
* @param {Array|String|Number=} options.id One or more comma separated cryptocurrency IDs
* @param {String[]|String} options.symbol One or more comma separated cryptocurrency symbols
*
* @example
* const client = new CoinMarketCap('api key')
* client.getMetadata({id: '1'}).then(console.log).catch(console.error)
* client.getMetadata({id: [1, 2]}).then(console.log).catch(console.error)
* client.getMetadata({symbol: 'BTC,ETH'}).then(console.log).catch(console.error)
* client.getMetadata({symbol: ['BTC', 'ETH']}).then(console.log).catch(console.error)
*/
getMetadata (args = {}) {
return createRequest({
fetcher: this.fetcher,
url: `${this.url}/cryptocurrency/info`,
config: this.config,
query: sanitizeIdAndSymbol(args.id, args.symbol)
})
}
/**
* Get information on all tickers.
* Start and limit options can only be used when currency or ID is not given.
* Currency and ID cannot be passed in at the same time.
*
* @param {Object=} options Options for the request
* @param {Number|String=} [options.start=1] Return results from rank start and above
* @param {Number|String=} [options.limit=100] Only returns limit number of results [1..5000]
* @param {String[]|String=} [options.convert="USD"] Return info in terms of another currency
* @param {String=} [options.sort="market_cap"] Sort results by the options at https://pro.coinmarketcap.com/api/v1#operation/getV1CryptocurrencyListingsLatest
* @param {String=} options.sortDir Direction in which to order cryptocurrencies ("asc" | "desc")
* @param {String=} [options.cryptocurrencyType="all"] Type of cryptocurrency to include ("all" | "coins" | "tokens")
*
* @example
* const client = new CoinMarketCap('api key')
* client.getTickers({limit: 3}).then(console.log).catch(console.error)
* client.getTickers({convert: 'EUR'}).then(console.log).catch(console.error)
* client.getTickers({start: 0, limit: 5}).then(console.log).catch(console.error)
* client.getTickers({sort: 'name'}).then(console.log).catch(console.error)
*/
getTickers (args = {}) {
let { start, limit, convert, sort, sortDir, cryptocurrencyType } = args
// eslint-disable-next-line
if (start && (limit == 0)) {
throw new Error('Start and limit = 0 cannot be passed in at the same time.')
}
// eslint-disable-next-line
if (limit == 0) {
limit = 5000
}
if (convert && convert instanceof Array) {
convert = convert.join(',')
}
return createRequest({
fetcher: this.fetcher,
url: `${this.url}/cryptocurrency/listings/latest`,
config: this.config,
query: { start, limit, convert, sort, sort_dir: sortDir, cryptocurrency_type: cryptocurrencyType }
})
}
/**
* Get latest market quote for 1 or more cryptocurrencies.
*
* @param {Object=} options Options for the request:
* @param {Array|String|Number=} options.id One or more comma separated cryptocurrency IDs
* @param {String[]|String=} options.symbol One or more comma separated cryptocurrency symbols
* @param {String[]|String=} [options.convert="USD"] Return quotes in terms of another currency
*
* @example
* const client = new CoinMarketCap('api key')
* client.getQuotes({id: '1'}).then(console.log).catch(console.error)
* client.getQuotes({id: [1, 2], convert: 'USD,EUR'}).then(console.log).catch(console.error)
* client.getQuotes({symbol: 'BTC,ETH'}).then(console.log).catch(console.error)
* client.getQuotes({symbol: ['BTC', 'ETH']}).then(console.log).catch(console.error)
*/
getQuotes (args = {}) {
let convert = args.convert
const { id, symbol } = sanitizeIdAndSymbol(args.id, args.symbol)
if (convert instanceof Array) {
convert = convert.join(',')
}
return createRequest({
fetcher: this.fetcher,
url: `${this.url}/cryptocurrency/quotes/latest`,
config: this.config,
query: { id, symbol, convert }
})
}
/**
* Get global information
*
* @param {Object|String[]|String=} options Options for the request:
* @param {String[]|String=} [options.convert="USD"] Return quotes in terms of another currency
*
* @example
* const client = new CoinMarketCap()
* client.getGlobal('GBP').then(console.log).catch(console.error)
* client.getGlobal({convert: 'GBP'}).then(console.log).catch(console.error)
*/
getGlobal (convert) {
if (typeof convert === 'string') {
convert = { convert: convert.toUpperCase() }
}
if (convert instanceof Array) {
convert = { convert: convert.map(currency => currency.toUpperCase()) }
}
if (convert && convert.convert instanceof Array) {
convert.convert = convert.convert.join(',')
}
return createRequest({
fetcher: this.fetcher,
url: `${this.url}/global-metrics/quotes/latest`,
config: this.config,
query: convert
})
}
}
const sanitizeIdAndSymbol = (id, symbol) => {
if (id && symbol) {
throw new Error('ID and symbol cannot be passed in at the same time.')
}
if (!id && !symbol) {
throw new Error('Either ID or symbol is required to be passed in.')
}
if (id instanceof Array) {
id = id.join(',')
}
if (symbol instanceof Array) {
symbol = symbol.join(',')
}
return { id, symbol }
}
const createRequest = (args = {}) => {
const { url, config, query, fetcher } = args
return fetcher(`${url}${query ? `?${qs.stringify(query)}` : ''}`, config).then(res =>
res.json()
)
}
module.exports = CoinMarketCap