api_connect_nodejs 2.0.4 → 2.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/conf/settings.ini +1 -1
- package/enums/streamingConstants.js +3 -0
- package/package.json +1 -1
- package/src/apiConnect.js +62 -7
- package/src/config.js +5 -0
- package/src/feed/depthFeed.js +137 -0
- package/src/feed/feed.js +29 -6
- package/src/feed/miniQuoteFeed.js +121 -0
- package/src/feed/quotesFeed.js +106 -1
- package/src/quote.js +75 -0
- package/validations/feedStreamerValidator.js +97 -3
- package/validations/quoteValidator.js +19 -0
package/conf/settings.ini
CHANGED
|
@@ -9,7 +9,7 @@ BasePathContent = https://nc.nuvamawealth.com/edelmw-content/content/
|
|
|
9
9
|
EquityContractURL = https://nc.nuvamawealth.com/app/toccontracts/instruments.zip
|
|
10
10
|
MFContractURL = https://nc.nuvamawealth.com/app/toccontracts/mfInstruments.zip
|
|
11
11
|
|
|
12
|
-
ApiIdKey = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
|
|
12
|
+
ApiIdKey = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcHAiOjAsImZmIjoiVyIsImJkIjoid2ViLXBjIiwibmJmIjoxNjkwNTQxNTQ5LCJzcmMiOiJlbXRtdyIsImF2IjoiMi4wLjUiLCJhcHBpZCI6IjQ5ZTJhNjU1MzAyZTYyM2NhZGEwMTQ2NWRkZTZiODgyIiwiaXNzIjoiZW10IiwiZXhwIjoxNjkwNTY5MDAwLCJpYXQiOjE2OTA1NDE4NDl9.n4N2-F5TWQoizi87_Tv7DyNxdizAa0IKdIS0RqZ4l1w
|
|
13
13
|
TlsVersion = 1.2
|
|
14
14
|
LogLevel = All
|
|
15
15
|
|
|
@@ -6,6 +6,9 @@ const streamingConstants = Object.freeze({
|
|
|
6
6
|
QUOTE_SREAM_REQ_CODE: 1,
|
|
7
7
|
ORDER_STREAM_REQ_CODE: 2,
|
|
8
8
|
LIVENEWS_STREAM_REQ_CODE: 3,
|
|
9
|
+
DEPTH_SREAM_REQ_CODE: 4,
|
|
10
|
+
MINI_QUOTE_SREAM_REQ_CODE: 5,
|
|
11
|
+
REDUCED_QUOTE_SREAM_REQ_CODE: 6,
|
|
9
12
|
});
|
|
10
13
|
|
|
11
14
|
module.exports = streamingConstants;
|
package/package.json
CHANGED
package/src/apiConnect.js
CHANGED
|
@@ -3,6 +3,7 @@ const readline = require("readline");
|
|
|
3
3
|
const log4js = require("./logger.js");
|
|
4
4
|
const Order = require("./order");
|
|
5
5
|
const Chart = require("./chart");
|
|
6
|
+
const Quote = require("./quote");
|
|
6
7
|
const LiveNews = require("./liveNews");
|
|
7
8
|
const Watchlist = require("./watchlist");
|
|
8
9
|
const ResearchCalls = require("./researchCalls");
|
|
@@ -14,6 +15,8 @@ const Feed = require("./feed/feed");
|
|
|
14
15
|
const QuotesFeed = require("./feed/quotesFeed");
|
|
15
16
|
const OrdersFeed = require("./feed/ordersFeed");
|
|
16
17
|
const LiveNewsFeed = require("./feed/liveNewsFeed");
|
|
18
|
+
const MiniQuoteFeed = require("./feed/miniQuoteFeed");
|
|
19
|
+
const DepthFeed = require("./feed/depthFeed");
|
|
17
20
|
|
|
18
21
|
const {
|
|
19
22
|
validatePlaceTrade,
|
|
@@ -197,6 +200,15 @@ class APIConnect {
|
|
|
197
200
|
.PostMethod(url, { lib: "EAC_NODE", vsn: this.version })
|
|
198
201
|
.then((res) => {
|
|
199
202
|
if (res.data.sts) {
|
|
203
|
+
if (res.data.msg === "OPTIONAL") {
|
|
204
|
+
console.log(
|
|
205
|
+
"New version " +
|
|
206
|
+
res.data.vsn +
|
|
207
|
+
" is available. Stay up to date for better experience"
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
return;
|
|
211
|
+
} else if (false == res.data.sts) {
|
|
200
212
|
if (res.data.msg === "MANDATORY") {
|
|
201
213
|
console.log(
|
|
202
214
|
"Mandatory Update. New version " +
|
|
@@ -204,15 +216,9 @@ class APIConnect {
|
|
|
204
216
|
". Update to new version to continue."
|
|
205
217
|
);
|
|
206
218
|
process.exit();
|
|
207
|
-
} else if (res.data.msg === "OPTIONAL") {
|
|
208
|
-
console.log(
|
|
209
|
-
"New version " +
|
|
210
|
-
res.data.vsn +
|
|
211
|
-
" is available. Stay up to date for better experience"
|
|
212
|
-
);
|
|
213
219
|
}
|
|
214
220
|
return;
|
|
215
|
-
}
|
|
221
|
+
}else {
|
|
216
222
|
throw res;
|
|
217
223
|
}
|
|
218
224
|
})
|
|
@@ -265,6 +271,36 @@ class APIConnect {
|
|
|
265
271
|
return orderFeedObj;
|
|
266
272
|
};
|
|
267
273
|
|
|
274
|
+
/**
|
|
275
|
+
* Get MiniQuoteStreaming Object
|
|
276
|
+
* @function initMiniQuoteStreaming
|
|
277
|
+
* @returns MiniQuoteStreaming Object, using this object you can call subsribe() and unsubsribe() methods.
|
|
278
|
+
*/
|
|
279
|
+
initMiniQuoteStreaming = () => {
|
|
280
|
+
let miniQuoteFeedObj = {};
|
|
281
|
+
try {
|
|
282
|
+
miniQuoteFeedObj = new MiniQuoteFeed(this.feedObject);
|
|
283
|
+
} catch (error) {
|
|
284
|
+
console.log(error);
|
|
285
|
+
}
|
|
286
|
+
return miniQuoteFeedObj;
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Get DepthStreaming Object
|
|
291
|
+
* @function initDepthStreaming
|
|
292
|
+
* @returns DepthStreaming Object, using this object you can call subsribe() and unsubsribe() methods.
|
|
293
|
+
*/
|
|
294
|
+
initDepthStreaming = () => {
|
|
295
|
+
let depthFeedObj = {};
|
|
296
|
+
try {
|
|
297
|
+
depthFeedObj = new DepthFeed(this.feedObject, this.__constants);
|
|
298
|
+
} catch (error) {
|
|
299
|
+
console.log(error);
|
|
300
|
+
}
|
|
301
|
+
return depthFeedObj;
|
|
302
|
+
};
|
|
303
|
+
|
|
268
304
|
/**
|
|
269
305
|
* Get Login info
|
|
270
306
|
* @returns Login info
|
|
@@ -2330,6 +2366,25 @@ class APIConnect {
|
|
|
2330
2366
|
});
|
|
2331
2367
|
}
|
|
2332
2368
|
}
|
|
2369
|
+
|
|
2370
|
+
//Get Market Depth
|
|
2371
|
+
/**
|
|
2372
|
+
*
|
|
2373
|
+
* @param {string} symbol
|
|
2374
|
+
* @returns
|
|
2375
|
+
*/
|
|
2376
|
+
getMarketDepth = (
|
|
2377
|
+
symbol,
|
|
2378
|
+
) => {
|
|
2379
|
+
let response = {};
|
|
2380
|
+
log4js.info("getMarketDepth method is called.");
|
|
2381
|
+
const quoteObj = new Quote(this.__http, this.__config, this.__constants);
|
|
2382
|
+
response = quoteObj.getMarketDepthAPI(
|
|
2383
|
+
symbol,
|
|
2384
|
+
);
|
|
2385
|
+
|
|
2386
|
+
return response;
|
|
2387
|
+
};
|
|
2333
2388
|
}
|
|
2334
2389
|
|
|
2335
2390
|
APIConnect.prototype.__constants = new __Constants();
|
package/src/config.js
CHANGED
|
@@ -311,6 +311,11 @@ class __Config {
|
|
|
311
311
|
// return this.baseurllogin + "accounts/" + userid + "/logout";
|
|
312
312
|
return this.baseurllogin + "account/logoff/" + userid;
|
|
313
313
|
};
|
|
314
|
+
|
|
315
|
+
//MARKET DEPTH
|
|
316
|
+
MarketDepthURL = function (symbol) {
|
|
317
|
+
return this.baseurlcontent + "quote/scrip/" + symbol;
|
|
318
|
+
};
|
|
314
319
|
}
|
|
315
320
|
|
|
316
321
|
module.exports = __Config;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
const log4js = require("../logger");
|
|
2
|
+
const configData = require("../iniparser");
|
|
3
|
+
const { DEPTH_SREAM_REQ_CODE } = require("../../enums/streamingConstants");
|
|
4
|
+
const {
|
|
5
|
+
validateSubscribeDepthFeed,
|
|
6
|
+
} = require("../../validations/feedStreamerValidator");
|
|
7
|
+
|
|
8
|
+
class DepthFeed {
|
|
9
|
+
/**
|
|
10
|
+
* Streamer
|
|
11
|
+
* DepthFeed Class for subsribe or unsubsribe Depth
|
|
12
|
+
*/
|
|
13
|
+
constructor(feed, constantsObj) {
|
|
14
|
+
this.feed = feed;
|
|
15
|
+
this.constants = constantsObj
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* QutoesFeed RequestBody Structure
|
|
20
|
+
* Return DepthFeed RequestBody Structure
|
|
21
|
+
* @function depthFeedRequestBody
|
|
22
|
+
* @returns object
|
|
23
|
+
*/
|
|
24
|
+
requestBody = () => {
|
|
25
|
+
return {
|
|
26
|
+
request: {
|
|
27
|
+
streaming_type: "quote2",
|
|
28
|
+
data: {
|
|
29
|
+
"accType": "EQ",
|
|
30
|
+
symbols: [],
|
|
31
|
+
},
|
|
32
|
+
formFactor: configData.formFactor,
|
|
33
|
+
appID: configData.ApiIdKey,
|
|
34
|
+
response_format: "json",
|
|
35
|
+
request_type: "",
|
|
36
|
+
},
|
|
37
|
+
echo: {},
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Create DepthFeed RequestBody
|
|
43
|
+
* Return DepthFeed RequestBody
|
|
44
|
+
* @function createDepthFeedRequest
|
|
45
|
+
* @param {Object[]} symbols - Array of subsribe Symbols
|
|
46
|
+
* @param {boolean} order - true for subsribe and false for unsubsribe
|
|
47
|
+
* @returns object
|
|
48
|
+
*/
|
|
49
|
+
createDepthFeedRequest = (symbols, depth = false) => {
|
|
50
|
+
let body = {};
|
|
51
|
+
const accTyp = this.constants.Data.data.lgnData.accTyp;
|
|
52
|
+
try {
|
|
53
|
+
body = this.requestBody();
|
|
54
|
+
const symset = symbols.map((sym) => ({
|
|
55
|
+
symbol: sym.trim()
|
|
56
|
+
}));
|
|
57
|
+
const substrMcx = '_MCX';
|
|
58
|
+
const substrNcdex = '_NCDEX';
|
|
59
|
+
const subArrContainsMcx = symbols.some(str =>
|
|
60
|
+
(str.toUpperCase()).includes(substrMcx)
|
|
61
|
+
);
|
|
62
|
+
const subArrContainsNcx = symbols.some(str => (str.toUpperCase()).includes(substrNcdex));
|
|
63
|
+
|
|
64
|
+
if ((subArrContainsMcx || subArrContainsNcx) && accTyp == 'EQ') {
|
|
65
|
+
body = {"account_type_exception" : "Symbol subscription error"}
|
|
66
|
+
}else {
|
|
67
|
+
body.request.data.symbols = symset;
|
|
68
|
+
|
|
69
|
+
if (depth) {
|
|
70
|
+
body.request.request_type = "subscribe";
|
|
71
|
+
} else {
|
|
72
|
+
body.request.request_type = "unsubscribe";
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
} catch (error) {
|
|
76
|
+
log4js.debug("createDepthFeedRequest error - " + error);
|
|
77
|
+
} finally {
|
|
78
|
+
return body;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* To subscribe to the streamer, Create the single instance of this mentioning `callback` method. After successsful subscription, `callback` method will be called whenever packet is available at the streamer.
|
|
84
|
+
* @async
|
|
85
|
+
* @function subscribeDepthFeed
|
|
86
|
+
* @param {(err?, data?, close?: number) => void} callBack Callback to receive the Feed in
|
|
87
|
+
* @param {Array<string>} symbols Symbol list for subscription: Symbol_exchange to be obtained from Contract File
|
|
88
|
+
* @returns
|
|
89
|
+
*/
|
|
90
|
+
subscribeDepthFeed = async (symbols, callback) => {
|
|
91
|
+
try {
|
|
92
|
+
/** Validation Start */
|
|
93
|
+
const validateResponse = validateSubscribeDepthFeed(callback, symbols);
|
|
94
|
+
|
|
95
|
+
if (validateResponse.error) {
|
|
96
|
+
log4js.debug(
|
|
97
|
+
"subscribeDepthFeed validation error - " +
|
|
98
|
+
validateResponse.error.details
|
|
99
|
+
);
|
|
100
|
+
return Promise.reject(validateResponse.error.details);
|
|
101
|
+
}
|
|
102
|
+
/** Validation End */
|
|
103
|
+
|
|
104
|
+
/** Create Streaming Depth Request */
|
|
105
|
+
let depthRequest = this.createDepthFeedRequest(symbols, true);
|
|
106
|
+
if(Object.keys(depthRequest).includes("account_type_exception")) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
/** Call connect method of Feed Class */
|
|
110
|
+
this.feed.subsribe(DEPTH_SREAM_REQ_CODE, depthRequest, callback);
|
|
111
|
+
} catch (error) {
|
|
112
|
+
log4js.debug("subscribeDepthFeed error - " + error);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* This method will unsubscribe the symbols from the streamer. After successful invokation of this, will stop the streamer packets of these symbols.
|
|
118
|
+
* @async
|
|
119
|
+
* @function unsubscribeDepthFeed
|
|
120
|
+
* @returns
|
|
121
|
+
*/
|
|
122
|
+
unsubscribeDepthFeed = async () => {
|
|
123
|
+
try {
|
|
124
|
+
/** Get Streaming Depth Request */
|
|
125
|
+
const depthRequest = this.createDepthFeedRequest([]);
|
|
126
|
+
if(Object.keys(depthRequest).includes("account_type_exception")) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
/** Unsubsribe symbols */
|
|
130
|
+
this.feed.unsubsribe(DEPTH_SREAM_REQ_CODE, depthRequest);
|
|
131
|
+
} catch (error) {
|
|
132
|
+
log4js.debug("unsubscribeDepthFeed error - " + error);
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
module.exports = DepthFeed;
|
package/src/feed/feed.js
CHANGED
|
@@ -80,10 +80,11 @@ class Feed {
|
|
|
80
80
|
this.sock.on("data", (data) => {
|
|
81
81
|
try {
|
|
82
82
|
let result = data.toString();
|
|
83
|
+
const obj = JSON.parse(result)
|
|
84
|
+
const streamingType = obj['response']['streaming_type']
|
|
83
85
|
if (result) {
|
|
84
86
|
if (
|
|
85
|
-
|
|
86
|
-
result.match(new RegExp("orderFiler", "g")).length > 0
|
|
87
|
+
streamingType.toLowerCase() == "orderFiler".toLowerCase()
|
|
87
88
|
) {
|
|
88
89
|
let callbackMethod =
|
|
89
90
|
this.requestsList[streamingConstants.ORDER_STREAM_REQ_CODE][
|
|
@@ -91,8 +92,7 @@ class Feed {
|
|
|
91
92
|
];
|
|
92
93
|
callbackMethod(null, result, null);
|
|
93
94
|
} else if (
|
|
94
|
-
|
|
95
|
-
result.match(new RegExp("quote3", "g")).length > 0
|
|
95
|
+
streamingType.toLowerCase() == "quote3".toLowerCase()
|
|
96
96
|
) {
|
|
97
97
|
let callbackMethod =
|
|
98
98
|
this.requestsList[streamingConstants.QUOTE_SREAM_REQ_CODE][
|
|
@@ -100,8 +100,31 @@ class Feed {
|
|
|
100
100
|
];
|
|
101
101
|
callbackMethod(null, result, null);
|
|
102
102
|
} else if (
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
streamingType.toLowerCase() == "quote".toLowerCase()
|
|
104
|
+
) {
|
|
105
|
+
let callbackMethod =
|
|
106
|
+
this.requestsList[streamingConstants.REDUCED_QUOTE_SREAM_REQ_CODE][
|
|
107
|
+
"callback"
|
|
108
|
+
];
|
|
109
|
+
callbackMethod(null, result, null);
|
|
110
|
+
} else if (
|
|
111
|
+
streamingType.toLowerCase() == "miniquote".toLowerCase()
|
|
112
|
+
) {
|
|
113
|
+
let callbackMethod =
|
|
114
|
+
this.requestsList[streamingConstants.MINI_QUOTE_SREAM_REQ_CODE][
|
|
115
|
+
"callback"
|
|
116
|
+
];
|
|
117
|
+
callbackMethod(null, result, null);
|
|
118
|
+
} else if (
|
|
119
|
+
streamingType.toLowerCase() == "quote2".toLowerCase()
|
|
120
|
+
) {
|
|
121
|
+
let callbackMethod =
|
|
122
|
+
this.requestsList[streamingConstants.DEPTH_SREAM_REQ_CODE][
|
|
123
|
+
"callback"
|
|
124
|
+
];
|
|
125
|
+
callbackMethod(null, result, null);
|
|
126
|
+
}else if (
|
|
127
|
+
streamingType.toLowerCase() == "news".toLowerCase()
|
|
105
128
|
) {
|
|
106
129
|
let callbackMethod =
|
|
107
130
|
this.requestsList[streamingConstants.LIVENEWS_STREAM_REQ_CODE][
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
const log4js = require("../logger");
|
|
2
|
+
const configData = require("../iniparser");
|
|
3
|
+
const { MINI_QUOTE_SREAM_REQ_CODE } = require("../../enums/streamingConstants");
|
|
4
|
+
const {
|
|
5
|
+
validateSubscribeMiniQuoteFeed,
|
|
6
|
+
validateUnsubscribeMiniQuoteFeed,
|
|
7
|
+
} = require("../../validations/feedStreamerValidator");
|
|
8
|
+
|
|
9
|
+
class MiniQuoteFeed {
|
|
10
|
+
/**
|
|
11
|
+
* Streamer
|
|
12
|
+
* MiniQuoteFeed Class for subsribe or unsubsribe MiniQuote
|
|
13
|
+
*/
|
|
14
|
+
constructor(feed) {
|
|
15
|
+
this.feed = feed;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* QutoesFeed RequestBody Structure
|
|
20
|
+
* Return MiniQuoteFeed RequestBody Structure
|
|
21
|
+
* @function miniQuoteFeedRequestBody
|
|
22
|
+
* @returns object
|
|
23
|
+
*/
|
|
24
|
+
requestBody = () => {
|
|
25
|
+
return {
|
|
26
|
+
request: {
|
|
27
|
+
streaming_type: "miniquote",
|
|
28
|
+
data: {
|
|
29
|
+
"accType": "EQ",
|
|
30
|
+
symbols: [],
|
|
31
|
+
},
|
|
32
|
+
formFactor: configData.formFactor,
|
|
33
|
+
appID: configData.ApiIdKey,
|
|
34
|
+
response_format: "json",
|
|
35
|
+
request_type: "",
|
|
36
|
+
},
|
|
37
|
+
echo: {},
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Create MiniQuoteFeed RequestBody
|
|
43
|
+
* Return MiniQuoteFeed RequestBody
|
|
44
|
+
* @function createMiniQuoteFeedRequest
|
|
45
|
+
* @param {Object[]} symbols - Array of subsribe Symbols
|
|
46
|
+
* @param {boolean} order - true for subsribe and false for unsubsribe
|
|
47
|
+
* @returns object
|
|
48
|
+
*/
|
|
49
|
+
createMiniQuoteFeedRequest = (symbols, miniQuote = false) => {
|
|
50
|
+
let body = {};
|
|
51
|
+
try {
|
|
52
|
+
body = this.requestBody();
|
|
53
|
+
const symset = symbols.map((sym) => ({ symbol: sym.trim() }));
|
|
54
|
+
|
|
55
|
+
body.request.data.symbols = symset;
|
|
56
|
+
|
|
57
|
+
if (miniQuote) {
|
|
58
|
+
body.request.request_type = "subscribe";
|
|
59
|
+
} else {
|
|
60
|
+
body.request.request_type = "unsubscribe";
|
|
61
|
+
}
|
|
62
|
+
} catch (error) {
|
|
63
|
+
log4js.debug("createMiniQuoteFeedRequest error - " + error);
|
|
64
|
+
} finally {
|
|
65
|
+
return body;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* To subscribe to the streamer, Create the single instance of this mentioning `callback` method. After successsful subscription, `callback` method will be called whenever packet is available at the streamer.
|
|
71
|
+
* @async
|
|
72
|
+
* @function subscribeMiniQuoteFeed
|
|
73
|
+
* @param {(err?, data?, close?: number) => void} callBack Callback to receive the Feed in
|
|
74
|
+
* @param {Array<string>} symbols Symbol list for subscription: Symbol_exchange to be obtained from Contract File
|
|
75
|
+
* @returns
|
|
76
|
+
*/
|
|
77
|
+
subscribeMiniQuoteFeed = async (symbols, callback) => {
|
|
78
|
+
try {
|
|
79
|
+
/** Validation Start */
|
|
80
|
+
const validateResponse = validateSubscribeMiniQuoteFeed(callback, symbols);
|
|
81
|
+
|
|
82
|
+
if (validateResponse.error) {
|
|
83
|
+
log4js.debug(
|
|
84
|
+
"subscribeMiniQuoteFeed validation error - " +
|
|
85
|
+
validateResponse.error.details
|
|
86
|
+
);
|
|
87
|
+
return Promise.reject(validateResponse.error.details);
|
|
88
|
+
}
|
|
89
|
+
/** Validation End */
|
|
90
|
+
|
|
91
|
+
/** Create Streaming MiniQuote Request */
|
|
92
|
+
let miniQuoteRequest = this.createMiniQuoteFeedRequest(symbols, true);
|
|
93
|
+
/** Call connect method of Feed Class */
|
|
94
|
+
this.feed.subsribe(MINI_QUOTE_SREAM_REQ_CODE, miniQuoteRequest, callback);
|
|
95
|
+
} catch (error) {
|
|
96
|
+
log4js.debug("subscribeMiniQuoteFeed error - " + error);
|
|
97
|
+
console.log(error);
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* This method will unsubscribe the symbols from the streamer. After successful invokation of this, will stop the streamer packets of these symbols.
|
|
103
|
+
* @async
|
|
104
|
+
* @function unsubscribeMiniQuoteFeed
|
|
105
|
+
* @returns
|
|
106
|
+
*/
|
|
107
|
+
unsubscribeMiniQuoteFeed = async () => {
|
|
108
|
+
try {
|
|
109
|
+
/** Get Streaming MiniQuote Request */
|
|
110
|
+
const miniQuoteRequest = this.createMiniQuoteFeedRequest([]);
|
|
111
|
+
|
|
112
|
+
/** Unsubsribe symbols */
|
|
113
|
+
this.feed.unsubsribe(MINI_QUOTE_SREAM_REQ_CODE, miniQuoteRequest);
|
|
114
|
+
} catch (error) {
|
|
115
|
+
log4js.debug("unsubscribeMiniQuoteFeed error - " + error);
|
|
116
|
+
console.log(error);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
module.exports = MiniQuoteFeed;
|
package/src/feed/quotesFeed.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
const log4js = require("../logger");
|
|
2
2
|
const configData = require("../iniparser");
|
|
3
|
-
const { QUOTE_SREAM_REQ_CODE } = require("../../enums/streamingConstants");
|
|
3
|
+
const { QUOTE_SREAM_REQ_CODE, REDUCED_QUOTE_SREAM_REQ_CODE } = require("../../enums/streamingConstants");
|
|
4
4
|
const {
|
|
5
5
|
validateSubscribeQuotesFeed,
|
|
6
6
|
validateUnsubscribeQuotesFeed,
|
|
7
|
+
validateSubscribeReducedQuotesFeed,
|
|
8
|
+
validateUnsubscribeReducedQuotesFeed,
|
|
7
9
|
} = require("../../validations/feedStreamerValidator");
|
|
8
10
|
|
|
9
11
|
class QuotesFeed {
|
|
@@ -116,6 +118,109 @@ class QuotesFeed {
|
|
|
116
118
|
console.log(error);
|
|
117
119
|
}
|
|
118
120
|
};
|
|
121
|
+
|
|
122
|
+
//Reduced Quote
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Reduced QutoesFeed RequestBody Structure
|
|
126
|
+
* Return Reduced QuotesFeed RequestBody Structure
|
|
127
|
+
* @function reducedQuotesFeedRequestBody
|
|
128
|
+
* @returns object
|
|
129
|
+
*/
|
|
130
|
+
reducedQuoteRequestBody = () => {
|
|
131
|
+
return {
|
|
132
|
+
request: {
|
|
133
|
+
streaming_type: "quote",
|
|
134
|
+
data: {
|
|
135
|
+
"accType": "EQ",
|
|
136
|
+
symbols: [],
|
|
137
|
+
},
|
|
138
|
+
formFactor: configData.formFactor,
|
|
139
|
+
appID: configData.ApiIdKey,
|
|
140
|
+
response_format: "json",
|
|
141
|
+
request_type: "",
|
|
142
|
+
},
|
|
143
|
+
echo: {},
|
|
144
|
+
};
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* Create ReducedQuotesFeed RequestBody
|
|
148
|
+
* Return ReducedQuotesFeed RequestBody
|
|
149
|
+
* @function createReducedQuotesFeedRequest
|
|
150
|
+
* @param {Object[]} symbols - Array of subsribe Symbols
|
|
151
|
+
* @param {boolean} order - true for subsribe and false for unsubsribe
|
|
152
|
+
* @returns object
|
|
153
|
+
*/
|
|
154
|
+
createReducedQuotesFeedRequest = (symbols, reducedQuote = false) => {
|
|
155
|
+
let body = {};
|
|
156
|
+
try {
|
|
157
|
+
body = this.reducedQuoteRequestBody();
|
|
158
|
+
const symset = symbols.map((sym) => ({ symbol: sym.trim() }));
|
|
159
|
+
|
|
160
|
+
body.request.data.symbols = symset;
|
|
161
|
+
|
|
162
|
+
if (reducedQuote) {
|
|
163
|
+
body.request.request_type = "subscribe";
|
|
164
|
+
} else {
|
|
165
|
+
body.request.request_type = "unsubscribe";
|
|
166
|
+
}
|
|
167
|
+
} catch (error) {
|
|
168
|
+
log4js.debug("createReducedQuotesFeedRequest error - " + error);
|
|
169
|
+
} finally {
|
|
170
|
+
return body;
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* To subscribe to the streamer, Create the single instance of this mentioning `callback` method. After successsful subscription, `callback` method will be called whenever packet is available at the streamer.
|
|
176
|
+
* @async
|
|
177
|
+
* @function subscribeReducedQuotesFeed
|
|
178
|
+
* @param {(err?, data?, close?: number) => void} callBack Callback to receive the Feed in
|
|
179
|
+
* @param {Array<string>} symbols Symbol list for subscription: Symbol_exchange to be obtained from Contract File
|
|
180
|
+
* @returns
|
|
181
|
+
*/
|
|
182
|
+
subscribeReducedQuotesFeed = async (symbols, callback) => {
|
|
183
|
+
try {
|
|
184
|
+
/** Validation Start */
|
|
185
|
+
const validateResponse = validateSubscribeReducedQuotesFeed(callback, symbols);
|
|
186
|
+
|
|
187
|
+
if (validateResponse.error) {
|
|
188
|
+
log4js.debug(
|
|
189
|
+
"subscribeReducedQuotesFeed validation error - " +
|
|
190
|
+
validateResponse.error.details
|
|
191
|
+
);
|
|
192
|
+
return Promise.reject(validateResponse.error.details);
|
|
193
|
+
}
|
|
194
|
+
/** Validation End */
|
|
195
|
+
|
|
196
|
+
/** Create Streaming Quote Request */
|
|
197
|
+
let reducedQuoteRequest = this.createReducedQuotesFeedRequest(symbols, true);
|
|
198
|
+
/** Call connect method of Feed Class */
|
|
199
|
+
this.feed.subsribe(REDUCED_QUOTE_SREAM_REQ_CODE, reducedQuoteRequest, callback);
|
|
200
|
+
} catch (error) {
|
|
201
|
+
log4js.debug("subscribeReducedQuotesFeed error - " + error);
|
|
202
|
+
console.log(error);
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* This method will unsubscribe the symbols from the streamer. After successful invokation of this, will stop the streamer packets of these symbols.
|
|
208
|
+
* @async
|
|
209
|
+
* @function unsubscribeReducedQuotesFeed
|
|
210
|
+
* @returns
|
|
211
|
+
*/
|
|
212
|
+
unsubscribeReducedQuotesFeed = async () => {
|
|
213
|
+
try {
|
|
214
|
+
/** Get Streaming Reduced Quote Request */
|
|
215
|
+
const reducedQuoteRequest = this.createReducedQuotesFeedRequest([]);
|
|
216
|
+
|
|
217
|
+
/** Unsubsribe symbols */
|
|
218
|
+
this.feed.unsubsribe(REDUCED_QUOTE_SREAM_REQ_CODE, reducedQuoteRequest);
|
|
219
|
+
} catch (error) {
|
|
220
|
+
log4js.debug("unsubscribeReducedQuotesFeed error - " + error);
|
|
221
|
+
console.log(error);
|
|
222
|
+
}
|
|
223
|
+
};
|
|
119
224
|
}
|
|
120
225
|
|
|
121
226
|
module.exports = QuotesFeed;
|
package/src/quote.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const log4js = require("./logger.js");
|
|
2
|
+
const {
|
|
3
|
+
validateMarketDepth,
|
|
4
|
+
} = require("../validations/quoteValidator");
|
|
5
|
+
|
|
6
|
+
class Quote {
|
|
7
|
+
constructor(http, config, constants) {
|
|
8
|
+
this.__http = http;
|
|
9
|
+
this.__config = config;
|
|
10
|
+
this.__constants = constants;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Modifying the response
|
|
14
|
+
*/
|
|
15
|
+
modifyResponse = async (response) => {
|
|
16
|
+
try {
|
|
17
|
+
const modifiedResponse = {};
|
|
18
|
+
let msgID = "";
|
|
19
|
+
let srvTm = "";
|
|
20
|
+
if (Object.keys(response).length !== 0) {
|
|
21
|
+
msgID = response["msgID"];
|
|
22
|
+
srvTm = response["srvTm"];
|
|
23
|
+
const data = response.data;
|
|
24
|
+
const mkd = data.mkd;
|
|
25
|
+
modifiedResponse["data"] = mkd;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
modifiedResponse["msgID"] = msgID;
|
|
29
|
+
modifiedResponse["srvTm"] = srvTm;
|
|
30
|
+
log4js.debug("modifiedResponse :" + JSON.stringify(modifiedResponse));
|
|
31
|
+
return modifiedResponse;
|
|
32
|
+
} catch (e) {
|
|
33
|
+
return Promise.reject(e);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
*
|
|
39
|
+
* @param {string} symbol
|
|
40
|
+
* @returns
|
|
41
|
+
*/
|
|
42
|
+
getMarketDepthAPI = async (symbol) => {
|
|
43
|
+
let result = {};
|
|
44
|
+
try {
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Validate market depth params
|
|
48
|
+
*/
|
|
49
|
+
const validateResponse = validateMarketDepth(
|
|
50
|
+
symbol,
|
|
51
|
+
);
|
|
52
|
+
if (validateResponse.error) {
|
|
53
|
+
log4js.debug(
|
|
54
|
+
"market depth validation error - " + validateResponse.error.details
|
|
55
|
+
);
|
|
56
|
+
return Promise.reject(validateResponse.error.details);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const url = this.__config.MarketDepthURL(symbol);
|
|
60
|
+
log4js.debug("market depth URL -" + url);
|
|
61
|
+
const response = await this.__http.GetMethod(url, false);
|
|
62
|
+
|
|
63
|
+
if (result.length !== 0) {
|
|
64
|
+
result = this.modifyResponse(response);
|
|
65
|
+
} else {
|
|
66
|
+
result = response;
|
|
67
|
+
}
|
|
68
|
+
return result;
|
|
69
|
+
} catch (error) {
|
|
70
|
+
log4js.debug("Market depth error - " + error);
|
|
71
|
+
return Promise.reject(error);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
module.exports = Quote;
|
|
@@ -46,6 +46,38 @@ validateStreamerCallback = (callback) => {
|
|
|
46
46
|
|
|
47
47
|
return UnsubcribeFeedQuoteSchema.validate(unsubcribeFeedQuoteObj);
|
|
48
48
|
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Validator For Subsribe Reduced Quote Feed
|
|
52
|
+
*/
|
|
53
|
+
validateSubscribeReducedQuotesFeed = (callback, symbols) => {
|
|
54
|
+
let subcribeFeedReducedQuoteObj = {
|
|
55
|
+
callback: callback,
|
|
56
|
+
symbols: symbols,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const subcribeFeedReducedQuoteSchema = Joi.object({
|
|
60
|
+
callback: Joi.function().required(),
|
|
61
|
+
symbols: Joi.array().items(Joi.string().min(1).required()).required(),
|
|
62
|
+
}).options({ abortEarly: false });
|
|
63
|
+
|
|
64
|
+
return subcribeFeedReducedQuoteSchema.validate(subcribeFeedReducedQuoteObj);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Validator For Unsubsribe Reduced Quote Feed
|
|
69
|
+
*/
|
|
70
|
+
validateUnsubscribeReducedQuotesFeed = (symbols) => {
|
|
71
|
+
let unsubcribeFeedReducedQuoteObj = {
|
|
72
|
+
symbols: symbols,
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const UnsubcribeFeedReducedQuoteSchema = Joi.object({
|
|
76
|
+
symbols: Joi.array().items(Joi.string().min(1).required()).required(),
|
|
77
|
+
}).options({ abortEarly: false });
|
|
78
|
+
|
|
79
|
+
return UnsubcribeFeedReducedQuoteSchema.validate(unsubcribeFeedReducedQuoteObj);
|
|
80
|
+
};
|
|
49
81
|
|
|
50
82
|
validateSubscribeOrdersFeed = (accId, userId, callback) => {
|
|
51
83
|
let subcribeOrdersFeedObj = {
|
|
@@ -62,7 +94,69 @@ validateStreamerCallback = (callback) => {
|
|
|
62
94
|
|
|
63
95
|
return subcribeOrdersFeedSchema.validate(subcribeOrdersFeedObj);
|
|
64
96
|
};
|
|
65
|
-
|
|
66
|
-
|
|
67
97
|
|
|
68
|
-
|
|
98
|
+
/**
|
|
99
|
+
* Validator For Subsribe MiniQuote Feed
|
|
100
|
+
*/
|
|
101
|
+
validateSubscribeMiniQuoteFeed = (callback, symbols) => {
|
|
102
|
+
let subcribeFeedMiniQuoteObj = {
|
|
103
|
+
callback: callback,
|
|
104
|
+
symbols: symbols,
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const subcribeFeedMiniQuoteSchema = Joi.object({
|
|
108
|
+
callback: Joi.function().required(),
|
|
109
|
+
symbols: Joi.array().items(Joi.string().min(1).required()).required(),
|
|
110
|
+
}).options({ abortEarly: false });
|
|
111
|
+
|
|
112
|
+
return subcribeFeedMiniQuoteSchema.validate(subcribeFeedMiniQuoteObj);
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Validator For Unsubsribe MiniQuote Feed
|
|
117
|
+
*/
|
|
118
|
+
validateUnsubscribeMiniQuoteFeed = (symbols) => {
|
|
119
|
+
let unsubcribeFeedMiniQuoteObj = {
|
|
120
|
+
symbols: symbols,
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const UnsubcribeFeedMiniQuoteSchema = Joi.object({
|
|
124
|
+
symbols: Joi.array().items(Joi.string().min(1).required()).required(),
|
|
125
|
+
}).options({ abortEarly: false });
|
|
126
|
+
|
|
127
|
+
return UnsubcribeFeedMiniQuoteSchema.validate(unsubcribeFeedMiniQuoteObj);
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Validator For Subsribe Market Depth Feed
|
|
132
|
+
*/
|
|
133
|
+
validateSubscribeDepthFeed = (callback, symbols) => {
|
|
134
|
+
let subcribeFeedDepthObj = {
|
|
135
|
+
callback: callback,
|
|
136
|
+
symbols: symbols,
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
const subcribeFeedDepthSchema = Joi.object({
|
|
140
|
+
callback: Joi.function().required(),
|
|
141
|
+
symbols: Joi.array().items(Joi.string().min(1).required()).required(),
|
|
142
|
+
}).options({ abortEarly: false });
|
|
143
|
+
|
|
144
|
+
return subcribeFeedDepthSchema.validate(subcribeFeedDepthObj);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Validator For Unsubsribe Depth Feed
|
|
149
|
+
*/
|
|
150
|
+
validateUnsubscribeDepthFeed = (symbols) => {
|
|
151
|
+
let unsubcribeFeedDepthObj = {
|
|
152
|
+
symbols: symbols,
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const UnsubcribeFeedDepthSchema = Joi.object({
|
|
156
|
+
symbols: Joi.array().items(Joi.string().min(1).required()).required(),
|
|
157
|
+
}).options({ abortEarly: false });
|
|
158
|
+
|
|
159
|
+
return UnsubcribeFeedDepthSchema.validate(unsubcribeFeedDepthObj);
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
module.exports = { validateStreamerCallback, validateSubscribeQuotesFeed, validateUnsubscribeQuotesFeed, validateSubscribeReducedQuotesFeed, validateUnsubscribeReducedQuotesFeed, validateSubscribeOrdersFeed, validateSubscribeMiniQuoteFeed, validateUnsubscribeMiniQuoteFeed, validateSubscribeDepthFeed, validateUnsubscribeDepthFeed};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const Joi = require("Joi");
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Validate Market Depth input params
|
|
5
|
+
*/
|
|
6
|
+
validateMarketDepth = (symbol) => {
|
|
7
|
+
const paramsObject = {
|
|
8
|
+
symbol: symbol,
|
|
9
|
+
};
|
|
10
|
+
const depthParamsSchema = Joi.object({
|
|
11
|
+
symbol: Joi.string().required(),
|
|
12
|
+
}).options({ abortEarly: false });
|
|
13
|
+
|
|
14
|
+
return depthParamsSchema.validate(paramsObject);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
module.exports = {
|
|
18
|
+
validateMarketDepth
|
|
19
|
+
};
|