Skip to content

Commit 0ea9f00

Browse files
author
Sander
committed
Migrated to typescript
1 parent abd678a commit 0ea9f00

26 files changed

+2351
-1285
lines changed

README.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ A Node.js wrapper for the CoinCodex API with no dependencies.
1010

1111
## • Installation
1212

13-
Latest version: 1.0.0
13+
Latest version: 2.0.0
1414

15-
`npm install coincodex-api`
15+
`npm install coincodex-api-v2`
1616

1717
## • CoinCodex API Documentation
1818

@@ -49,9 +49,9 @@ All calls are returned in the following format:
4949

5050
The CoinCodexClient splits up the currently available calls outline in the official CoinCodex API documentation into two parts. (Including `firstPageHistory()`)
5151

52-
| Namespace | Usage | Description |
53-
| --- | --- | --- |
54-
`coins` | `CoinCodexClient.coins[...]` | Calls related to coins
52+
| Namespace | Usage | Description |
53+
| --------- | ---------------------------- | ---------------------- |
54+
| `coins` | `CoinCodexClient.coins[...]` | Calls related to coins |
5555

5656
___
5757
### • First Page History

build/index.js

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
"use strict";
2+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3+
if (k2 === undefined) k2 = k;
4+
var desc = Object.getOwnPropertyDescriptor(m, k);
5+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6+
desc = { enumerable: true, get: function() { return m[k]; } };
7+
}
8+
Object.defineProperty(o, k2, desc);
9+
}) : (function(o, m, k, k2) {
10+
if (k2 === undefined) k2 = k;
11+
o[k2] = m[k];
12+
}));
13+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14+
Object.defineProperty(o, "default", { enumerable: true, value: v });
15+
}) : function(o, v) {
16+
o["default"] = v;
17+
});
18+
var __importStar = (this && this.__importStar) || function (mod) {
19+
if (mod && mod.__esModule) return mod;
20+
var result = {};
21+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22+
__setModuleDefault(result, mod);
23+
return result;
24+
};
25+
module.exports = Promise.resolve().then(() => __importStar(require('./lib/CoinCodex')));

build/lib/CoinCodex.js

+170
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
"use strict";
2+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4+
return new (P || (P = Promise))(function (resolve, reject) {
5+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8+
step((generator = generator.apply(thisArg, _arguments || [])).next());
9+
});
10+
};
11+
var __importDefault = (this && this.__importDefault) || function (mod) {
12+
return (mod && mod.__esModule) ? mod : { "default": mod };
13+
};
14+
Object.defineProperty(exports, "__esModule", { value: true });
15+
exports.CoinCodex = void 0;
16+
const https_1 = __importDefault(require("https"));
17+
const utilities_1 = __importDefault(require("./helpers/utilities"));
18+
const constants_1 = __importDefault(require("./helpers/constants"));
19+
/**
20+
* @description A Node.js wrapper for the CoinCodex API with no dependencies. For more information, visit: https://coincodex.com/page/api/
21+
* @example
22+
* const CoinCodex = require('coincodex-api');
23+
* const CoinCodexClient = new CoinCodex();
24+
*/
25+
class CoinCodex {
26+
/** Returns historic data for coins needed to draw the graph on the frontpage */
27+
firstPageHistory(params) {
28+
return __awaiter(this, void 0, void 0, function* () {
29+
//Must be object
30+
if (!utilities_1.default.isObject(params))
31+
utilities_1.default._WARN_('Invalid parameter', 'params must be of type: Object');
32+
if (!params['days'])
33+
utilities_1.default._WARN_('Missing parameter', 'params must include `days` and be a string or number');
34+
if (!params['coins_limit'])
35+
utilities_1.default._WARN_('Missing parameter', 'params must include `coins_limit` and be a string or number');
36+
//If no 'samples', just set to default: 1
37+
if (utilities_1.default.isNumber(params['samples']))
38+
params['samples'] = `${params['samples']}`;
39+
if (!utilities_1.default.isString(params['samples']) || utilities_1.default.isStringEmpty(params['samples'])) {
40+
params['samples'] = 1;
41+
}
42+
//Get values
43+
const { days, samples, coins_limit } = params;
44+
const path = `/api/coincodex/get_firstpage_history/${days}/${samples}/${coins_limit}`;
45+
const options = this._buildRequestOptions(path);
46+
return this._request(options);
47+
});
48+
}
49+
;
50+
/** Calls related to coins */
51+
get coins() {
52+
return {
53+
/** Returns all coins on the platform with properties that are needed to display them on the frontpage */
54+
all: () => __awaiter(this, void 0, void 0, function* () {
55+
const path = `/apps/coincodex/cache/all_coins.json`;
56+
const options = this._buildRequestOptions(path);
57+
return this._request(options);
58+
}),
59+
/** Returns all properties for the coin needed to display the coin details page */
60+
fetch: (coinId) => __awaiter(this, void 0, void 0, function* () {
61+
//Must have coinId
62+
if (!utilities_1.default.isString(coinId) || utilities_1.default.isStringEmpty(coinId))
63+
utilities_1.default._WARN_('Invalid parameter', 'coinId must be of type: String and greater than 0 characters.');
64+
const path = `/api/coincodex/get_coin/${coinId}`;
65+
const options = this._buildRequestOptions(path);
66+
return this._request(options);
67+
}),
68+
/** Returns historical price data for a single coin */
69+
fetchHistory: (coinId, params) => __awaiter(this, void 0, void 0, function* () {
70+
//Must have coinId
71+
if (!utilities_1.default.isString(coinId) || utilities_1.default.isStringEmpty(coinId))
72+
utilities_1.default._WARN_('Invalid parameter', 'coinId must be of type: String and greater than 0 characters.');
73+
//Must be object
74+
if (!utilities_1.default.isObject(params))
75+
utilities_1.default._WARN_('Invalid parameter', 'params must be of type: Object');
76+
//If no params.start_date, params.end_date... Warn
77+
if (!utilities_1.default.isString(params['start_date']) || utilities_1.default.isStringEmpty(params['start_date']))
78+
utilities_1.default._WARN_('Missing parameter', 'params must include `start_date` and be a string in format: `YYYY-MM-DD`');
79+
if (!utilities_1.default.isString(params['end_date']) || utilities_1.default.isStringEmpty(params['end_date']))
80+
utilities_1.default._WARN_('Missing parameter', 'params must include `end_date` and be a string in format: `YYYY-MM-DD`');
81+
//If no 'samples', just set to default: 1
82+
if (utilities_1.default.isNumber(params['samples']))
83+
params['samples'] = `${params['samples']}`;
84+
if (!utilities_1.default.isString(params['samples']) || utilities_1.default.isStringEmpty(params['samples'])) {
85+
params['samples'] = 1;
86+
}
87+
//Get values
88+
const { start_date, end_date, samples } = params;
89+
const path = `/api/coincodex/get_coin_history/${coinId}/${start_date}/${end_date}/${samples}`;
90+
const options = this._buildRequestOptions(path);
91+
return this._request(options);
92+
}),
93+
/** Returns exchanges and markets for a coin */
94+
markets: (coinId) => __awaiter(this, void 0, void 0, function* () {
95+
//Must have coinId
96+
if (!utilities_1.default.isString(coinId) || utilities_1.default.isStringEmpty(coinId))
97+
utilities_1.default._WARN_('Invalid parameter', 'coinId must be of type: String and greater than 0 characters.');
98+
const path = `/api/exchange/get_markets_by_coin/${coinId}`;
99+
const options = this._buildRequestOptions(path);
100+
return this._request(options);
101+
}),
102+
/** Returns min and max ranges of given coinId(s) for 1 hour, 1 day, 7 day, 30 day, 90 day, 180 day, year to date, last 365 days and all time */
103+
ranges: (coinIds) => __awaiter(this, void 0, void 0, function* () {
104+
if (utilities_1.default.isString(coinIds) && utilities_1.default.isStringEmpty(coinIds))
105+
utilities_1.default._WARN_('Invalid parameter', 'coinId must be of type: String or Array and greater than 0 characters, items.');
106+
if (Array.isArray(coinIds)) {
107+
if (coinIds.length === 0)
108+
utilities_1.default._WARN_('Invalid parameter', 'coinId must be of type: String or Array and greater than 0 characters, items.');
109+
//If are arrays, convert to string
110+
coinIds = coinIds.join(',');
111+
}
112+
const path = `/api/coincodex/get_coin_ranges/${coinIds}`;
113+
const options = this._buildRequestOptions(path);
114+
return this._request(options);
115+
}),
116+
};
117+
}
118+
;
119+
/** Build options for https.request */
120+
_buildRequestOptions(path) {
121+
return {
122+
path,
123+
method: 'GET',
124+
host: constants_1.default.HOST,
125+
port: 443,
126+
};
127+
}
128+
;
129+
/** Perform https request */
130+
_request(options) {
131+
return new Promise((resolve, reject) => {
132+
//Perform request
133+
let req = https_1.default.request(options, (res) => {
134+
let body = [];
135+
//Set body on data
136+
res.on('data', (chunk) => {
137+
body.push(chunk);
138+
});
139+
//On end, end the Promise
140+
res.on('end', () => {
141+
try {
142+
body = Buffer.concat(body);
143+
body = body.toString();
144+
//Check if page is returned instead of JSON
145+
if (body.startsWith('<!DOCTYPE html>'))
146+
utilities_1.default._WARN_('Invalid request', 'There was a problem with your request. The parameter(s) you gave are missing or incorrect.');
147+
//Attempt to parse
148+
body = JSON.parse(body);
149+
}
150+
catch (error) {
151+
reject(error);
152+
}
153+
;
154+
//Create return object
155+
resolve({
156+
success: !(res.statusCode < 200 || res.statusCode >= 300),
157+
message: res.statusMessage,
158+
code: res.statusCode,
159+
data: body
160+
});
161+
});
162+
});
163+
//On error, reject the Promise
164+
req.on('error', (error) => reject(error));
165+
//End request
166+
req.end();
167+
});
168+
}
169+
}
170+
exports.CoinCodex = CoinCodex;

build/lib/helpers/constants.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
"use strict";
2+
Object.defineProperty(exports, "__esModule", { value: true });
3+
// Constants
4+
const BASE = 'https://coincodex.com'; /** The base url for the CoinCodex API */
5+
const HOST = 'coincodex.com'; /** The host of the CoinCodex API */
6+
const API_VERSION = 'Beta v0.2'; /** The current version for the CoinCodex API */
7+
const ACCEPTED_METHODS = ['GET']; /** The current accepted methods for CoinCodex API calls */
8+
exports.default = { BASE, HOST, API_VERSION, ACCEPTED_METHODS };

build/lib/helpers/test.js

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"use strict";
2+
Object.defineProperty(exports, "__esModule", { value: true });
3+
/** Shared tests for validating CoinCodexClient requests */
4+
const chai_1 = require("chai");
5+
const shouldBeAValidRequest = function () {
6+
it('should return object: {success, message, code, data}', function (done) {
7+
(0, chai_1.expect)(this.data).to.be.an('object');
8+
done();
9+
});
10+
it('should be a successful request', function (done) {
11+
(0, chai_1.expect)(this.data.success).to.be.true;
12+
done();
13+
});
14+
it('should return a 200 code', function (done) {
15+
(0, chai_1.expect)(this.data.code).to.equal(200);
16+
done();
17+
});
18+
};
19+
exports.default = { shouldBeAValidRequest };

build/lib/helpers/utilities.js

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
"use strict";
2+
Object.defineProperty(exports, "__esModule", { value: true });
3+
/** Internal helper to check if parameter is a string */
4+
const isString = (iValue) => {
5+
return (typeof iValue === 'string' || iValue instanceof String);
6+
};
7+
/** Internal helper to check if string is empty */
8+
const isStringEmpty = (str) => {
9+
if (!isString(str))
10+
return false;
11+
return (str.length == 0);
12+
};
13+
/** Internal helper to check if parameter is a date */
14+
const isDate = (date) => {
15+
if (isString(date) || Array.isArray(date) || date == undefined || date == null)
16+
return false;
17+
return (date && Object.prototype.toString.call(date) === "[object Date]" && !isNaN(date));
18+
};
19+
/** Internal helper to check if parameter is an object */
20+
const isObject = (obj) => {
21+
if (Array.isArray(obj) || isDate(obj))
22+
return false;
23+
return (obj !== null && typeof obj === 'object');
24+
};
25+
/** Internal helper to check if parameter is a number */
26+
const isNumber = (num) => {
27+
return (!isNaN(num) && !isNaN(parseInt(num)));
28+
};
29+
/** Internal helper to emit a warning to the console */
30+
const _WARN_ = (title, detail) => {
31+
process.emitWarning(title, {
32+
detail,
33+
code: 'CoinCodex',
34+
});
35+
return true;
36+
};
37+
exports.default = {
38+
isString,
39+
isStringEmpty,
40+
isDate,
41+
isObject,
42+
isNumber,
43+
_WARN_,
44+
};

build/test/CoinCodex.js

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
"use strict";
2+
var __importDefault = (this && this.__importDefault) || function (mod) {
3+
return (mod && mod.__esModule) ? mod : { "default": mod };
4+
};
5+
Object.defineProperty(exports, "__esModule", { value: true });
6+
const CoinCodex_1 = require("../lib/CoinCodex");
7+
const test_1 = __importDefault(require("../lib/helpers/test"));
8+
describe('CoinCodex', function () {
9+
beforeEach(function (done) {
10+
this.CoinCodexClient = new CoinCodex_1.CoinCodex();
11+
done();
12+
});
13+
describe('firstPageHistory', function () {
14+
beforeEach(function (done) {
15+
this.CoinCodexClient.firstPageHistory({
16+
days: 31,
17+
coins_limit: 5,
18+
samples: 31,
19+
}).then((data) => {
20+
this.data = data;
21+
done();
22+
});
23+
});
24+
test_1.default.shouldBeAValidRequest();
25+
});
26+
describe('coins', function () {
27+
describe('all', function () {
28+
beforeEach(function (done) {
29+
this.CoinCodexClient.coins.all().then((data) => {
30+
this.data = data;
31+
done();
32+
});
33+
});
34+
test_1.default.shouldBeAValidRequest();
35+
});
36+
describe('fetch', function () {
37+
beforeEach(function (done) {
38+
this.CoinCodexClient.coins.fetch('btc').then((data) => {
39+
this.data = data;
40+
done();
41+
});
42+
});
43+
test_1.default.shouldBeAValidRequest();
44+
});
45+
describe('fetchHistory', function () {
46+
beforeEach(function (done) {
47+
this.CoinCodexClient.coins.fetchHistory('btc', {
48+
start_date: '2018-01-01',
49+
end_date: '2018-01-31',
50+
samples: 31,
51+
}).then((data) => {
52+
this.data = data;
53+
done();
54+
});
55+
});
56+
test_1.default.shouldBeAValidRequest();
57+
});
58+
// ISSUE: Is not returning a successful request but is according documentation
59+
// describe('markets', function () {
60+
// beforeEach(function (done) {
61+
// this.CoinCodexClient.coins.markets('eth').then((data: any) => {
62+
// console.log('coincodex-markets-eth', data)
63+
// this.data = data;
64+
// done();
65+
// });
66+
// });
67+
// test.shouldBeAValidRequest();
68+
// });
69+
describe('ranges', function () {
70+
beforeEach(function (done) {
71+
this.CoinCodexClient.coins.ranges([
72+
'btc',
73+
'eth',
74+
]).then((data) => {
75+
this.data = data;
76+
done();
77+
});
78+
});
79+
test_1.default.shouldBeAValidRequest();
80+
});
81+
});
82+
});

build/types.js

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
"use strict";
2+
Object.defineProperty(exports, "__esModule", { value: true });

index.js

-1
This file was deleted.

index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export = import('./lib/CoinCodex');

0 commit comments

Comments
 (0)