firstock 1.0.9 → 1.1.0
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/Readme.md +1 -1
- package/dist/websockets/websocket_functions.js +10 -112
- package/dist/websockets/websockets.js +0 -8
- package/package.json +1 -1
package/Readme.md
CHANGED
|
@@ -21,17 +21,6 @@ exports.subscribeOptionGreeks = subscribeOptionGreeks;
|
|
|
21
21
|
exports.unsubscribeOptionGreeks = unsubscribeOptionGreeks;
|
|
22
22
|
const ws_1 = __importDefault(require("ws"));
|
|
23
23
|
const fs_1 = require("fs");
|
|
24
|
-
// Configure logging
|
|
25
|
-
const logger = {
|
|
26
|
-
debug: (msg) => console.debug(`${new Date().toISOString()} - ${msg}`),
|
|
27
|
-
info: (msg) => console.info(`${new Date().toISOString()} - ${msg}`),
|
|
28
|
-
warning: (msg) => console.warn(`${new Date().toISOString()} - ${msg}`),
|
|
29
|
-
error: (msg, err) => {
|
|
30
|
-
console.error(`[ERROR] ${new Date().toISOString()} - ${msg}`);
|
|
31
|
-
if (err)
|
|
32
|
-
console.error(err);
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
24
|
var UpdateType;
|
|
36
25
|
(function (UpdateType) {
|
|
37
26
|
UpdateType["ORDER"] = "order";
|
|
@@ -85,14 +74,12 @@ class ConnectionManager {
|
|
|
85
74
|
return __awaiter(this, void 0, void 0, function* () {
|
|
86
75
|
yield this.acquireLock();
|
|
87
76
|
if (this.indexMap.has(ws)) {
|
|
88
|
-
logger.info("Connection already exists");
|
|
89
77
|
this.releaseLock();
|
|
90
78
|
return this.indexMap.get(ws);
|
|
91
79
|
}
|
|
92
80
|
const safe = new SafeConn(ws);
|
|
93
81
|
this.connMap.set(safe, true);
|
|
94
82
|
this.indexMap.set(ws, safe);
|
|
95
|
-
logger.info("Connection added");
|
|
96
83
|
this.releaseLock();
|
|
97
84
|
return safe;
|
|
98
85
|
});
|
|
@@ -135,7 +122,6 @@ class ConnectionManager {
|
|
|
135
122
|
return __awaiter(this, void 0, void 0, function* () {
|
|
136
123
|
yield this.acquireLock();
|
|
137
124
|
if (this.indexMap.has(ws)) {
|
|
138
|
-
// Set shutdown flag BEFORE closing
|
|
139
125
|
_setShutdownFlag(ws);
|
|
140
126
|
const safe = this.indexMap.get(ws);
|
|
141
127
|
this.connMap.delete(safe);
|
|
@@ -148,13 +134,10 @@ class ConnectionManager {
|
|
|
148
134
|
catch (e) {
|
|
149
135
|
// Ignore errors during close
|
|
150
136
|
}
|
|
151
|
-
logger.info("Connection deleted");
|
|
152
|
-
// Clear subscription tracking
|
|
153
137
|
_clearTrackedSubscriptions(ws);
|
|
154
138
|
this.releaseLock();
|
|
155
139
|
return;
|
|
156
140
|
}
|
|
157
|
-
logger.info("Connection not found");
|
|
158
141
|
this.releaseLock();
|
|
159
142
|
});
|
|
160
143
|
}
|
|
@@ -178,7 +161,6 @@ function _trackSubscription(ws, tokens, subscriptionType) {
|
|
|
178
161
|
tracker[subscriptionType].push(token);
|
|
179
162
|
}
|
|
180
163
|
}
|
|
181
|
-
logger.debug(`Tracked subscription: ${subscriptionType} - ${tokens.join(', ')}`);
|
|
182
164
|
}
|
|
183
165
|
function _untrackSubscription(ws, tokens, subscriptionType) {
|
|
184
166
|
const wsId = _getWsId(ws);
|
|
@@ -191,7 +173,6 @@ function _untrackSubscription(ws, tokens, subscriptionType) {
|
|
|
191
173
|
}
|
|
192
174
|
}
|
|
193
175
|
}
|
|
194
|
-
logger.debug(`Untracked subscription: ${subscriptionType} - ${tokens.join(', ')}`);
|
|
195
176
|
}
|
|
196
177
|
function _getTrackedSubscriptions(ws) {
|
|
197
178
|
const wsId = _getWsId(ws);
|
|
@@ -201,7 +182,6 @@ function _clearTrackedSubscriptions(ws) {
|
|
|
201
182
|
const wsId = _getWsId(ws);
|
|
202
183
|
if (subscriptionTracker.has(wsId)) {
|
|
203
184
|
subscriptionTracker.delete(wsId);
|
|
204
|
-
logger.debug(`Cleared subscription tracking for connection ${wsId}`);
|
|
205
185
|
}
|
|
206
186
|
}
|
|
207
187
|
// Shutdown flags
|
|
@@ -209,7 +189,6 @@ const shutdownFlags = new Map();
|
|
|
209
189
|
function _setShutdownFlag(ws) {
|
|
210
190
|
const wsId = _getWsId(ws);
|
|
211
191
|
shutdownFlags.set(wsId, true);
|
|
212
|
-
logger.debug(`Shutdown flag set for connection ${wsId}`);
|
|
213
192
|
}
|
|
214
193
|
function _isShutdownRequested(ws) {
|
|
215
194
|
const wsId = _getWsId(ws);
|
|
@@ -219,7 +198,6 @@ function _clearShutdownFlag(ws) {
|
|
|
219
198
|
const wsId = _getWsId(ws);
|
|
220
199
|
if (shutdownFlags.has(wsId)) {
|
|
221
200
|
shutdownFlags.delete(wsId);
|
|
222
|
-
logger.debug(`Shutdown flag cleared for connection ${wsId}`);
|
|
223
201
|
}
|
|
224
202
|
}
|
|
225
203
|
function getUrlAndHeaderData(userId, config) {
|
|
@@ -231,7 +209,6 @@ function getUrlAndHeaderData(userId, config) {
|
|
|
231
209
|
const acceptLanguage = config.accept_language || 'en-US,en;q=0.9';
|
|
232
210
|
const origin = config.origin || '';
|
|
233
211
|
const baseUrl = `${scheme}://${host}${path}`;
|
|
234
|
-
logger.info(`Connecting to ${baseUrl}`);
|
|
235
212
|
let configJson;
|
|
236
213
|
try {
|
|
237
214
|
const configFile = (0, fs_1.readFileSync)('config.json', 'utf-8');
|
|
@@ -240,7 +217,6 @@ function getUrlAndHeaderData(userId, config) {
|
|
|
240
217
|
catch (e) {
|
|
241
218
|
return ['', null, new Error('Failed to read config.json')];
|
|
242
219
|
}
|
|
243
|
-
// Use the userId parameter to get the jKey
|
|
244
220
|
if (!configJson[userId]) {
|
|
245
221
|
return ['', null, new Error(`User ID '${userId}' not found in config.json`)];
|
|
246
222
|
}
|
|
@@ -279,11 +255,9 @@ function _identifyUpdateType(data) {
|
|
|
279
255
|
}
|
|
280
256
|
function _handleAuthenticationResponse(message) {
|
|
281
257
|
if (message.includes("Authentication successful")) {
|
|
282
|
-
logger.info("Authentication successful");
|
|
283
258
|
return true;
|
|
284
259
|
}
|
|
285
260
|
else if (message.includes('"status":"failed"')) {
|
|
286
|
-
logger.warning(`Authentication failed: ${message}`);
|
|
287
261
|
return false;
|
|
288
262
|
}
|
|
289
263
|
return true;
|
|
@@ -292,25 +266,15 @@ function readMessage(userId, ws, model, config) {
|
|
|
292
266
|
return __awaiter(this, void 0, void 0, function* () {
|
|
293
267
|
const maxRetries = config.max_websocket_connection_retries || 3;
|
|
294
268
|
const timeInterval = config.time_interval || 5;
|
|
295
|
-
let messageCount = 0;
|
|
296
269
|
let isAuthenticated = true;
|
|
297
|
-
logger.info(`Starting message reader for user ${userId}`);
|
|
298
|
-
logger.info(`Callbacks configured - Feed: ${model.subscribe_feed_data !== undefined}, ` +
|
|
299
|
-
`Order: ${model.order_data !== undefined}, ` +
|
|
300
|
-
`Position: ${model.position_data !== undefined}, ` +
|
|
301
|
-
`Option Greeks: ${model.subscribe_option_greeks_data !== undefined}`);
|
|
302
270
|
const messageHandler = (data) => __awaiter(this, void 0, void 0, function* () {
|
|
303
271
|
if (!(yield exports.connections.checkIfConnectionExists(ws))) {
|
|
304
|
-
logger.info("Connection no longer exists, stopping reader");
|
|
305
272
|
_clearShutdownFlag(ws);
|
|
306
273
|
return;
|
|
307
274
|
}
|
|
308
275
|
try {
|
|
309
276
|
const message = data.toString();
|
|
310
|
-
messageCount++;
|
|
311
|
-
logger.debug(`Message #${messageCount}: ${message.substring(0, 200)}...`);
|
|
312
277
|
if (!message) {
|
|
313
|
-
logger.debug("Empty message received, skipping");
|
|
314
278
|
return;
|
|
315
279
|
}
|
|
316
280
|
let parsedData;
|
|
@@ -318,14 +282,12 @@ function readMessage(userId, ws, model, config) {
|
|
|
318
282
|
parsedData = JSON.parse(message);
|
|
319
283
|
}
|
|
320
284
|
catch (e) {
|
|
321
|
-
logger.error(`JSON parse error: ${e.message}. Message: ${message.substring(0, 200)}`);
|
|
322
285
|
return;
|
|
323
286
|
}
|
|
324
287
|
// Handle authentication responses
|
|
325
288
|
if (parsedData.status && parsedData.message) {
|
|
326
289
|
if (_handleAuthenticationResponse(message)) {
|
|
327
290
|
isAuthenticated = true;
|
|
328
|
-
logger.info("Re-authentication successful");
|
|
329
291
|
}
|
|
330
292
|
return;
|
|
331
293
|
}
|
|
@@ -335,10 +297,9 @@ function readMessage(userId, ws, model, config) {
|
|
|
335
297
|
if (model.order_data) {
|
|
336
298
|
try {
|
|
337
299
|
model.order_data(parsedData);
|
|
338
|
-
logger.debug("Order callback invoked");
|
|
339
300
|
}
|
|
340
301
|
catch (e) {
|
|
341
|
-
|
|
302
|
+
// Ignore callback errors
|
|
342
303
|
}
|
|
343
304
|
}
|
|
344
305
|
}
|
|
@@ -346,10 +307,9 @@ function readMessage(userId, ws, model, config) {
|
|
|
346
307
|
if (model.position_data) {
|
|
347
308
|
try {
|
|
348
309
|
model.position_data(parsedData);
|
|
349
|
-
logger.debug("Position callback invoked");
|
|
350
310
|
}
|
|
351
311
|
catch (e) {
|
|
352
|
-
|
|
312
|
+
// Ignore callback errors
|
|
353
313
|
}
|
|
354
314
|
}
|
|
355
315
|
}
|
|
@@ -363,10 +323,9 @@ function readMessage(userId, ws, model, config) {
|
|
|
363
323
|
}
|
|
364
324
|
}
|
|
365
325
|
}
|
|
366
|
-
logger.debug("Option Greeks callback invoked");
|
|
367
326
|
}
|
|
368
327
|
catch (e) {
|
|
369
|
-
|
|
328
|
+
// Ignore callback errors
|
|
370
329
|
}
|
|
371
330
|
}
|
|
372
331
|
}
|
|
@@ -374,55 +333,39 @@ function readMessage(userId, ws, model, config) {
|
|
|
374
333
|
if (model.subscribe_feed_data) {
|
|
375
334
|
try {
|
|
376
335
|
model.subscribe_feed_data(parsedData);
|
|
377
|
-
logger.debug("Feed callback invoked");
|
|
378
336
|
}
|
|
379
337
|
catch (e) {
|
|
380
|
-
|
|
338
|
+
// Ignore callback errors
|
|
381
339
|
}
|
|
382
340
|
}
|
|
383
341
|
}
|
|
384
342
|
}
|
|
385
343
|
catch (e) {
|
|
386
|
-
|
|
344
|
+
// Ignore processing errors
|
|
387
345
|
}
|
|
388
346
|
});
|
|
389
347
|
const closeHandler = () => __awaiter(this, void 0, void 0, function* () {
|
|
390
|
-
// Check if shutdown was requested
|
|
391
348
|
if (_isShutdownRequested(ws)) {
|
|
392
|
-
logger.info("Connection closed intentionally");
|
|
393
349
|
_clearShutdownFlag(ws);
|
|
394
350
|
return;
|
|
395
351
|
}
|
|
396
|
-
// Unexpected disconnection - attempt reconnection
|
|
397
|
-
logger.warning("Unexpected disconnection");
|
|
398
|
-
console.log("\n Connection lost");
|
|
399
|
-
console.log("Attempting to reconnect...");
|
|
400
352
|
if (!(yield exports.connections.checkIfConnectionExists(ws))) {
|
|
401
|
-
logger.info("Connection no longer in manager, stopping reader");
|
|
402
353
|
return;
|
|
403
354
|
}
|
|
404
|
-
// Attempt reconnection
|
|
405
355
|
const newWs = yield _attemptReconnection(userId, ws, config, maxRetries, timeInterval, model);
|
|
406
356
|
if (newWs === null) {
|
|
407
|
-
logger.error("Failed to reconnect after all attempts");
|
|
408
|
-
console.log("✗ Failed to reconnect. Please restart the application.");
|
|
409
357
|
return;
|
|
410
358
|
}
|
|
411
|
-
logger.info("Reconnection successful, resuming message reading");
|
|
412
|
-
// Call user's reconnection callback if provided
|
|
413
359
|
if (model.on_reconnect) {
|
|
414
360
|
try {
|
|
415
361
|
model.on_reconnect(newWs);
|
|
416
|
-
logger.info("User's on_reconnect callback executed");
|
|
417
362
|
}
|
|
418
363
|
catch (callbackError) {
|
|
419
|
-
|
|
364
|
+
// Ignore callback errors
|
|
420
365
|
}
|
|
421
366
|
}
|
|
422
367
|
});
|
|
423
368
|
const errorHandler = (error) => __awaiter(this, void 0, void 0, function* () {
|
|
424
|
-
logger.error(`WebSocket error: ${error.message}`, error);
|
|
425
|
-
// Trigger close handler for reconnection logic
|
|
426
369
|
yield closeHandler();
|
|
427
370
|
});
|
|
428
371
|
ws.on('message', messageHandler);
|
|
@@ -432,28 +375,20 @@ function readMessage(userId, ws, model, config) {
|
|
|
432
375
|
}
|
|
433
376
|
function _attemptReconnection(userId, oldWs, config, maxRetries, timeInterval, model) {
|
|
434
377
|
return __awaiter(this, void 0, void 0, function* () {
|
|
435
|
-
// Get the actual tracked subscriptions
|
|
436
378
|
const tracked = _getTrackedSubscriptions(oldWs);
|
|
437
379
|
const allTokens = tracked.tokens;
|
|
438
380
|
const allOptionGreeksTokens = tracked.option_greeks_tokens;
|
|
439
|
-
logger.info(`Attempting reconnection. Will restore: ${allTokens.length} market tokens, ${allOptionGreeksTokens.length} option greeks tokens`);
|
|
440
381
|
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
441
382
|
if (!(yield exports.connections.checkIfConnectionExists(oldWs))) {
|
|
442
|
-
logger.info("Connection no longer exists in manager, stopping reconnection");
|
|
443
383
|
return null;
|
|
444
384
|
}
|
|
445
|
-
logger.info(`Reconnection attempt ${attempt}/${maxRetries}...`);
|
|
446
|
-
console.log(`Reconnection attempt ${attempt}/${maxRetries}...`);
|
|
447
385
|
yield new Promise(resolve => setTimeout(resolve, timeInterval * 1000));
|
|
448
386
|
try {
|
|
449
|
-
// Create new connection
|
|
450
387
|
const [baseUrl, headers, err] = getUrlAndHeaderData(userId, config);
|
|
451
388
|
if (err) {
|
|
452
|
-
logger.error(`Failed to get URL/headers: ${err.message}`);
|
|
453
389
|
continue;
|
|
454
390
|
}
|
|
455
391
|
const newWs = new ws_1.default(baseUrl, { headers });
|
|
456
|
-
// Wait for connection to open
|
|
457
392
|
yield new Promise((resolve, reject) => {
|
|
458
393
|
const timeout = setTimeout(() => {
|
|
459
394
|
reject(new Error('Connection timeout'));
|
|
@@ -467,8 +402,6 @@ function _attemptReconnection(userId, oldWs, config, maxRetries, timeInterval, m
|
|
|
467
402
|
reject(error);
|
|
468
403
|
});
|
|
469
404
|
});
|
|
470
|
-
logger.info(`New WebSocket connection created (attempt ${attempt})`);
|
|
471
|
-
// Wait for authentication message
|
|
472
405
|
const authMessage = yield new Promise((resolve, reject) => {
|
|
473
406
|
const timeout = setTimeout(() => {
|
|
474
407
|
reject(new Error('Authentication timeout'));
|
|
@@ -482,13 +415,11 @@ function _attemptReconnection(userId, oldWs, config, maxRetries, timeInterval, m
|
|
|
482
415
|
reject(error);
|
|
483
416
|
});
|
|
484
417
|
});
|
|
485
|
-
logger.info(`Reconnection auth message: ${authMessage}`);
|
|
486
418
|
if (!authMessage.includes("Authentication successful")) {
|
|
487
|
-
logger.warning(`Authentication failed on reconnect: ${authMessage}`);
|
|
488
419
|
newWs.close();
|
|
489
420
|
continue;
|
|
490
421
|
}
|
|
491
|
-
// Transfer subscription tracking
|
|
422
|
+
// Transfer subscription tracking
|
|
492
423
|
const oldWsId = _getWsId(oldWs);
|
|
493
424
|
const newWsId = _getWsId(newWs);
|
|
494
425
|
if (subscriptionTracker.has(oldWsId)) {
|
|
@@ -497,55 +428,29 @@ function _attemptReconnection(userId, oldWs, config, maxRetries, timeInterval, m
|
|
|
497
428
|
tokens: [...oldTracker.tokens],
|
|
498
429
|
option_greeks_tokens: [...oldTracker.option_greeks_tokens]
|
|
499
430
|
});
|
|
500
|
-
logger.debug(`Transferred subscription tracking from ${oldWsId} to ${newWsId}`);
|
|
501
431
|
}
|
|
502
|
-
// Update connection manager
|
|
503
432
|
yield exports.connections.deleteConnection(oldWs);
|
|
504
433
|
yield exports.connections.addConnection(newWs);
|
|
505
|
-
logger.info("Connection manager updated with new connection");
|
|
506
|
-
// Resubscribe to all tracked tokens
|
|
507
|
-
logger.info("Resubscribing to previous subscriptions...");
|
|
508
|
-
console.log("Resubscribing to previous feeds...");
|
|
509
434
|
// Resubscribe to market feed tokens
|
|
510
435
|
if (allTokens.length > 0) {
|
|
511
436
|
yield new Promise(resolve => setTimeout(resolve, 500));
|
|
512
437
|
const tokensStr = allTokens.join("|");
|
|
513
438
|
const msg = JSON.stringify({ action: "subscribe", tokens: tokensStr });
|
|
514
|
-
|
|
515
|
-
if (error) {
|
|
516
|
-
logger.error(`Failed to resubscribe to market tokens: ${error}`);
|
|
517
|
-
}
|
|
518
|
-
else {
|
|
519
|
-
logger.info(`Resubscribed to ${allTokens.length} market feed token(s): ${allTokens.join(', ')}`);
|
|
520
|
-
console.log(`✓ Resubscribed to ${allTokens.length} market feed token(s)`);
|
|
521
|
-
}
|
|
439
|
+
yield exports.connections.writeMessage(newWs, msg);
|
|
522
440
|
}
|
|
441
|
+
// Resubscribe to option Greeks tokens
|
|
523
442
|
if (allOptionGreeksTokens.length > 0) {
|
|
524
443
|
yield new Promise(resolve => setTimeout(resolve, 500));
|
|
525
444
|
const tokensStr = allOptionGreeksTokens.join("|");
|
|
526
445
|
const msg = JSON.stringify({ action: "subscribe-option-greeks", tokens: tokensStr });
|
|
527
|
-
|
|
528
|
-
if (error) {
|
|
529
|
-
logger.error(`Failed to resubscribe to option Greeks: ${error}`);
|
|
530
|
-
}
|
|
531
|
-
else {
|
|
532
|
-
logger.info(`Resubscribed to ${allOptionGreeksTokens.length} option Greeks token(s): ${allOptionGreeksTokens.join(', ')}`);
|
|
533
|
-
console.log(`✓ Resubscribed to ${allOptionGreeksTokens.length} option Greeks token(s)`);
|
|
534
|
-
}
|
|
446
|
+
yield exports.connections.writeMessage(newWs, msg);
|
|
535
447
|
}
|
|
536
448
|
yield new Promise(resolve => setTimeout(resolve, 1000));
|
|
537
|
-
logger.info("Reconnection and resubscription successful!");
|
|
538
|
-
console.log("✓ Reconnection complete - all subscriptions restored");
|
|
539
|
-
// IMPORTANT: Restart the message reader for the new WebSocket
|
|
540
449
|
readMessage(userId, newWs, model, config);
|
|
541
450
|
return newWs;
|
|
542
451
|
}
|
|
543
452
|
catch (e) {
|
|
544
|
-
logger.error(`Reconnection attempt ${attempt} failed: ${e.message}`, e);
|
|
545
|
-
console.log(`✗ Attempt ${attempt} failed: ${e.message.substring(0, 100)}...`);
|
|
546
453
|
if (attempt === maxRetries) {
|
|
547
|
-
logger.error("Max reconnection attempts reached");
|
|
548
|
-
console.log(`✗ All ${maxRetries} reconnection attempts failed`);
|
|
549
454
|
return null;
|
|
550
455
|
}
|
|
551
456
|
}
|
|
@@ -574,12 +479,10 @@ function subscribe(ws, tokens) {
|
|
|
574
479
|
action: "subscribe",
|
|
575
480
|
tokens: tokensStr
|
|
576
481
|
});
|
|
577
|
-
logger.info(`Sending subscribe message: ${msg}`);
|
|
578
482
|
const error = yield exports.connections.writeMessage(ws, msg);
|
|
579
483
|
if (error) {
|
|
580
484
|
return { error: { message: error } };
|
|
581
485
|
}
|
|
582
|
-
logger.info("Subscribe message sent successfully");
|
|
583
486
|
return null;
|
|
584
487
|
});
|
|
585
488
|
}
|
|
@@ -598,7 +501,6 @@ function unsubscribe(ws, tokens) {
|
|
|
598
501
|
action: "unsubscribe",
|
|
599
502
|
tokens: tokensStr
|
|
600
503
|
});
|
|
601
|
-
logger.info(`Sending unsubscribe message: ${msg}`);
|
|
602
504
|
const error = yield exports.connections.writeMessage(ws, msg);
|
|
603
505
|
if (error) {
|
|
604
506
|
return { error: { message: error } };
|
|
@@ -627,12 +529,10 @@ function subscribeOptionGreeks(ws, tokens) {
|
|
|
627
529
|
action: "subscribe-option-greeks",
|
|
628
530
|
tokens: tokensStr
|
|
629
531
|
});
|
|
630
|
-
logger.info(`Sending subscribe option greeks message: ${msg}`);
|
|
631
532
|
const error = yield exports.connections.writeMessage(ws, msg);
|
|
632
533
|
if (error) {
|
|
633
534
|
return { error: { message: error } };
|
|
634
535
|
}
|
|
635
|
-
logger.info("Subscribe option greeks message sent successfully");
|
|
636
536
|
return null;
|
|
637
537
|
});
|
|
638
538
|
}
|
|
@@ -657,12 +557,10 @@ function unsubscribeOptionGreeks(ws, tokens) {
|
|
|
657
557
|
action: "unsubscribe-option-greeks",
|
|
658
558
|
tokens: tokensStr
|
|
659
559
|
});
|
|
660
|
-
logger.info(`Sending unsubscribe option greeks message: ${msg}`);
|
|
661
560
|
const error = yield exports.connections.writeMessage(ws, msg);
|
|
662
561
|
if (error) {
|
|
663
562
|
return { error: { message: error } };
|
|
664
563
|
}
|
|
665
|
-
logger.info("Unsubscribe option greeks message sent successfully");
|
|
666
564
|
return null;
|
|
667
565
|
});
|
|
668
566
|
}
|
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.FirstockWebSocket = void 0;
|
|
4
|
-
const logger = {
|
|
5
|
-
info: (msg) => console.info(`[INFO] ${new Date().toISOString()} - ${msg}`),
|
|
6
|
-
error: (msg, err) => {
|
|
7
|
-
console.error(`[ERROR] ${new Date().toISOString()} - ${msg}`);
|
|
8
|
-
if (err)
|
|
9
|
-
console.error(err);
|
|
10
|
-
}
|
|
11
|
-
};
|
|
12
4
|
class FirstockWebSocket {
|
|
13
5
|
constructor(options = {}) {
|
|
14
6
|
this.tokens = options.tokens || [];
|