cmc-api
Version:
CoinMarketCap RESTful API Wrapper
249 lines • 12.9 kB
JavaScript
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Client = void 0;
const cmc_error_code_enum_1 = require("../enums/cmc-error-code.enum");
const cmc_apikey_disabled_error_1 = require("../errors/cmc-apikey-disabled.error");
const cmc_apikey_required_error_1 = require("../errors/cmc-apikey-required.error");
const cmc_invalid_error_1 = require("../errors/cmc-invalid.error");
const cmc_missing_error_1 = require("../errors/cmc-missing.error");
const cmc_payment_expired_error_1 = require("../errors/cmc-payment-expired.error");
const cmc_payment_required_error_1 = require("../errors/cmc-payment-required.error");
const cmc_plan_unauthorize_error_1 = require("../errors/cmc-plan-unauthorize.error");
const cmc_rate_limit_daily_error_1 = require("../errors/cmc-rate-limit-daily.error");
const cmc_rate_limit_ip_error_1 = require("../errors/cmc-rate-limit-ip.error");
const cmc_rate_limit_minute_error_1 = require("../errors/cmc-rate-limit-minute.error");
const cmc_rate_limit_monthly_error_1 = require("../errors/cmc-rate-limit-monthly.error");
const cmc_request_error_1 = require("../errors/cmc-request.error");
const decorators_util_1 = require("../utils/decorators.util");
/**
* The `Client` class provides methods to interact with the CoinMarketCap API.
* It allows sending HTTP GET requests, setting API keys, and handling errors.
*
* @remarks
* This class includes methods for generating URIs with query parameters,
* generating HTTP headers, and handling various error codes returned by the API.
*
* @example
* ```typescript
* import { CoinMarketCapApi } from "..";
*
* const apikey = process.env.COINMARKETCAP_APIKEY;
* const cmc = new CoinMarketCapApi(apikey);
*
* const data = await cmc.client.req('/v1/cryptocurrency/map');
* console.log(data);
* ```
*/
class Client {
/**
* Initializes a new instance of the `Client` class.
* The constructor sets the base URL to the Pro API by default.
*/
constructor() {
if (!this.baseURL)
this.baseURL = Client.BaseURL.Pro;
}
/**
* Send an HTTP GET request to the specified endpoint with optional query parameters and headers.
*
* @template TData - The expected type of the response data.
* @template TQuery - The type of the query parameters, defaults to `Record<string, string | number | (string | number)[] | boolean>`.
* @param {string} endpoint - The API endpoint to send the request to.
* @param {TQuery} [query] - Optional query parameters to include in the request.
* @param {Record<string, string>} [headers] - Optional headers to include in the request.
* @returns {Promise<TData>} - A promise that resolves to the response data of type `TData`.
* @throws {CmcErrorClass} Will throw an error if the response status indicates an error.
*/
async req(endpoint, query, headers) {
var _a, _b;
const uri = this.genUri(endpoint, query);
const requestInit = { method: "GET", headers: this.genHeaders(headers) };
const request = await fetch(uri, requestInit);
const result = await request.json();
const status = ((_a = result === null || result === void 0 ? void 0 : result.data) === null || _a === void 0 ? void 0 : _a.status) || (result === null || result === void 0 ? void 0 : result.status);
const data = (((_b = result === null || result === void 0 ? void 0 : result.data) === null || _b === void 0 ? void 0 : _b.data) || (result === null || result === void 0 ? void 0 : result.data));
this.status = status;
if (this.onError && (!status || (status === null || status === void 0 ? void 0 : status.error_code) > 0))
this.onError(uri, result);
if ((status === null || status === void 0 ? void 0 : status.error_code) > 0)
throw this.error(data);
return (data !== null && data !== void 0 ? data : result);
}
/**
* Set the API key for the client.
*
* @param apiKey - The API key to be set.
* @returns The client instance with the API key set.
* @example
* ```typescript
* const apikey = process.env.COINMARKETCAP_APIKEY;
* const cmc = new CoinMarketCapApi(apikey);
* cmc.client.setApiKey('dfa3195f-f1d4-f1c1-a1fa-83461b5f42eb');
* ```
*/
setApiKey(apiKey) {
this.apikey = apiKey;
return this;
}
/**
* Set the base URL for the client.
*
* @param {string} baseUrl - The base URL to be set.
* @returns The client instance with the base URL set.
* @example
* ```typescript
* const apikey = process.env.COINMARKETCAP_APIKEY;
* const cmc = new CoinMarketCapApi(apikey);
* cmc.client.setBaseUrl('https://sandbox-api.coinmarketcap.com');
* ```
*/
setBaseUrl(baseUrl) {
this.baseURL = baseUrl;
return this;
}
/**
* Converts an array of strings into a single comma-separated string.
* If the input is already a string, it returns the input as is.
*
* @template TValue - The type of the input value, defaults to `string | number | (string | number)[]`.
* @param {TValue} value - The input which can be either a string or an array of strings.
* @returns A comma-separated string if the input is an array, otherwise the input string.
*/
commaSeparate(value) {
return Array.isArray(value) ? value.join(",") : String(value);
}
/**
* Set up the client to use the CoinMarketCap API sandbox environment.
* This method sets the API key to the sandbox key and the base URL to the sandbox URL.
* @returns The client instance with the sandbox environment set.
*/
sandbox() {
this.apikey = Client.SandboxApikey;
this.baseURL = Client.BaseURL.Sandbox;
return this;
}
/**
* Generates a complete URI with query parameters.
*
* @template TQuery - The type of the query parameters, defaults to `Record<string, string | number | (string | number)[] | boolean>`.
* @param {string} endpoint - The endpoint to append to the base URL.
* @param {TQuery} [query] - An optional object containing query parameters as key-value pairs.
* @returns {URL} - The generated URL with the provided endpoint and query parameters.
*/
genUri(endpoint, query) {
const uri = new URL(endpoint, this.baseURL);
if (query) {
for (const key of Object.keys(query))
if (query[key] && query[key] !== "undefined" && query[key] !== "null") {
if (Array.isArray(query[key])) {
uri.searchParams.append(key, this.commaSeparate(query[key]));
}
else {
uri.searchParams.append(key, String(query === null || query === void 0 ? void 0 : query[key]));
}
}
}
return uri;
}
/**
* Generates HTTP headers for the API request.
*
* @param additionHeaders - An object containing additional headers to be included in the request.
* @returns A Headers object with the API key and any additional headers appended.
*
* @see {@link Headers}
*/
genHeaders(additionHeaders) {
const headers = new Headers();
headers.append("X-CMC_PRO_API_KEY", this.apikey);
if (additionHeaders)
for (const key of Object.keys(additionHeaders))
headers.append(key, additionHeaders[key]);
return headers;
}
/**
* Handles errors based on the provided {@link CmcStatusResponse} and returns an appropriate {@link CmcErrorClass} instance.
*
* @param {CmcStatusResponse} status - The status object containing the error code and other relevant information.
* @param {any} data - Optional additional data related to the error.
* @returns An instance of a class extending {@link CmcErrorClass} that corresponds to the specific error code.
*
* The method maps the following error codes to their respective error classes:
* - {@link CmcErrorCode.ApikeyInvalid} for {@link CmcInvalidError}
* - {@link CmcErrorCode.ApikeyMissing} for {@link CmcMissingError}
* - {@link CmcErrorCode.ApikeyPlanRequiresPayment} for {@link CmcPaymentRequiredError}
* - {@link CmcErrorCode.ApikeyPlanPaymentExpired} for {@link CmcPaymentExpiredError}
* - {@link CmcErrorCode.ApikeyRequired} for {@link CmcApikeyRequiredError}
* - {@link CmcErrorCode.ApikeyPlanNotAuthorized} for {@link CmcPlanUnauthorizeError}
* - {@link CmcErrorCode.ApikeyDisable} for {@link CmcApikeyDisabledError}
* - {@link CmcErrorCode.ApikeyPlanMinuteRateLimitReached} for {@link CmcMinuteRateLimitError}
* - {@link CmcErrorCode.ApikeyPlanDailyRateLimitReached} for {@link CmcDailyRateLimitError}
* - {@link CmcErrorCode.ApikeyPlanMonthlyRateLimitReached} for {@link CmcMonthlyRateLimitError}
* - {@link CmcErrorCode.IpRateLimitReached} for {@link CmcIpRateLimitError}
*
* If the error code does not match any of the above, a generic {@link CmcRequestError} is returned.
*/
error(data) {
var _a;
switch ((_a = this.status) === null || _a === void 0 ? void 0 : _a.error_code) {
case cmc_error_code_enum_1.CmcErrorCode.ApikeyInvalid:
return new cmc_invalid_error_1.CmcInvalidError(this.status, data);
case cmc_error_code_enum_1.CmcErrorCode.ApikeyMissing:
return new cmc_missing_error_1.CmcMissingError(this.status, data);
case cmc_error_code_enum_1.CmcErrorCode.ApikeyPlanRequiresPayment:
return new cmc_payment_required_error_1.CmcPaymentRequiredError(this.status, data);
case cmc_error_code_enum_1.CmcErrorCode.ApikeyPlanPaymentExpired:
return new cmc_payment_expired_error_1.CmcPaymentExpiredError(this.status, data);
case cmc_error_code_enum_1.CmcErrorCode.ApikeyRequired:
return new cmc_apikey_required_error_1.CmcApikeyRequiredError(this.status, data);
case cmc_error_code_enum_1.CmcErrorCode.ApikeyPlanNotAuthorized:
return new cmc_plan_unauthorize_error_1.CmcPlanUnauthorizeError(this.status, data);
case cmc_error_code_enum_1.CmcErrorCode.ApikeyDisable:
return new cmc_apikey_disabled_error_1.CmcApikeyDisabledError(this.status, data);
case cmc_error_code_enum_1.CmcErrorCode.ApikeyPlanMinuteRateLimitReached:
return new cmc_rate_limit_minute_error_1.CmcMinuteRateLimitError(this.status, data);
case cmc_error_code_enum_1.CmcErrorCode.ApikeyPlanDailyRateLimitReached:
return new cmc_rate_limit_daily_error_1.CmcDailyRateLimitError(this.status, data);
case cmc_error_code_enum_1.CmcErrorCode.ApikeyPlanMonthlyRateLimitReached:
return new cmc_rate_limit_monthly_error_1.CmcMonthlyRateLimitError(this.status, data);
case cmc_error_code_enum_1.CmcErrorCode.IpRateLimitReached:
return new cmc_rate_limit_ip_error_1.CmcIpRateLimitError(this.status, data);
}
return new cmc_request_error_1.CmcRequestError(this.status, data);
}
}
exports.Client = Client;
/**
* The API key used for accessing the sandbox environment of the service.
* This key is intended for testing purposes and should not be used in production.
* @internal @private
* @constant {string}
*/
Client.SandboxApikey = "b54bcf4d-1bca-4e8e-9a24-22ff2c3d462c";
/**
* A collection of base URLs for the CoinMarketCap API.
* @readonly @internal @private
* @see {@link https://pro.coinmarketcap.com/api/v1#section/Quick-Start-Guide | Quick Start Guide}
*/
Client.BaseURL = {
Sandbox: "https://sandbox-api.coinmarketcap.com",
Pro: "https://pro-api.coinmarketcap.com",
};
__decorate([
(0, decorators_util_1.Enumerable)(false),
__metadata("design:type", String)
], Client.prototype, "baseURL", void 0);
__decorate([
(0, decorators_util_1.Enumerable)(false),
__metadata("design:type", String)
], Client.prototype, "apikey", void 0);
//# sourceMappingURL=client.js.map