@adaptic/utils 0.0.379 → 0.0.381

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/dist/test.js CHANGED
@@ -6147,22 +6147,28 @@ class AlpacaMarketDataAPI extends EventEmitter {
6147
6147
  v1beta1url;
6148
6148
  stockStreamUrl = 'wss://stream.data.alpaca.markets/v2/sip'; // production values
6149
6149
  optionStreamUrl = 'wss://stream.data.alpaca.markets/v1beta3/options'; // production values
6150
+ cryptoStreamUrl = 'wss://stream.data.alpaca.markets/v1beta3/crypto/us'; // production values
6150
6151
  stockWs = null;
6151
6152
  optionWs = null;
6153
+ cryptoWs = null;
6152
6154
  stockSubscriptions = { trades: [], quotes: [], bars: [] };
6153
6155
  optionSubscriptions = { trades: [], quotes: [], bars: [] };
6156
+ cryptoSubscriptions = { trades: [], quotes: [], bars: [] };
6154
6157
  setMode(mode = 'production') {
6155
6158
  if (mode === 'sandbox') { // sandbox mode
6156
6159
  this.stockStreamUrl = 'wss://stream.data.sandbox.alpaca.markets/v2/sip';
6157
6160
  this.optionStreamUrl = 'wss://stream.data.sandbox.alpaca.markets/v1beta3/options';
6161
+ this.cryptoStreamUrl = 'wss://stream.data.sandbox.alpaca.markets/v1beta3/crypto/us';
6158
6162
  }
6159
6163
  else if (mode === 'test') { // test mode, can only use ticker FAKEPACA
6160
6164
  this.stockStreamUrl = 'wss://stream.data.alpaca.markets/v2/test';
6161
6165
  this.optionStreamUrl = 'wss://stream.data.alpaca.markets/v1beta3/options'; // there's no test mode for options
6166
+ this.cryptoStreamUrl = 'wss://stream.data.alpaca.markets/v1beta3/crypto/us'; // there's no test mode for crypto
6162
6167
  }
6163
6168
  else { // production
6164
6169
  this.stockStreamUrl = 'wss://stream.data.alpaca.markets/v2/sip';
6165
6170
  this.optionStreamUrl = 'wss://stream.data.alpaca.markets/v1beta3/options';
6171
+ this.cryptoStreamUrl = 'wss://stream.data.alpaca.markets/v1beta3/crypto/us';
6166
6172
  }
6167
6173
  }
6168
6174
  getMode() {
@@ -6204,14 +6210,26 @@ class AlpacaMarketDataAPI extends EventEmitter {
6204
6210
  return super.emit(event, ...args);
6205
6211
  }
6206
6212
  connect(streamType) {
6207
- const url = streamType === 'stock' ? this.stockStreamUrl : this.optionStreamUrl;
6213
+ let url;
6214
+ if (streamType === 'stock') {
6215
+ url = this.stockStreamUrl;
6216
+ }
6217
+ else if (streamType === 'option') {
6218
+ url = this.optionStreamUrl;
6219
+ }
6220
+ else {
6221
+ url = this.cryptoStreamUrl;
6222
+ }
6208
6223
  const ws = new WebSocket(url);
6209
6224
  if (streamType === 'stock') {
6210
6225
  this.stockWs = ws;
6211
6226
  }
6212
- else {
6227
+ else if (streamType === 'option') {
6213
6228
  this.optionWs = ws;
6214
6229
  }
6230
+ else {
6231
+ this.cryptoWs = ws;
6232
+ }
6215
6233
  ws.on('open', () => {
6216
6234
  log$1(`${streamType} stream connected`, { type: 'info' });
6217
6235
  const authMessage = {
@@ -6222,20 +6240,36 @@ class AlpacaMarketDataAPI extends EventEmitter {
6222
6240
  ws.send(JSON.stringify(authMessage));
6223
6241
  });
6224
6242
  ws.on('message', (data) => {
6225
- //log(`RAW MESSASGE: ${data.toString()}`);
6226
- const messages = JSON.parse(data.toString());
6243
+ const rawData = data.toString();
6244
+ let messages;
6245
+ try {
6246
+ messages = JSON.parse(rawData);
6247
+ }
6248
+ catch (e) {
6249
+ log$1(`${streamType} stream received invalid JSON: ${rawData.substring(0, 200)}`, { type: 'error' });
6250
+ return;
6251
+ }
6227
6252
  for (const message of messages) {
6228
6253
  if (message.T === 'success' && message.msg === 'authenticated') {
6229
6254
  log$1(`${streamType} stream authenticated`, { type: 'info' });
6230
6255
  this.sendSubscription(streamType);
6231
6256
  }
6257
+ else if (message.T === 'success' && message.msg === 'connected') {
6258
+ log$1(`${streamType} stream connected message received`, { type: 'debug' });
6259
+ }
6260
+ else if (message.T === 'subscription') {
6261
+ log$1(`${streamType} subscription confirmed: trades=${message.trades?.length || 0}, quotes=${message.quotes?.length || 0}, bars=${message.bars?.length || 0}`, { type: 'info' });
6262
+ }
6232
6263
  else if (message.T === 'error') {
6233
- log$1(`${streamType} stream error: ${message.msg}`, { type: 'error' });
6264
+ log$1(`${streamType} stream error: ${message.msg} (code: ${message.code}, raw: ${JSON.stringify(message)})`, { type: 'error' });
6234
6265
  }
6235
6266
  else if (message.S) {
6236
6267
  super.emit(`${streamType}-${message.T}`, message);
6237
6268
  super.emit(`${streamType}-data`, message);
6238
6269
  }
6270
+ else {
6271
+ log$1(`${streamType} received unknown message type: ${JSON.stringify(message)}`, { type: 'debug' });
6272
+ }
6239
6273
  }
6240
6274
  });
6241
6275
  ws.on('close', () => {
@@ -6243,9 +6277,12 @@ class AlpacaMarketDataAPI extends EventEmitter {
6243
6277
  if (streamType === 'stock') {
6244
6278
  this.stockWs = null;
6245
6279
  }
6246
- else {
6280
+ else if (streamType === 'option') {
6247
6281
  this.optionWs = null;
6248
6282
  }
6283
+ else {
6284
+ this.cryptoWs = null;
6285
+ }
6249
6286
  // Optional: implement reconnect logic
6250
6287
  });
6251
6288
  ws.on('error', (error) => {
@@ -6253,8 +6290,23 @@ class AlpacaMarketDataAPI extends EventEmitter {
6253
6290
  });
6254
6291
  }
6255
6292
  sendSubscription(streamType) {
6256
- const ws = streamType === 'stock' ? this.stockWs : this.optionWs;
6257
- const subscriptions = streamType === 'stock' ? this.stockSubscriptions : this.optionSubscriptions;
6293
+ let ws;
6294
+ let subscriptions;
6295
+ if (streamType === 'stock') {
6296
+ ws = this.stockWs;
6297
+ subscriptions = this.stockSubscriptions;
6298
+ }
6299
+ else if (streamType === 'option') {
6300
+ ws = this.optionWs;
6301
+ subscriptions = this.optionSubscriptions;
6302
+ }
6303
+ else {
6304
+ ws = this.cryptoWs;
6305
+ subscriptions = this.cryptoSubscriptions;
6306
+ }
6307
+ log$1(`sendSubscription called for ${streamType} (wsReady=${ws?.readyState === WebSocket.OPEN}, trades=${subscriptions.trades?.length || 0}, quotes=${subscriptions.quotes?.length || 0}, bars=${subscriptions.bars?.length || 0})`, {
6308
+ type: 'debug',
6309
+ });
6258
6310
  if (ws && ws.readyState === WebSocket.OPEN) {
6259
6311
  const subMessagePayload = {};
6260
6312
  if (subscriptions.trades.length > 0) {
@@ -6271,9 +6323,17 @@ class AlpacaMarketDataAPI extends EventEmitter {
6271
6323
  action: 'subscribe',
6272
6324
  ...subMessagePayload,
6273
6325
  };
6274
- ws.send(JSON.stringify(subMessage));
6326
+ const messageJson = JSON.stringify(subMessage);
6327
+ log$1(`Sending ${streamType} subscription: ${messageJson}`, { type: 'info' });
6328
+ ws.send(messageJson);
6329
+ }
6330
+ else {
6331
+ log$1(`No ${streamType} subscriptions to send (all arrays empty)`, { type: 'debug' });
6275
6332
  }
6276
6333
  }
6334
+ else {
6335
+ log$1(`Cannot send ${streamType} subscription: WebSocket not ready`, { type: 'warn' });
6336
+ }
6277
6337
  }
6278
6338
  connectStockStream() {
6279
6339
  if (!this.stockWs) {
@@ -6285,6 +6345,11 @@ class AlpacaMarketDataAPI extends EventEmitter {
6285
6345
  this.connect('option');
6286
6346
  }
6287
6347
  }
6348
+ connectCryptoStream() {
6349
+ if (!this.cryptoWs) {
6350
+ this.connect('crypto');
6351
+ }
6352
+ }
6288
6353
  disconnectStockStream() {
6289
6354
  if (this.stockWs) {
6290
6355
  this.stockWs.close();
@@ -6295,8 +6360,38 @@ class AlpacaMarketDataAPI extends EventEmitter {
6295
6360
  this.optionWs.close();
6296
6361
  }
6297
6362
  }
6363
+ disconnectCryptoStream() {
6364
+ if (this.cryptoWs) {
6365
+ this.cryptoWs.close();
6366
+ }
6367
+ }
6368
+ /**
6369
+ * Check if a specific stream is connected
6370
+ * @param streamType - The type of stream to check
6371
+ * @returns True if the stream is connected
6372
+ */
6373
+ isStreamConnected(streamType) {
6374
+ if (streamType === 'stock') {
6375
+ return this.stockWs !== null && this.stockWs.readyState === WebSocket.OPEN;
6376
+ }
6377
+ else if (streamType === 'option') {
6378
+ return this.optionWs !== null && this.optionWs.readyState === WebSocket.OPEN;
6379
+ }
6380
+ else {
6381
+ return this.cryptoWs !== null && this.cryptoWs.readyState === WebSocket.OPEN;
6382
+ }
6383
+ }
6298
6384
  subscribe(streamType, subscriptions) {
6299
- const currentSubscriptions = streamType === 'stock' ? this.stockSubscriptions : this.optionSubscriptions;
6385
+ let currentSubscriptions;
6386
+ if (streamType === 'stock') {
6387
+ currentSubscriptions = this.stockSubscriptions;
6388
+ }
6389
+ else if (streamType === 'option') {
6390
+ currentSubscriptions = this.optionSubscriptions;
6391
+ }
6392
+ else {
6393
+ currentSubscriptions = this.cryptoSubscriptions;
6394
+ }
6300
6395
  Object.entries(subscriptions).forEach(([key, value]) => {
6301
6396
  if (value) {
6302
6397
  currentSubscriptions[key] = [...new Set([...(currentSubscriptions[key] || []), ...value])];
@@ -6305,7 +6400,16 @@ class AlpacaMarketDataAPI extends EventEmitter {
6305
6400
  this.sendSubscription(streamType);
6306
6401
  }
6307
6402
  unsubscribe(streamType, subscriptions) {
6308
- const currentSubscriptions = streamType === 'stock' ? this.stockSubscriptions : this.optionSubscriptions;
6403
+ let currentSubscriptions;
6404
+ if (streamType === 'stock') {
6405
+ currentSubscriptions = this.stockSubscriptions;
6406
+ }
6407
+ else if (streamType === 'option') {
6408
+ currentSubscriptions = this.optionSubscriptions;
6409
+ }
6410
+ else {
6411
+ currentSubscriptions = this.cryptoSubscriptions;
6412
+ }
6309
6413
  Object.entries(subscriptions).forEach(([key, value]) => {
6310
6414
  if (value) {
6311
6415
  currentSubscriptions[key] = (currentSubscriptions[key] || []).filter(s => !value.includes(s));
@@ -6315,7 +6419,16 @@ class AlpacaMarketDataAPI extends EventEmitter {
6315
6419
  action: 'unsubscribe',
6316
6420
  ...subscriptions,
6317
6421
  };
6318
- const ws = streamType === 'stock' ? this.stockWs : this.optionWs;
6422
+ let ws;
6423
+ if (streamType === 'stock') {
6424
+ ws = this.stockWs;
6425
+ }
6426
+ else if (streamType === 'option') {
6427
+ ws = this.optionWs;
6428
+ }
6429
+ else {
6430
+ ws = this.cryptoWs;
6431
+ }
6319
6432
  if (ws && ws.readyState === WebSocket.OPEN) {
6320
6433
  ws.send(JSON.stringify(unsubMessage));
6321
6434
  }