shoonya-sdk 0.4.2 → 0.4.4

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.
@@ -1,46 +1,5 @@
1
1
  import { EventEmitter } from 'events';
2
2
 
3
- declare const paths: {
4
- readonly login: "QuickAuth";
5
- readonly logout: "Logout";
6
- readonly forgotPassword: "ForgotPassword";
7
- readonly changePassword: "Changepwd";
8
- readonly watchlist: "MWList";
9
- readonly getWatchlist: "MarketWatch";
10
- readonly searchScrip: "SearchScrip";
11
- readonly userInfo: "UserDetails";
12
- readonly clientInfo: "ClientDetails";
13
- readonly quotes: "GetQuotes";
14
- readonly addScripToWL: "AddMultiScripsToMW";
15
- readonly removeScripFromWL: "DeleteMultiMWScrips";
16
- readonly securityInfo: "GetSecurityInfo";
17
- readonly placeOrder: "PlaceOrder";
18
- readonly modifyOrder: "ModifyOrder";
19
- readonly cancelOrder: "CancelOrder";
20
- readonly exitSNOOrder: "ExitSNOOrder";
21
- readonly historicData: "TPSeries";
22
- readonly optionChain: "GetOptionChain";
23
- readonly orderBook: "OrderBook";
24
- };
25
- type Path = keyof typeof paths;
26
-
27
- type LogType = "DEBUG" | "WARN" | "ERROR";
28
- declare class Logger {
29
- logPath: string;
30
- maxSize: number;
31
- fileName: string;
32
- /**
33
- *
34
- * @param logFileName name to prepend the logs file with
35
- * @param size max size of file (in bytes)
36
- */
37
- constructor(logFileName: string, size: number);
38
- log(msg: string, logType?: LogType): void;
39
- private checkLogSize;
40
- private deleteOldestFile;
41
- private checkPathExistance;
42
- }
43
-
44
3
  type RequestDataType = {
45
4
  [key: string]: string;
46
5
  };
@@ -203,6 +162,128 @@ interface OrderBookFail {
203
162
  emsg: string;
204
163
  }
205
164
  type OrderBook = OrderBookSuccess[] | OrderBookFail;
165
+ interface GetLimitsParam {
166
+ /**
167
+ * Product Name
168
+ * (Select from ‘prarr’ Array provided in User Details response, and if same is allowed for selected, exchange.
169
+ * Show product display name, for user to select, and send corresponding prd in API call)
170
+ *
171
+ * ```
172
+ * `C` : CNC
173
+ * `M` : NRML
174
+ * `I` : MIS
175
+ * `B` : Bracket Order
176
+ * `H` : Cover Order
177
+ * ```
178
+ */
179
+ prd?: "C" | "M" | "I" | "B" | "H";
180
+ seg?: "CM" | "FX" | "FO";
181
+ exch?: "NSE" | "NFO" | "BSE" | "MCX" | "CDS";
182
+ }
183
+ interface GetLimitsResponseFail {
184
+ stat: "Not_Ok";
185
+ emsg: string;
186
+ }
187
+ interface GetLimitsResponseSuccess {
188
+ request_time: string;
189
+ stat: "Ok";
190
+ prfname: string;
191
+ cash: number;
192
+ payin: number;
193
+ payout: number;
194
+ brkcollamt: number;
195
+ unclearedcash: number;
196
+ aux_daycash: number;
197
+ aux_brkcollamt: number;
198
+ aux_unclearedcash: number;
199
+ daycash: number;
200
+ turnoverlmt: number;
201
+ pendordvallmt: number;
202
+ remarks_amt: number;
203
+ remarks_text: string;
204
+ blk_amt: number;
205
+ }
206
+ interface GetSecurityInfoSuccess {
207
+ request_time: string;
208
+ stat: "Ok";
209
+ exch: "NFO" | "NSE" | "BSE" | "MCX" | "CDS";
210
+ tsym: string;
211
+ cname: string;
212
+ symname: string;
213
+ seg: string;
214
+ exd: string;
215
+ instname: string;
216
+ optt: "CE" | "PE";
217
+ und_exch: string;
218
+ und_tk: string;
219
+ pp: string;
220
+ prcftr: string;
221
+ ls: string;
222
+ ti: string;
223
+ mult: string;
224
+ weekly: string;
225
+ dname: string;
226
+ uc: string;
227
+ lc: string;
228
+ strprc: string;
229
+ prcftr_d: string;
230
+ exptime: string;
231
+ token: string;
232
+ frzqty: string;
233
+ delmrg: string;
234
+ varmrg: string;
235
+ expmrg: string;
236
+ }
237
+ interface GetSecurityInfoFail {
238
+ stat: "Not_Ok";
239
+ request_time: string;
240
+ emsg: string;
241
+ }
242
+ type GetSecurityInfoResponse = GetSecurityInfoSuccess | GetSecurityInfoFail;
243
+ type GetTokenExpiry = "current" | "next" | "next-next" | "more-than-1-day" | "more-than-3-day" | "more-than-10-day";
244
+
245
+ declare const paths: {
246
+ readonly login: "QuickAuth";
247
+ readonly logout: "Logout";
248
+ readonly forgotPassword: "ForgotPassword";
249
+ readonly changePassword: "Changepwd";
250
+ readonly watchlist: "MWList";
251
+ readonly getWatchlist: "MarketWatch";
252
+ readonly searchScrip: "SearchScrip";
253
+ readonly userInfo: "UserDetails";
254
+ readonly clientInfo: "ClientDetails";
255
+ readonly quotes: "GetQuotes";
256
+ readonly addScripToWL: "AddMultiScripsToMW";
257
+ readonly removeScripFromWL: "DeleteMultiMWScrips";
258
+ readonly securityInfo: "GetSecurityInfo";
259
+ readonly placeOrder: "PlaceOrder";
260
+ readonly modifyOrder: "ModifyOrder";
261
+ readonly cancelOrder: "CancelOrder";
262
+ readonly exitSNOOrder: "ExitSNOOrder";
263
+ readonly historicData: "TPSeries";
264
+ readonly optionChain: "GetOptionChain";
265
+ readonly orderBook: "OrderBook";
266
+ readonly holding: "Holdings";
267
+ readonly limits: "Limits";
268
+ };
269
+ type Path = keyof typeof paths;
270
+
271
+ type LogType = "DEBUG" | "WARN" | "ERROR";
272
+ declare class Logger {
273
+ logPath: string;
274
+ maxSize: number;
275
+ fileName: string;
276
+ /**
277
+ *
278
+ * @param logFileName name to prepend the logs file with
279
+ * @param size max size of file (in bytes)
280
+ */
281
+ constructor(logFileName: string, size: number);
282
+ log(msg: string, logType?: LogType): void;
283
+ private checkLogSize;
284
+ private deleteOldestFile;
285
+ private checkPathExistance;
286
+ }
206
287
 
207
288
  type ShoonyaWSEvents = "connect" | "open" | "priceUpdate" | "orderUpdate" | "stopped" | "close" | "reconnect" | "error";
208
289
  declare interface Shoonya {
@@ -228,6 +309,7 @@ declare class Shoonya extends EventEmitter {
228
309
  private reconnectTimeout;
229
310
  private heartbeatTimeout;
230
311
  private lastWsMsgAt;
312
+ private autoReconnectTimeout;
231
313
  constructor(options?: {
232
314
  logging: boolean;
233
315
  /**
@@ -288,7 +370,7 @@ declare class Shoonya extends EventEmitter {
288
370
  * @returns
289
371
  */
290
372
  removeScripFromWatchList(listName: string, scrips: string[]): Promise<unknown>;
291
- getSecurityInfo(exchange: string, contractToken: string): Promise<unknown>;
373
+ getSecurityInfo(exchange: string, contractToken: string): Promise<GetSecurityInfoResponse>;
292
374
  placeOrder(details: OrderInput): Promise<PlaceOrder>;
293
375
  modifyOrder(orderDetail: MakeKeysRequired<Partial<OrderInput>, "exch" | "norenordno" | "tsym">): Promise<unknown>;
294
376
  cancelOrder(orderNo: string): Promise<unknown>;
@@ -329,7 +411,10 @@ declare class Shoonya extends EventEmitter {
329
411
  * @default 5
330
412
  */
331
413
  count?: string;
332
- optionExpiry?: "current" | "next" | "next-next" | "more-than-1-day";
414
+ /**
415
+ * @default current
416
+ */
417
+ optionExpiry?: GetTokenExpiry;
333
418
  }): Promise<{
334
419
  token: number;
335
420
  exchange: "NFO" | "MCX";
@@ -337,6 +422,21 @@ declare class Shoonya extends EventEmitter {
337
422
  }>;
338
423
  private getFormattedExpiry;
339
424
  private getNextFormattedDates;
425
+ /**
426
+ * Product Name
427
+ * (Select from ‘prarr’ Array provided in User Details response, and if same is allowed for selected, exchange.
428
+ * Show product display name, for user to select, and send corresponding prd in API call)
429
+ *
430
+ * ```
431
+ * `C` : CNC
432
+ * `M` : NRML
433
+ * `I` : MIS
434
+ * `B` : Bracket Order
435
+ * `H` : Cover Order
436
+ * ```
437
+ */
438
+ getAccountHolding(productName: "C" | "M" | "I" | "B" | "H"): Promise<any>;
439
+ getAccountLimits(params?: GetLimitsParam): Promise<GetLimitsResponseSuccess | GetLimitsResponseFail>;
340
440
  getLastWSMessage(): Date;
341
441
  getWSState(): {
342
442
  OPEN: boolean;
@@ -344,6 +444,7 @@ declare class Shoonya extends EventEmitter {
344
444
  CLOSING: boolean;
345
445
  CONNECTING: boolean;
346
446
  };
447
+ getSubscribedTokens(): string[];
347
448
  connectWS(): void;
348
449
  /**
349
450
  *
@@ -1,46 +1,5 @@
1
1
  import { EventEmitter } from 'events';
2
2
 
3
- declare const paths: {
4
- readonly login: "QuickAuth";
5
- readonly logout: "Logout";
6
- readonly forgotPassword: "ForgotPassword";
7
- readonly changePassword: "Changepwd";
8
- readonly watchlist: "MWList";
9
- readonly getWatchlist: "MarketWatch";
10
- readonly searchScrip: "SearchScrip";
11
- readonly userInfo: "UserDetails";
12
- readonly clientInfo: "ClientDetails";
13
- readonly quotes: "GetQuotes";
14
- readonly addScripToWL: "AddMultiScripsToMW";
15
- readonly removeScripFromWL: "DeleteMultiMWScrips";
16
- readonly securityInfo: "GetSecurityInfo";
17
- readonly placeOrder: "PlaceOrder";
18
- readonly modifyOrder: "ModifyOrder";
19
- readonly cancelOrder: "CancelOrder";
20
- readonly exitSNOOrder: "ExitSNOOrder";
21
- readonly historicData: "TPSeries";
22
- readonly optionChain: "GetOptionChain";
23
- readonly orderBook: "OrderBook";
24
- };
25
- type Path = keyof typeof paths;
26
-
27
- type LogType = "DEBUG" | "WARN" | "ERROR";
28
- declare class Logger {
29
- logPath: string;
30
- maxSize: number;
31
- fileName: string;
32
- /**
33
- *
34
- * @param logFileName name to prepend the logs file with
35
- * @param size max size of file (in bytes)
36
- */
37
- constructor(logFileName: string, size: number);
38
- log(msg: string, logType?: LogType): void;
39
- private checkLogSize;
40
- private deleteOldestFile;
41
- private checkPathExistance;
42
- }
43
-
44
3
  type RequestDataType = {
45
4
  [key: string]: string;
46
5
  };
@@ -203,6 +162,128 @@ interface OrderBookFail {
203
162
  emsg: string;
204
163
  }
205
164
  type OrderBook = OrderBookSuccess[] | OrderBookFail;
165
+ interface GetLimitsParam {
166
+ /**
167
+ * Product Name
168
+ * (Select from ‘prarr’ Array provided in User Details response, and if same is allowed for selected, exchange.
169
+ * Show product display name, for user to select, and send corresponding prd in API call)
170
+ *
171
+ * ```
172
+ * `C` : CNC
173
+ * `M` : NRML
174
+ * `I` : MIS
175
+ * `B` : Bracket Order
176
+ * `H` : Cover Order
177
+ * ```
178
+ */
179
+ prd?: "C" | "M" | "I" | "B" | "H";
180
+ seg?: "CM" | "FX" | "FO";
181
+ exch?: "NSE" | "NFO" | "BSE" | "MCX" | "CDS";
182
+ }
183
+ interface GetLimitsResponseFail {
184
+ stat: "Not_Ok";
185
+ emsg: string;
186
+ }
187
+ interface GetLimitsResponseSuccess {
188
+ request_time: string;
189
+ stat: "Ok";
190
+ prfname: string;
191
+ cash: number;
192
+ payin: number;
193
+ payout: number;
194
+ brkcollamt: number;
195
+ unclearedcash: number;
196
+ aux_daycash: number;
197
+ aux_brkcollamt: number;
198
+ aux_unclearedcash: number;
199
+ daycash: number;
200
+ turnoverlmt: number;
201
+ pendordvallmt: number;
202
+ remarks_amt: number;
203
+ remarks_text: string;
204
+ blk_amt: number;
205
+ }
206
+ interface GetSecurityInfoSuccess {
207
+ request_time: string;
208
+ stat: "Ok";
209
+ exch: "NFO" | "NSE" | "BSE" | "MCX" | "CDS";
210
+ tsym: string;
211
+ cname: string;
212
+ symname: string;
213
+ seg: string;
214
+ exd: string;
215
+ instname: string;
216
+ optt: "CE" | "PE";
217
+ und_exch: string;
218
+ und_tk: string;
219
+ pp: string;
220
+ prcftr: string;
221
+ ls: string;
222
+ ti: string;
223
+ mult: string;
224
+ weekly: string;
225
+ dname: string;
226
+ uc: string;
227
+ lc: string;
228
+ strprc: string;
229
+ prcftr_d: string;
230
+ exptime: string;
231
+ token: string;
232
+ frzqty: string;
233
+ delmrg: string;
234
+ varmrg: string;
235
+ expmrg: string;
236
+ }
237
+ interface GetSecurityInfoFail {
238
+ stat: "Not_Ok";
239
+ request_time: string;
240
+ emsg: string;
241
+ }
242
+ type GetSecurityInfoResponse = GetSecurityInfoSuccess | GetSecurityInfoFail;
243
+ type GetTokenExpiry = "current" | "next" | "next-next" | "more-than-1-day" | "more-than-3-day" | "more-than-10-day";
244
+
245
+ declare const paths: {
246
+ readonly login: "QuickAuth";
247
+ readonly logout: "Logout";
248
+ readonly forgotPassword: "ForgotPassword";
249
+ readonly changePassword: "Changepwd";
250
+ readonly watchlist: "MWList";
251
+ readonly getWatchlist: "MarketWatch";
252
+ readonly searchScrip: "SearchScrip";
253
+ readonly userInfo: "UserDetails";
254
+ readonly clientInfo: "ClientDetails";
255
+ readonly quotes: "GetQuotes";
256
+ readonly addScripToWL: "AddMultiScripsToMW";
257
+ readonly removeScripFromWL: "DeleteMultiMWScrips";
258
+ readonly securityInfo: "GetSecurityInfo";
259
+ readonly placeOrder: "PlaceOrder";
260
+ readonly modifyOrder: "ModifyOrder";
261
+ readonly cancelOrder: "CancelOrder";
262
+ readonly exitSNOOrder: "ExitSNOOrder";
263
+ readonly historicData: "TPSeries";
264
+ readonly optionChain: "GetOptionChain";
265
+ readonly orderBook: "OrderBook";
266
+ readonly holding: "Holdings";
267
+ readonly limits: "Limits";
268
+ };
269
+ type Path = keyof typeof paths;
270
+
271
+ type LogType = "DEBUG" | "WARN" | "ERROR";
272
+ declare class Logger {
273
+ logPath: string;
274
+ maxSize: number;
275
+ fileName: string;
276
+ /**
277
+ *
278
+ * @param logFileName name to prepend the logs file with
279
+ * @param size max size of file (in bytes)
280
+ */
281
+ constructor(logFileName: string, size: number);
282
+ log(msg: string, logType?: LogType): void;
283
+ private checkLogSize;
284
+ private deleteOldestFile;
285
+ private checkPathExistance;
286
+ }
206
287
 
207
288
  type ShoonyaWSEvents = "connect" | "open" | "priceUpdate" | "orderUpdate" | "stopped" | "close" | "reconnect" | "error";
208
289
  declare interface Shoonya {
@@ -228,6 +309,7 @@ declare class Shoonya extends EventEmitter {
228
309
  private reconnectTimeout;
229
310
  private heartbeatTimeout;
230
311
  private lastWsMsgAt;
312
+ private autoReconnectTimeout;
231
313
  constructor(options?: {
232
314
  logging: boolean;
233
315
  /**
@@ -288,7 +370,7 @@ declare class Shoonya extends EventEmitter {
288
370
  * @returns
289
371
  */
290
372
  removeScripFromWatchList(listName: string, scrips: string[]): Promise<unknown>;
291
- getSecurityInfo(exchange: string, contractToken: string): Promise<unknown>;
373
+ getSecurityInfo(exchange: string, contractToken: string): Promise<GetSecurityInfoResponse>;
292
374
  placeOrder(details: OrderInput): Promise<PlaceOrder>;
293
375
  modifyOrder(orderDetail: MakeKeysRequired<Partial<OrderInput>, "exch" | "norenordno" | "tsym">): Promise<unknown>;
294
376
  cancelOrder(orderNo: string): Promise<unknown>;
@@ -329,7 +411,10 @@ declare class Shoonya extends EventEmitter {
329
411
  * @default 5
330
412
  */
331
413
  count?: string;
332
- optionExpiry?: "current" | "next" | "next-next" | "more-than-1-day";
414
+ /**
415
+ * @default current
416
+ */
417
+ optionExpiry?: GetTokenExpiry;
333
418
  }): Promise<{
334
419
  token: number;
335
420
  exchange: "NFO" | "MCX";
@@ -337,6 +422,21 @@ declare class Shoonya extends EventEmitter {
337
422
  }>;
338
423
  private getFormattedExpiry;
339
424
  private getNextFormattedDates;
425
+ /**
426
+ * Product Name
427
+ * (Select from ‘prarr’ Array provided in User Details response, and if same is allowed for selected, exchange.
428
+ * Show product display name, for user to select, and send corresponding prd in API call)
429
+ *
430
+ * ```
431
+ * `C` : CNC
432
+ * `M` : NRML
433
+ * `I` : MIS
434
+ * `B` : Bracket Order
435
+ * `H` : Cover Order
436
+ * ```
437
+ */
438
+ getAccountHolding(productName: "C" | "M" | "I" | "B" | "H"): Promise<any>;
439
+ getAccountLimits(params?: GetLimitsParam): Promise<GetLimitsResponseSuccess | GetLimitsResponseFail>;
340
440
  getLastWSMessage(): Date;
341
441
  getWSState(): {
342
442
  OPEN: boolean;
@@ -344,6 +444,7 @@ declare class Shoonya extends EventEmitter {
344
444
  CLOSING: boolean;
345
445
  CONNECTING: boolean;
346
446
  };
447
+ getSubscribedTokens(): string[];
347
448
  connectWS(): void;
348
449
  /**
349
450
  *
@@ -63,7 +63,9 @@ var paths = {
63
63
  exitSNOOrder: "ExitSNOOrder",
64
64
  historicData: "TPSeries",
65
65
  optionChain: "GetOptionChain",
66
- orderBook: "OrderBook"
66
+ orderBook: "OrderBook",
67
+ holding: "Holdings",
68
+ limits: "Limits"
67
69
  };
68
70
 
69
71
  // src/shoonya-sdk.ts
@@ -137,6 +139,25 @@ var Logger = class {
137
139
  };
138
140
  var logger_default = Logger;
139
141
 
142
+ // src/utils/parser.ts
143
+ var exampleObject = {
144
+ convertable: "57.3",
145
+ unconvertable: "So"
146
+ };
147
+ function parseKeysToNumber(obj) {
148
+ const newObj = {};
149
+ for (const key in obj) {
150
+ if (Number.isNaN(Number(obj[key]))) {
151
+ newObj[key] = String(obj[key]);
152
+ } else {
153
+ newObj[key] = Number(obj[key]);
154
+ }
155
+ }
156
+ return newObj;
157
+ }
158
+ __name(parseKeysToNumber, "parseKeysToNumber");
159
+ var parsedObj = parseKeysToNumber(exampleObject);
160
+
140
161
  // src/shoonya-sdk.ts
141
162
  var import_totp_generator = __toESM(require("totp-generator"));
142
163
  var Shoonya = class extends import_events.EventEmitter {
@@ -161,6 +182,7 @@ var Shoonya = class extends import_events.EventEmitter {
161
182
  reconnectTimeout;
162
183
  heartbeatTimeout;
163
184
  lastWsMsgAt;
185
+ autoReconnectTimeout = 1e3;
164
186
  constructor(options) {
165
187
  const {
166
188
  logging = false,
@@ -357,7 +379,10 @@ var Shoonya = class extends import_events.EventEmitter {
357
379
  exch: exchange,
358
380
  token: contractToken
359
381
  };
360
- return this.request("securityInfo", { data, key: this.accessToken });
382
+ return this.request("securityInfo", {
383
+ data,
384
+ key: this.accessToken
385
+ });
361
386
  }
362
387
  async placeOrder(details) {
363
388
  const data = {
@@ -459,10 +484,12 @@ var Shoonya = class extends import_events.EventEmitter {
459
484
  continue;
460
485
  if (optionExpiry === "next-next" && c < 3)
461
486
  continue;
462
- if (optionExpiry === "more-than-1-day") {
487
+ const match = optionExpiry.match(/more-than-(\d+)-day/);
488
+ if (match) {
463
489
  const dateNow = (/* @__PURE__ */ new Date()).getDate();
464
490
  const optionExpiryDate = unformattedDate.getDate();
465
- if (optionExpiryDate - dateNow === 0)
491
+ const check = parseInt(match[1], 10);
492
+ if (optionExpiryDate - dateNow < check)
466
493
  continue;
467
494
  }
468
495
  for (const { tsym, token } of optionChain.values) {
@@ -482,9 +509,9 @@ var Shoonya = class extends import_events.EventEmitter {
482
509
  }
483
510
  getNextFormattedDates(expiry) {
484
511
  let multiplier = 1;
485
- if (expiry === "next" || expiry === "more-than-1-day")
512
+ if (["next", "more-than-1-day", "more-than-3-day"].includes(expiry))
486
513
  multiplier = 2;
487
- if (expiry === "next-next")
514
+ if (["next-next", "more-than-10-day"].includes(expiry))
488
515
  multiplier = 3;
489
516
  let currentDate = /* @__PURE__ */ new Date();
490
517
  let dates = [];
@@ -496,6 +523,43 @@ var Shoonya = class extends import_events.EventEmitter {
496
523
  }
497
524
  return dates;
498
525
  }
526
+ /**
527
+ * Product Name
528
+ * (Select from ‘prarr’ Array provided in User Details response, and if same is allowed for selected, exchange.
529
+ * Show product display name, for user to select, and send corresponding prd in API call)
530
+ *
531
+ * ```
532
+ * `C` : CNC
533
+ * `M` : NRML
534
+ * `I` : MIS
535
+ * `B` : Bracket Order
536
+ * `H` : Cover Order
537
+ * ```
538
+ */
539
+ async getAccountHolding(productName) {
540
+ const data = {
541
+ uid: this.userId,
542
+ actid: this.accountId,
543
+ prd: productName
544
+ };
545
+ return await this.request("holding", { data, key: this.accessToken });
546
+ }
547
+ async getAccountLimits(params) {
548
+ const data = {
549
+ uid: this.userId,
550
+ actid: this.accountId,
551
+ ...params
552
+ };
553
+ const res = await this.request("limits", {
554
+ data,
555
+ key: this.accessToken
556
+ });
557
+ if (res.stat === "Not_Ok") {
558
+ return res;
559
+ }
560
+ const parsedObject = parseKeysToNumber(res);
561
+ return parsedObject;
562
+ }
499
563
  getLastWSMessage() {
500
564
  return this.lastWsMsgAt;
501
565
  }
@@ -507,6 +571,9 @@ var Shoonya = class extends import_events.EventEmitter {
507
571
  CONNECTING: this.ws && this.ws.readyState === this.ws.CONNECTING
508
572
  };
509
573
  }
574
+ getSubscribedTokens() {
575
+ return this.scripList;
576
+ }
510
577
  // WebSocket API
511
578
  connectWS() {
512
579
  if (this.getWSState().OPEN || this.getWSState().CONNECTING) {
@@ -530,6 +597,7 @@ var Shoonya = class extends import_events.EventEmitter {
530
597
  }, this.heartbeatTimeout.timeout);
531
598
  if (this.cronJobRunning) {
532
599
  this.subscribe(this.scripList);
600
+ this.logging && this.logger.log("Subscribed to " + JSON.stringify(this.scripList));
533
601
  return;
534
602
  }
535
603
  import_node_cron.default.schedule(
@@ -537,23 +605,17 @@ var Shoonya = class extends import_events.EventEmitter {
537
605
  async () => {
538
606
  this.cronJobRunning = true;
539
607
  try {
608
+ this.disconnect();
609
+ const { setTimeout: setTimeout2 } = await import("timers/promises");
610
+ await setTimeout2(this.autoReconnectTimeout);
540
611
  const cred = {
541
612
  apiKey: this.apiKey,
542
613
  password: this.password,
543
614
  twoFa: this.twoFa,
544
615
  userId: this.userId
545
616
  };
546
- this.logger.log("Old access token: " + this.accessToken);
547
617
  await this.login(cred);
548
- this.logger.log("New access token: " + this.accessToken);
549
- let msg2 = {
550
- t: "c",
551
- uid: this.userId,
552
- actid: this.accountId,
553
- source: "API",
554
- susertoken: this.accessToken
555
- };
556
- this.ws.send(JSON.stringify(msg2));
618
+ this.connectWS();
557
619
  this.emit("open", "opened ws connection");
558
620
  this.logging && this.logger.log("Token Refreshed");
559
621
  } catch (err) {
@@ -30,7 +30,9 @@ var paths = {
30
30
  exitSNOOrder: "ExitSNOOrder",
31
31
  historicData: "TPSeries",
32
32
  optionChain: "GetOptionChain",
33
- orderBook: "OrderBook"
33
+ orderBook: "OrderBook",
34
+ holding: "Holdings",
35
+ limits: "Limits"
34
36
  };
35
37
 
36
38
  // src/shoonya-sdk.ts
@@ -111,6 +113,25 @@ var Logger = class {
111
113
  };
112
114
  var logger_default = Logger;
113
115
 
116
+ // src/utils/parser.ts
117
+ var exampleObject = {
118
+ convertable: "57.3",
119
+ unconvertable: "So"
120
+ };
121
+ function parseKeysToNumber(obj) {
122
+ const newObj = {};
123
+ for (const key in obj) {
124
+ if (Number.isNaN(Number(obj[key]))) {
125
+ newObj[key] = String(obj[key]);
126
+ } else {
127
+ newObj[key] = Number(obj[key]);
128
+ }
129
+ }
130
+ return newObj;
131
+ }
132
+ __name(parseKeysToNumber, "parseKeysToNumber");
133
+ var parsedObj = parseKeysToNumber(exampleObject);
134
+
114
135
  // src/shoonya-sdk.ts
115
136
  import totp from "totp-generator";
116
137
  var Shoonya = class extends EventEmitter {
@@ -135,6 +156,7 @@ var Shoonya = class extends EventEmitter {
135
156
  reconnectTimeout;
136
157
  heartbeatTimeout;
137
158
  lastWsMsgAt;
159
+ autoReconnectTimeout = 1e3;
138
160
  constructor(options) {
139
161
  const {
140
162
  logging = false,
@@ -331,7 +353,10 @@ var Shoonya = class extends EventEmitter {
331
353
  exch: exchange,
332
354
  token: contractToken
333
355
  };
334
- return this.request("securityInfo", { data, key: this.accessToken });
356
+ return this.request("securityInfo", {
357
+ data,
358
+ key: this.accessToken
359
+ });
335
360
  }
336
361
  async placeOrder(details) {
337
362
  const data = {
@@ -433,10 +458,12 @@ var Shoonya = class extends EventEmitter {
433
458
  continue;
434
459
  if (optionExpiry === "next-next" && c < 3)
435
460
  continue;
436
- if (optionExpiry === "more-than-1-day") {
461
+ const match = optionExpiry.match(/more-than-(\d+)-day/);
462
+ if (match) {
437
463
  const dateNow = (/* @__PURE__ */ new Date()).getDate();
438
464
  const optionExpiryDate = unformattedDate.getDate();
439
- if (optionExpiryDate - dateNow === 0)
465
+ const check = parseInt(match[1], 10);
466
+ if (optionExpiryDate - dateNow < check)
440
467
  continue;
441
468
  }
442
469
  for (const { tsym, token } of optionChain.values) {
@@ -456,9 +483,9 @@ var Shoonya = class extends EventEmitter {
456
483
  }
457
484
  getNextFormattedDates(expiry) {
458
485
  let multiplier = 1;
459
- if (expiry === "next" || expiry === "more-than-1-day")
486
+ if (["next", "more-than-1-day", "more-than-3-day"].includes(expiry))
460
487
  multiplier = 2;
461
- if (expiry === "next-next")
488
+ if (["next-next", "more-than-10-day"].includes(expiry))
462
489
  multiplier = 3;
463
490
  let currentDate = /* @__PURE__ */ new Date();
464
491
  let dates = [];
@@ -470,6 +497,43 @@ var Shoonya = class extends EventEmitter {
470
497
  }
471
498
  return dates;
472
499
  }
500
+ /**
501
+ * Product Name
502
+ * (Select from ‘prarr’ Array provided in User Details response, and if same is allowed for selected, exchange.
503
+ * Show product display name, for user to select, and send corresponding prd in API call)
504
+ *
505
+ * ```
506
+ * `C` : CNC
507
+ * `M` : NRML
508
+ * `I` : MIS
509
+ * `B` : Bracket Order
510
+ * `H` : Cover Order
511
+ * ```
512
+ */
513
+ async getAccountHolding(productName) {
514
+ const data = {
515
+ uid: this.userId,
516
+ actid: this.accountId,
517
+ prd: productName
518
+ };
519
+ return await this.request("holding", { data, key: this.accessToken });
520
+ }
521
+ async getAccountLimits(params) {
522
+ const data = {
523
+ uid: this.userId,
524
+ actid: this.accountId,
525
+ ...params
526
+ };
527
+ const res = await this.request("limits", {
528
+ data,
529
+ key: this.accessToken
530
+ });
531
+ if (res.stat === "Not_Ok") {
532
+ return res;
533
+ }
534
+ const parsedObject = parseKeysToNumber(res);
535
+ return parsedObject;
536
+ }
473
537
  getLastWSMessage() {
474
538
  return this.lastWsMsgAt;
475
539
  }
@@ -481,6 +545,9 @@ var Shoonya = class extends EventEmitter {
481
545
  CONNECTING: this.ws && this.ws.readyState === this.ws.CONNECTING
482
546
  };
483
547
  }
548
+ getSubscribedTokens() {
549
+ return this.scripList;
550
+ }
484
551
  // WebSocket API
485
552
  connectWS() {
486
553
  if (this.getWSState().OPEN || this.getWSState().CONNECTING) {
@@ -504,6 +571,7 @@ var Shoonya = class extends EventEmitter {
504
571
  }, this.heartbeatTimeout.timeout);
505
572
  if (this.cronJobRunning) {
506
573
  this.subscribe(this.scripList);
574
+ this.logging && this.logger.log("Subscribed to " + JSON.stringify(this.scripList));
507
575
  return;
508
576
  }
509
577
  cron.schedule(
@@ -511,23 +579,17 @@ var Shoonya = class extends EventEmitter {
511
579
  async () => {
512
580
  this.cronJobRunning = true;
513
581
  try {
582
+ this.disconnect();
583
+ const { setTimeout: setTimeout2 } = await import("timers/promises");
584
+ await setTimeout2(this.autoReconnectTimeout);
514
585
  const cred = {
515
586
  apiKey: this.apiKey,
516
587
  password: this.password,
517
588
  twoFa: this.twoFa,
518
589
  userId: this.userId
519
590
  };
520
- this.logger.log("Old access token: " + this.accessToken);
521
591
  await this.login(cred);
522
- this.logger.log("New access token: " + this.accessToken);
523
- let msg2 = {
524
- t: "c",
525
- uid: this.userId,
526
- actid: this.accountId,
527
- source: "API",
528
- susertoken: this.accessToken
529
- };
530
- this.ws.send(JSON.stringify(msg2));
592
+ this.connectWS();
531
593
  this.emit("open", "opened ws connection");
532
594
  this.logging && this.logger.log("Token Refreshed");
533
595
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shoonya-sdk",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "description": "Wrapper around Shoonya API",
5
5
  "main": "dist/shoonya-sdk.js",
6
6
  "module": "dist/shoonya-sdk.mjs",