Skip to content

Commit 6e41d07

Browse files
committed
feat: converted candles
1 parent 1b60139 commit 6e41d07

File tree

10 files changed

+207
-27
lines changed

10 files changed

+207
-27
lines changed

README.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,39 +20,39 @@ This sdk makes use of the [api version 3](https://api.exchange.cryptomkt.com) of
2020

2121
## rest client
2222

23-
```javascript
23+
```typescript
2424
const { Client } = require("cryptomarket");
2525

2626
// instance a client
27-
let apiKey = "AB32B3201";
28-
let apiSecret = "21b12401";
29-
let client = new Client(apiKey, apiSecret);
27+
const apiKey = "AB32B3201";
28+
const apiSecret = "21b12401";
29+
const client = new Client(apiKey, apiSecret);
3030

3131
// get currencies
32-
let currencies = await client.getCurrencies();
32+
const currencies = await client.getCurrencies();
3333

3434
// get order books
35-
let orderBook = await client.getOrderBook("EOSETH");
35+
const orderBook = await client.getOrderBook("EOSETH");
3636

3737
// get your account balances
38-
let accountBalances = await client.getWalletBalances();
38+
const accountBalances = await client.getWalletBalances();
3939

4040
// get your trading balances
41-
let tradingBalances = await client.getSpotTradingBalances();
41+
const tradingBalances = await client.getSpotTradingBalances();
4242

4343
// move balance from wallet to spot trading
44-
let result = await client.transferBetweenWalletAndExchange({
44+
const result = await client.transferBetweenWalletAndExchange({
4545
currency: "EOS",
4646
amount: "3.2",
4747
source: Account.Wallet,
4848
destination: Account.Spot,
4949
});
5050

5151
// get your active orders
52-
let orders = await client.getAllActiveSpotOrders("EOSETH");
52+
const activeOrders = await client.getAllActiveSpotOrders("EOSETH");
5353

5454
// create a new order
55-
let newOrder = await client.createOrder({
55+
const newOrder = await client.createOrder({
5656
symbol: "EOSETH",
5757
side: "buy",
5858
quantity: "10",

lib/client.ts

Lines changed: 79 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ import {
3737
Trade,
3838
Transaction,
3939
} from "./models";
40+
import { ConvertedCandlesBySymbol } from "./models/ConvertedCandle";
41+
import { ConvertedCandles } from "./models/ConvertedCandles";
4042
import { fromCamelCaseToSnakeCase, fromSnakeCaseToCamelCase } from "./paramStyleConverter"
4143

4244

@@ -394,9 +396,9 @@ export class Client {
394396
/**
395397
* Get candles for all symbols or for specified symbols
396398
*
397-
* Candels are used for OHLC representation
399+
* Candles are used for OHLC representation
398400
*
399-
* The result contains candles with non-zero volume only (no trades = no candles).
401+
* The result contains candles with non-zero volume only (no trades = no candles).
400402
*
401403
* Requires no API key Access Rights.
402404
*
@@ -426,9 +428,9 @@ export class Client {
426428
/**
427429
* Get candles for a symbol
428430
*
429-
* Candels are used for OHLC representation
431+
* Candles are used for OHLC representation
430432
*
431-
* The result contains candles with non-zero volume only (no trades = no candles).
433+
* The result contains candles with non-zero volume only (no trades = no candles).
432434
*
433435
* Requires no API key Access Rights.
434436
*
@@ -459,6 +461,79 @@ export class Client {
459461
return this.get(`public/candles/${symbol}`, params);
460462
}
461463

464+
/**
465+
* Gets candles regarding the last price converted to the target currency for all symbols or for the specified symbols
466+
*
467+
* Candles are used for OHLC representation
468+
*
469+
* The result contains candles with non-zero volume only (no trades = no candles).
470+
*
471+
* Conversion from the symbol quote currency to the target currency is the mean of "best" bid price and "best" ask price in the order book. If there is no "best" bid or ask price, the last price is returned.
472+
*
473+
* Requires no API key Access Rights.
474+
*
475+
* https://api.exchange.cryptomkt.com/#candles
476+
*
477+
* @param {object} [params]
478+
* @param {string[]} [params.targetCurrency] Target currency for conversion
479+
* @param {string[]} [params.symbols] Optional. A list of symbol ids
480+
* @param {PERIOD} [params.period] Optional. A valid tick interval. 'M1' (one minute), 'M3', 'M5', 'M15', 'M30', 'H1' (one hour), 'H4', 'D1' (one day), 'D7', '1M' (one month). Default is 'M30'
481+
* @param {SORT} [params.sort] Optional. Sort direction. 'ASC' or 'DESC'. Default is 'DESC'
482+
* @param {string} [params.from] Optional. Initial value of the queried interval. As Datetime
483+
* @param {string} [params.till] Optional. Last value of the queried interval. As Datetime
484+
* @param {number} [params.limit] Optional. Candles per query. Defaul is 10. Min is 1. Max is 1000
485+
*
486+
* @return A class with the targetCurrency and data with a map with a list of candles for each symbol of the query. indexed by symbol.
487+
*/
488+
getConvertedCandles(params?: {
489+
targetCurrency: string;
490+
symbols?: string[];
491+
period?: PERIOD;
492+
sort?: SORT;
493+
from?: string;
494+
till?: string;
495+
limit?: number;
496+
}): Promise<ConvertedCandles> {
497+
return this.get("public/converted/candles", params);
498+
}
499+
500+
/**
501+
* Gets candles regarding the last price converted to the target currency for the specified symbol
502+
*
503+
* Candles are used for OHLC representation
504+
*
505+
* The result contains candles with non-zero volume only (no trades = no candles).
506+
*
507+
* Conversion from the symbol quote currency to the target currency is the mean of "best" bid price and "best" ask price in the order book. If there is no "best" bid or ask price, the last price is returned.
508+
*
509+
* Requires no API key Access Rights.
510+
*
511+
* https://api.exchange.cryptomkt.com/#candles
512+
*
513+
* @param {string[]} symbol A symbol id
514+
* @param {object} params
515+
* @param {string[]} params.targetCurrency Target currency for conversion
516+
* @param {PERIOD} [params.period] Optional. A valid tick interval. 'M1' (one minute), 'M3', 'M5', 'M15', 'M30', 'H1' (one hour), 'H4', 'D1' (one day), 'D7', '1M' (one month). Default is 'M30'
517+
* @param {SORT} [params.sort] Optional. Sort direction. 'ASC' or 'DESC'. Default is 'DESC'
518+
* @param {string} [params.from] Optional. Initial value of the queried interval. As Datetime
519+
* @param {string} [params.till] Optional. Last value of the queried interval. As Datetime
520+
* @param {number} [params.limit] Optional. Candles per query. Defaul is 10. Min is 1. Max is 1000
521+
*
522+
* @return An object with the targetCurrency and data with a list of candles for the symbol of the query.
523+
*/
524+
getConvertedCandlesBySymbol(
525+
symbol: string,
526+
params?: {
527+
targetCurrency: string;
528+
period?: PERIOD;
529+
sort?: SORT;
530+
from?: string;
531+
till?: string;
532+
limit?: number;
533+
}): Promise<ConvertedCandlesBySymbol> {
534+
return this.get(`public/converted/candles/${symbol}`, params);
535+
}
536+
462537
/////////////////////////
463538
// AUTHENTICATED CALLS //
464539
/////////////////////////

lib/models/ConvertedCandle.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { Candle } from "./Candle";
2+
3+
export interface ConvertedCandlesBySymbol {
4+
targetCurrency: string;
5+
data: Candle[];
6+
}

lib/models/ConvertedCandles.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { Candle } from "./Candle";
2+
3+
export interface ConvertedCandles {
4+
targetCurrency: string;
5+
data: { [key: string]: Candle[] };
6+
}

lib/paramStyleConverter.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,12 @@ const convertObjectKeysToCamelCase = (obj: { [x: string]: any }): { [x: string]:
3939
}
4040

4141

42-
const camelCaseToSnakeCase = (camelCase: string) => {
43-
return camelCase.replace(/([A-Z])/g, letter => `_${letter.toLowerCase()}`);
44-
}
42+
const camelCaseToSnakeCase = (camelCase: string) => camelCase
43+
.replace(/([A-Z])/g, letter => `_${letter.toLowerCase()}`)
44+
4545

46-
const snakeCaseToCamelCase = (value: string) =>
47-
value.replace(/([_][a-z])/g, _letter => _letter.replace('_', '').toUpperCase()
48-
);
46+
const snakeCaseToCamelCase = (value: string) => value
47+
.replace(/([_][a-z])/g, _letter => _letter.replace('_', '').toUpperCase());
4948

5049
const isObject = (value: any) => {
5150
return typeof (value) == "object";

lib/websocket/clientBase.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ export class WSClientBase {
109109
this.ws.send(JSON.stringify(payload));
110110
return withTimeout(this.requestTimeoutMs, promise);
111111
}
112+
112113
protected requestList({ method, params: paramsRaw = {}, responseCount = 1 }: { method: any; params?: {}; responseCount?: number; }): Promise<unknown> {
113114
const params = fromCamelCaseToSnakeCase(paramsRaw)
114115
const { id, promise } = this.multiResponsePromiseFactory.newMultiResponsePromise(responseCount);

lib/websocket/marketDataClient.ts

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ export class MarketDataClient extends WSClientBase {
7474
const promise = new Promise(function (resolve, reject) {
7575
emitter.once(ID.toString(), function (response) {
7676
if ("error" in response) {
77-
reject(new CryptomarketAPIException(response));
77+
reject(new CryptomarketAPIException(response.error));
7878
return;
7979
}
8080
resolve(response.result);
@@ -159,7 +159,7 @@ export class MarketDataClient extends WSClientBase {
159159
/**
160160
* subscribe to a feed of candles
161161
*
162-
* subscription is for all symbols or for the specified symbols
162+
* subscription is for the specified symbols
163163
*
164164
* normal subscriptions have one update message per symbol
165165
*
@@ -171,9 +171,9 @@ export class MarketDataClient extends WSClientBase {
171171
* https://api.exchange.cryptomkt.com/#subscribe-to-candles
172172
*
173173
* @param {function} callback a function that recieves notifications as a dict of candles indexed by symbol, and the type of notification (either SNAPSHOT or UPDATE)
174-
* @param {PERIOD} [params.period] Optional. A valid tick interval. 'M1' (one minute), 'M3', 'M5', 'M15', 'M30', 'H1' (one hour), 'H4', 'D1' (one day), 'D7', '1M' (one month). Default is 'M30'
175-
* @param {string[]} [params.symbols] Optional. A list of symbol ids
176-
* @param {number} params.limit Number of historical entries returned in the first feed. Min is 0. Max is 1000. Default is 0
174+
* @param {PERIOD} params.period A valid tick interval. 'M1' (one minute), 'M3', 'M5', 'M15', 'M30', 'H1' (one hour), 'H4', 'D1' (one day), 'D7', '1M' (one month).
175+
* @param {string[]} params.symbols A list of symbol ids
176+
* @param {number} [params.limit] Optional. Number of historical entries returned in the first feed. Min is 0. Max is 1000. Default is 0
177177
* @return A promise that resolves when subscribed with a list of the successfully subscribed symbols
178178
*/
179179
subscribeToCandles({
@@ -193,6 +193,41 @@ export class MarketDataClient extends WSClientBase {
193193
});
194194
}
195195

196+
/**
197+
* subscribes to a feed of candles regarding the last price converted to the target currency * for the specified symbols
198+
*
199+
* subscription is only for the specified symbols
200+
*
201+
* normal subscriptions have one update message per symbol
202+
*
203+
* Requires no API key Access Rights
204+
*
205+
* https://api.exchange.cryptomkt.com/#subscribe-to-converted-candles
206+
*
207+
* @param {function} callback a function that recieves notifications as a dict of candles indexed by symbol, and the type of notification (either SNAPSHOT or UPDATE)
208+
* @param {function} params.targetCurrency Target currency for conversion
209+
* @param {PERIOD} params.period A valid tick interval. 'M1' (one minute), 'M3', 'M5', 'M15', 'M30', 'H1' (one hour), 'H4', 'D1' (one day), 'D7', '1M' (one month). Default is 'M30'
210+
* @param {string[]} params.symbols A list of symbol ids
211+
* @param {number} [params.limit] Optional. Number of historical entries returned in the first feed. Min is 0. Max is 1000. Default is 0
212+
* @return A promise that resolves when subscribed with a list of the successfully subscribed symbols
213+
*/
214+
subscribeToConvertedCandles({
215+
callback,
216+
params: { period, ...params },
217+
}: {
218+
callback: (
219+
notification: { [x: string]: WSCandle[] },
220+
type: NOTIFICATION_TYPE
221+
) => any;
222+
params: { targetCurrency: string, period: PERIOD; symbols: string[]; limit?: number };
223+
}): Promise<string[]> {
224+
return this.makeSubscription({
225+
channel: `converted/candles/${period}`,
226+
callback: parseMapListInterceptor(callback, parseWSCandle),
227+
params,
228+
});
229+
}
230+
196231
/**
197232
* subscribe to a feed of mini tickers
198233
*

test/rest/marketData.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,4 +251,42 @@ describe("Rest client test", () => {
251251
assert(goodList(goodCandle, candles), "not good candles");
252252
});
253253
});
254+
describe("Get Converted candles", () => {
255+
it("for all symbols", async function () {
256+
this.timeout(0);
257+
let candles = await client.getConvertedCandles({ targetCurrency: "ETH" });
258+
assert(!emptyDict(candles), "empty list of candles");
259+
assert(
260+
goodDict((candleList) => goodList(goodCandle, candleList), candles.data),
261+
"not good candles"
262+
);
263+
});
264+
it("for 2 symbols", async function () {
265+
this.timeout(0);
266+
let candles = await client.getConvertedCandles({
267+
targetCurrency: "ETH",
268+
symbols: ["EOSETH", "PAXGBTC"],
269+
period: PERIOD._1_HOUR,
270+
limit: 2,
271+
});
272+
assert(dictSize(candles, 2), "wrong number of symbols");
273+
assert(
274+
goodDict((candleList) => goodList(goodCandle, candleList), candles.data),
275+
"not good candles"
276+
);
277+
});
278+
});
279+
describe("Get converted candles Of Symbol", () => {
280+
it("with period and limit", async function () {
281+
this.timeout(0);
282+
let candles = await client.getConvertedCandlesBySymbol("ADAETH", {
283+
targetCurrency: "BTC",
284+
period: PERIOD._30_MINUTES,
285+
limit: 2,
286+
});
287+
assert(listSize(candles.data, 2), "wrong number of candles");
288+
assert(goodList(goodCandle, candles.data), "not good candles");
289+
});
290+
});
254291
});
292+

test/rest/walletManagement.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,12 @@ describe("wallet management", () => {
154154
it("cro belongs", async function () {
155155
this.timeout(0);
156156
let croAddress = await client.getDepositCryptoAddress("CRO");
157+
console.log(croAddress)
157158
let result = await client.checkIfCryptoAddressBelongsToCurrentAccount(
158159
croAddress.address
159160
);
161+
162+
console.log(result)
160163
assert(result === true, "does not belong");
161164
});
162165
it.skip("eos belongs", async function () {

test/websocket/marketData.test.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ describe("websocket market data client", function () {
3939

4040
describe("subscribe to candles", function () {
4141
it("gets a feed of candles", async function () {
42-
// TODO: unknown state
4342
this.timeout(0);
4443
await wsclient.connect();
4544
await wsclient.subscribeToCandles({
@@ -54,6 +53,24 @@ describe("websocket market data client", function () {
5453
});
5554
});
5655

56+
57+
describe.only("subscribe to converted candles", function () {
58+
it("gets a feed of candles", async function () {
59+
this.timeout(0);
60+
await wsclient.connect();
61+
await wsclient.subscribeToConvertedCandles({
62+
callback: checkGoodMapListValues(goodWSCandle),
63+
params: {
64+
period: PERIOD._1_MINUTE,
65+
targetCurrency: "BTC",
66+
symbols: ["EOSETH", "ETHBTC"],
67+
limit: 3,
68+
},
69+
});
70+
await timeout(3 * SECOND);
71+
});
72+
});
73+
5774
describe("subscribe to mini ticker", function () {
5875
it("gets a feed of mini tickers (with are candles)", async function () {
5976
this.timeout(0);

0 commit comments

Comments
 (0)