@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/index.cjs +125 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +125 -12
- package/dist/index.mjs.map +1 -1
- package/dist/test.js +125 -12
- package/dist/test.js.map +1 -1
- package/dist/types/alpaca-market-data-api.d.ts +16 -3
- package/dist/types/alpaca-market-data-api.d.ts.map +1 -1
- package/dist/types/types/alpaca-types.d.ts +89 -0
- package/dist/types/types/alpaca-types.d.ts.map +1 -1
- package/package.json +2 -1
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
|
-
|
|
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
|
-
|
|
6226
|
-
|
|
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
|
-
|
|
6257
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
}
|