@openfeed/sdk-js 1.2.3 → 1.3.2

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.
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
+
5
+ ### [1.2.3](https://github.com/openfeed-org/sdk-js/compare/1.2.2...1.2.3) (2024-12-09)
6
+
7
+
8
+ ### Features
9
+
10
+ * Added heartbeat listener. ([960bd7a](https://github.com/openfeed-org/sdk-js/commit/960bd7ad27b0cd1c5dfe9714a315d72fdad588b0))
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
+
5
+ ## [1.3.0](https://github.com/openfeed-org/sdk-js/compare/1.2.3...1.3.0) (2025-01-08)
6
+
7
+
8
+ ### Features
9
+
10
+ * regenarate files from proto to add new properties ([1c7e22f](https://github.com/openfeed-org/sdk-js/commit/1c7e22fa0a06d129a44abff90bdce72e3d1976de))
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
+
5
+ ### [1.3.1](https://github.com/openfeed-org/sdk-js/compare/1.3.0...1.3.1) (2025-01-08)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * fix type issues ([926eb95](https://github.com/openfeed-org/sdk-js/commit/926eb95db5d3aefa743610c00531438aa8fa46d8))
package/CHANGELOG.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
- ### [1.2.3](https://github.com/openfeed-org/sdk-js/compare/1.2.2...1.2.3) (2024-12-09)
5
+ ### [1.3.2](https://github.com/openfeed-org/sdk-js/compare/1.3.1...1.3.2) (2025-01-23)
6
6
 
7
7
 
8
- ### Features
8
+ ### Bug Fixes
9
9
 
10
- * Added heartbeat listener. ([960bd7a](https://github.com/openfeed-org/sdk-js/commit/960bd7ad27b0cd1c5dfe9714a315d72fdad588b0))
10
+ * address issues with subscription type and error subscription messages, expand tests ([8c82453](https://github.com/openfeed-org/sdk-js/commit/8c82453f18435418b30d1f5c37a6106bb1e50a65))
package/DOCUMENTATION.md CHANGED
@@ -147,7 +147,7 @@ enum SubscriptionType {
147
147
  DEPTH_PRICE = 3,
148
148
  DEPTH_ORDER = 4,
149
149
  TRADES = 5,
150
- CUMLATIVE_VOLUME = 6,
150
+ CUMULATIVE_VOLUME = 6,
151
151
  OHLC = 7,
152
152
  OHLC_NON_REGULAR = 8,
153
153
  }
@@ -158,12 +158,12 @@ enum SubscriptionType {
158
158
  Now that we know how to use the listener and client objects, let's put together a little demo that subscribes to all MSFT messages and prints what's happening to the console:
159
159
 
160
160
  ```ts
161
- import { OpenFeedClient } from "./connection/connection";
161
+ import { OpenFeedClient } from "./connection/client";
162
162
 
163
163
  import { Service } from "../generated/openfeed";
164
164
  import { SubscriptionType } from "../generated/openfeed_api";
165
165
  import { OpenFeedListeners } from "./connection/listeners";
166
- import { IOpenFeedLogger } from "./connection/connection_interfaces";
166
+ import { IOpenFeedLogger } from "./connection/interfaces";
167
167
 
168
168
  const connect = async () => {
169
169
  const logger: IOpenFeedLogger = console;
@@ -424,6 +424,7 @@ export interface ClearBook {
424
424
  export interface InstrumentStatus {
425
425
  /** UTC Timestamp, nano seconds since Unix epoch */
426
426
  transactionTime: Long;
427
+ /** / Trading status. */
427
428
  tradingStatus: InstrumentTradingStatus;
428
429
  /** UTC Timestamp, nano seconds since Unix epoch */
429
430
  openingTime: Long;
@@ -431,6 +432,8 @@ export interface InstrumentStatus {
431
432
  /** / Date only, format 2012-07-04 -> 20120704 */
432
433
  tradeDate: number;
433
434
  regulationSHOShortSalePriceTest: RegulationSHOShortSalePriceTest;
435
+ /** / Prior trading status for the instrument. */
436
+ priorTradingStatus: InstrumentTradingStatus;
434
437
  }
435
438
  /**
436
439
  * / Best Bid and Offer.
@@ -31,9 +31,10 @@ export declare enum SubscriptionType {
31
31
  DEPTH_PRICE = 3,
32
32
  DEPTH_ORDER = 4,
33
33
  TRADES = 5,
34
- CUMLATIVE_VOLUME = 6,
34
+ CUMULATIVE_VOLUME = 6,
35
35
  OHLC = 7,
36
36
  OHLC_NON_REGULAR = 8,
37
+ SETTLEMENT = 9,
37
38
  UNRECOGNIZED = -1
38
39
  }
39
40
  /** / Symbol type for the subscription filter. */
@@ -203,6 +204,10 @@ export interface SubscriptionRequest_Request {
203
204
  bulkSubscriptionFilter: BulkSubscriptionFilter[];
204
205
  /** / Filter for Spread Types */
205
206
  spreadTypeFilter: string[];
207
+ /** / Do not send instrument(s) on successful subscription */
208
+ subscriptionDoNotSendInstruments: boolean;
209
+ /** / Do not send market snapshot(s) on successful subscription */
210
+ subscriptionDoNotSendSnapshots: boolean;
206
211
  }
207
212
  export interface SubscriptionResponse {
208
213
  correlationId: Long;
@@ -240,10 +245,14 @@ export interface ListSubscriptionsResponse_Subscription {
240
245
  subscriptionId: string;
241
246
  symbolId: string;
242
247
  marketId: Long;
243
- symbols: string[];
248
+ symbolCounts: ListSubscriptionsResponse_SymbolCount[];
244
249
  exchange: string;
245
250
  root: string;
246
251
  }
252
+ export interface ListSubscriptionsResponse_SymbolCount {
253
+ symbol: string;
254
+ count: number;
255
+ }
247
256
  export declare const OpenfeedGatewayRequestEncode: {
248
257
  encode(message: OpenfeedGatewayRequest, writer?: _m0.Writer): _m0.Writer;
249
258
  }, OpenfeedGatewayRequestDecode: {
@@ -354,3 +363,8 @@ export declare const ListSubscriptionsResponse_SubscriptionEncode: {
354
363
  }, ListSubscriptionsResponse_SubscriptionDecode: {
355
364
  decode(input: _m0.Reader | Uint8Array, length?: number): ListSubscriptionsResponse_Subscription;
356
365
  };
366
+ export declare const ListSubscriptionsResponse_SymbolCountEncode: {
367
+ encode(message: ListSubscriptionsResponse_SymbolCount, writer?: _m0.Writer): _m0.Writer;
368
+ }, ListSubscriptionsResponse_SymbolCountDecode: {
369
+ decode(input: _m0.Reader | Uint8Array, length?: number): ListSubscriptionsResponse_SymbolCount;
370
+ };
@@ -1 +1 @@
1
- export declare const version = "1.2.3";
1
+ export declare const version = "1.3.2";
package/dist/index.js CHANGED
@@ -933,7 +933,6 @@ Long.fromBytesBE = function fromBytesBE(bytes, unsigned) {
933
933
  unsigned
934
934
  );
935
935
  };
936
- const toT = (obj) => obj;
937
936
  var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
938
937
  function getDefaultExportFromCjs(x) {
939
938
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
@@ -4267,7 +4266,8 @@ function createBaseInstrumentStatus() {
4267
4266
  openingTime: Long.ZERO,
4268
4267
  note: "",
4269
4268
  tradeDate: 0,
4270
- regulationSHOShortSalePriceTest: 0
4269
+ regulationSHOShortSalePriceTest: 0,
4270
+ priorTradingStatus: 0
4271
4271
  };
4272
4272
  }
4273
4273
  const InstrumentStatusDecode = {
@@ -4314,6 +4314,12 @@ const InstrumentStatusDecode = {
4314
4314
  }
4315
4315
  message.regulationSHOShortSalePriceTest = reader2.int32();
4316
4316
  continue;
4317
+ case 15:
4318
+ if (tag !== 120) {
4319
+ break;
4320
+ }
4321
+ message.priorTradingStatus = reader2.int32();
4322
+ continue;
4317
4323
  }
4318
4324
  if ((tag & 7) === 4 || tag === 0) {
4319
4325
  break;
@@ -7208,9 +7214,10 @@ var SubscriptionType = /* @__PURE__ */ ((SubscriptionType2) => {
7208
7214
  SubscriptionType2[SubscriptionType2["DEPTH_PRICE"] = 3] = "DEPTH_PRICE";
7209
7215
  SubscriptionType2[SubscriptionType2["DEPTH_ORDER"] = 4] = "DEPTH_ORDER";
7210
7216
  SubscriptionType2[SubscriptionType2["TRADES"] = 5] = "TRADES";
7211
- SubscriptionType2[SubscriptionType2["CUMLATIVE_VOLUME"] = 6] = "CUMLATIVE_VOLUME";
7217
+ SubscriptionType2[SubscriptionType2["CUMULATIVE_VOLUME"] = 6] = "CUMULATIVE_VOLUME";
7212
7218
  SubscriptionType2[SubscriptionType2["OHLC"] = 7] = "OHLC";
7213
7219
  SubscriptionType2[SubscriptionType2["OHLC_NON_REGULAR"] = 8] = "OHLC_NON_REGULAR";
7220
+ SubscriptionType2[SubscriptionType2["SETTLEMENT"] = 9] = "SETTLEMENT";
7214
7221
  SubscriptionType2[SubscriptionType2["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
7215
7222
  return SubscriptionType2;
7216
7223
  })(SubscriptionType || {});
@@ -7917,6 +7924,12 @@ const SubscriptionRequest_RequestEncode = {
7917
7924
  for (const v of message.spreadTypeFilter) {
7918
7925
  writer2.uint32(114).string(v);
7919
7926
  }
7927
+ if (message.subscriptionDoNotSendInstruments === true) {
7928
+ writer2.uint32(120).bool(message.subscriptionDoNotSendInstruments);
7929
+ }
7930
+ if (message.subscriptionDoNotSendSnapshots === true) {
7931
+ writer2.uint32(128).bool(message.subscriptionDoNotSendSnapshots);
7932
+ }
7920
7933
  return writer2;
7921
7934
  }
7922
7935
  };
@@ -8120,7 +8133,7 @@ const ListSubscriptionsResponse_SessionDecode = {
8120
8133
  }
8121
8134
  };
8122
8135
  function createBaseListSubscriptionsResponse_Subscription() {
8123
- return { subscriptionId: "", symbolId: "", marketId: Long.ZERO, symbols: [], exchange: "", root: "" };
8136
+ return { subscriptionId: "", symbolId: "", marketId: Long.ZERO, symbolCounts: [], exchange: "", root: "" };
8124
8137
  }
8125
8138
  const ListSubscriptionsResponse_SubscriptionDecode = {
8126
8139
  decode(input, length) {
@@ -8152,7 +8165,7 @@ const ListSubscriptionsResponse_SubscriptionDecode = {
8152
8165
  if (tag !== 34) {
8153
8166
  break;
8154
8167
  }
8155
- message.symbols.push(reader2.string());
8168
+ message.symbolCounts.push(ListSubscriptionsResponse_SymbolCountDecode.decode(reader2, reader2.uint32()));
8156
8169
  continue;
8157
8170
  case 10:
8158
8171
  if (tag !== 82) {
@@ -8175,6 +8188,38 @@ const ListSubscriptionsResponse_SubscriptionDecode = {
8175
8188
  return message;
8176
8189
  }
8177
8190
  };
8191
+ function createBaseListSubscriptionsResponse_SymbolCount() {
8192
+ return { symbol: "", count: 0 };
8193
+ }
8194
+ const ListSubscriptionsResponse_SymbolCountDecode = {
8195
+ decode(input, length) {
8196
+ const reader2 = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
8197
+ let end2 = length === void 0 ? reader2.len : reader2.pos + length;
8198
+ const message = createBaseListSubscriptionsResponse_SymbolCount();
8199
+ while (reader2.pos < end2) {
8200
+ const tag = reader2.uint32();
8201
+ switch (tag >>> 3) {
8202
+ case 1:
8203
+ if (tag !== 10) {
8204
+ break;
8205
+ }
8206
+ message.symbol = reader2.string();
8207
+ continue;
8208
+ case 2:
8209
+ if (tag !== 16) {
8210
+ break;
8211
+ }
8212
+ message.count = reader2.sint32();
8213
+ continue;
8214
+ }
8215
+ if ((tag & 7) === 4 || tag === 0) {
8216
+ break;
8217
+ }
8218
+ reader2.skipType(tag & 7);
8219
+ }
8220
+ return message;
8221
+ }
8222
+ };
8178
8223
  if (_m0.util.Long !== Long) {
8179
8224
  _m0.util.Long = Long;
8180
8225
  _m0.configure();
@@ -8213,7 +8258,15 @@ class ResolutionSource {
8213
8258
  return this.onError;
8214
8259
  }
8215
8260
  }
8216
- const version = "1.2.3";
8261
+ const _CorrelationId = class _CorrelationId {
8262
+ };
8263
+ __publicField(_CorrelationId, "correlationId", Long.fromNumber(-1));
8264
+ __publicField(_CorrelationId, "create", () => {
8265
+ _CorrelationId.correlationId = _CorrelationId.correlationId.add(1);
8266
+ return _CorrelationId.correlationId;
8267
+ });
8268
+ let CorrelationId = _CorrelationId;
8269
+ const toT = (obj) => obj;
8217
8270
  const send = (socket, message) => {
8218
8271
  socket.send(OpenfeedGatewayRequestEncode.encode(toT(message)).finish());
8219
8272
  };
@@ -8230,14 +8283,11 @@ const receive = (msgEvent) => {
8230
8283
  }
8231
8284
  return res;
8232
8285
  };
8233
- const _CorrelationId = class _CorrelationId {
8286
+ const TIME = {
8287
+ RECONNECT: 5e3,
8288
+ CONNECTION_TIMEOUT: 15e3,
8289
+ SUBSCRIPTION_RETRY: 100
8234
8290
  };
8235
- __publicField(_CorrelationId, "correlationId", Long.fromNumber(-1));
8236
- __publicField(_CorrelationId, "create", () => {
8237
- _CorrelationId.correlationId = _CorrelationId.correlationId.add(1);
8238
- return _CorrelationId.correlationId;
8239
- });
8240
- let CorrelationId = _CorrelationId;
8241
8291
  class DuplicateLoginError extends Error {
8242
8292
  get name() {
8243
8293
  return this.constructor.name;
@@ -8267,7 +8317,7 @@ class OpenFeedConnection {
8267
8317
  for (; ; ) {
8268
8318
  let timeoutId = null;
8269
8319
  const waitPromise = new Promise((resolve) => {
8270
- timeoutId = setTimeout(resolve, 15e3);
8320
+ timeoutId = setTimeout(resolve, TIME.CONNECTION_TIMEOUT);
8271
8321
  });
8272
8322
  try {
8273
8323
  await Promise.race([waitPromise, this.whenDisconnectedSource.whenCompleted]);
@@ -8377,7 +8427,9 @@ class OpenFeedConnection {
8377
8427
  snapshotIntervalSeconds,
8378
8428
  instrumentType: [],
8379
8429
  bulkSubscriptionFilter: [],
8380
- spreadTypeFilter: []
8430
+ spreadTypeFilter: [],
8431
+ subscriptionDoNotSendInstruments: false,
8432
+ subscriptionDoNotSendSnapshots: false
8381
8433
  };
8382
8434
  if (symbols) {
8383
8435
  for (const symbol of symbols) {
@@ -8436,7 +8488,7 @@ class OpenFeedConnection {
8436
8488
  throw new Error(`Subscription ID ${subscriptionId} does not exist.`);
8437
8489
  }
8438
8490
  const [originalRequest, sub] = subscription;
8439
- return this.fireUnsubscribeWhenReady(originalRequest, sub);
8491
+ this.fireUnsubscribeWhenReady(originalRequest, sub);
8440
8492
  });
8441
8493
  __publicField(this, "getExchanges", async () => {
8442
8494
  var _a;
@@ -8548,6 +8600,23 @@ class OpenFeedConnection {
8548
8600
  }
8549
8601
  }
8550
8602
  }
8603
+ const version = "1.3.2";
8604
+ const getClientVersion = async (clientId) => {
8605
+ var _a, _b, _c, _d, _e, _f;
8606
+ let platformDescription;
8607
+ if (typeof window !== "undefined") {
8608
+ platformDescription = navigator.userAgent;
8609
+ } else {
8610
+ const os = await import("./empty-411f875a.js");
8611
+ try {
8612
+ platformDescription = `Node.js ${process.version}; ${(_a = os.version) == null ? void 0 : _a.call(os)} ${(_b = os.release) == null ? void 0 : _b.call(os)}; ${(_c = os.arch) == null ? void 0 : _c.call(os)};`;
8613
+ } catch (e) {
8614
+ platformDescription = `Unknown OS; ${((_d = os.version) == null ? void 0 : _d.call(os)) ?? ""} ${((_e = os.release) == null ? void 0 : _e.call(os)) ?? ""}; ${((_f = os.arch) == null ? void 0 : _f.call(os)) ?? ""};`;
8615
+ }
8616
+ }
8617
+ const clientVersion = `sdk-js:${version};client-id:${clientId ?? "default"};platform:${platformDescription}`;
8618
+ return clientVersion;
8619
+ };
8551
8620
  class OpenFeedClient {
8552
8621
  constructor(url, username, password, listeners, logger, clientId) {
8553
8622
  __publicField(this, "socket", null);
@@ -8559,21 +8628,9 @@ class OpenFeedClient {
8559
8628
  __publicField(this, "subscribeResetSource", new ResolutionSource());
8560
8629
  __publicField(this, "subscriptions", /* @__PURE__ */ new Map());
8561
8630
  __publicField(this, "onOpen", async () => {
8562
- var _a, _b, _c, _d, _e, _f;
8563
8631
  if (!this.socket)
8564
8632
  return;
8565
- let platformDescription;
8566
- if (typeof window !== "undefined") {
8567
- platformDescription = navigator.userAgent;
8568
- } else {
8569
- const os = await import("./empty-411f875a.js");
8570
- try {
8571
- platformDescription = `Node.js ${process.version}; ${(_a = os.version) == null ? void 0 : _a.call(os)} ${(_b = os.release) == null ? void 0 : _b.call(os)}; ${(_c = os.arch) == null ? void 0 : _c.call(os)};`;
8572
- } catch (e) {
8573
- platformDescription = `Unknown OS; ${((_d = os.version) == null ? void 0 : _d.call(os)) ?? ""} ${((_e = os.release) == null ? void 0 : _e.call(os)) ?? ""}; ${((_f = os.arch) == null ? void 0 : _f.call(os)) ?? ""};`;
8574
- }
8575
- }
8576
- const clientVersion = `sdk-js:${version};client-id:${this.clientId ?? "default"};platform:${platformDescription}`;
8633
+ const clientVersion = await getClientVersion(this.clientId);
8577
8634
  const loginRequest = {
8578
8635
  loginRequest: {
8579
8636
  correlationId: CorrelationId.create(),
@@ -8635,7 +8692,6 @@ class OpenFeedClient {
8635
8692
  __publicField(this, "runConnectLoop", async () => {
8636
8693
  var _a, _b;
8637
8694
  for (; ; ) {
8638
- let timeoutId = null;
8639
8695
  if (this.socket) {
8640
8696
  if (this.socket.readyState !== WebSocket$1.CLOSED && this.socket.readyState !== WebSocket$1.CLOSING) {
8641
8697
  this.socket.close(1e3, "Closed from socket loop");
@@ -8685,15 +8741,9 @@ class OpenFeedClient {
8685
8741
  this.loopResetSource = new ResolutionSource();
8686
8742
  this.subscribeResetSource.resolve();
8687
8743
  this.subscribeResetSource = new ResolutionSource();
8688
- try {
8689
- await new Promise((resolve) => {
8690
- timeoutId = setTimeout(resolve, 5e3);
8691
- });
8692
- } finally {
8693
- if (timeoutId) {
8694
- clearTimeout(timeoutId);
8695
- }
8696
- }
8744
+ await new Promise((resolve) => {
8745
+ setTimeout(resolve, TIME.RECONNECT);
8746
+ });
8697
8747
  }
8698
8748
  });
8699
8749
  __publicField(this, "cleanUp", () => {
@@ -8706,11 +8756,10 @@ class OpenFeedClient {
8706
8756
  __publicField(this, "runSubscribeLoop", async (service2, subscriptionType, snapshotIntervalSeconds, symbols, marketIds, exchanges, channels, cancelSource) => {
8707
8757
  var _a;
8708
8758
  for (; ; ) {
8709
- let timeoutId = null;
8710
8759
  try {
8711
8760
  const connection = await Promise.race([this.connection, cancelSource.whenCompleted]);
8712
8761
  if (cancelSource.completed || /* can't actually happen */
8713
- !(connection instanceof OpenFeedConnection)) {
8762
+ !connection) {
8714
8763
  return;
8715
8764
  }
8716
8765
  const subscriptionId = connection.subscribe(
@@ -8733,12 +8782,8 @@ class OpenFeedClient {
8733
8782
  } catch (error) {
8734
8783
  (_a = this.logger) == null ? void 0 : _a.warn("Subscription error:", error);
8735
8784
  await new Promise((resolve) => {
8736
- timeoutId = setTimeout(resolve, 100);
8785
+ setTimeout(resolve, TIME.SUBSCRIPTION_RETRY);
8737
8786
  });
8738
- } finally {
8739
- if (timeoutId) {
8740
- clearTimeout(timeoutId);
8741
- }
8742
8787
  }
8743
8788
  }
8744
8789
  });
@@ -8801,7 +8846,6 @@ const IDGetters = [
8801
8846
  ];
8802
8847
  class OpenFeedListeners {
8803
8848
  constructor() {
8804
- __publicField(this, "instrumentBySymbol", /* @__PURE__ */ new Map());
8805
8849
  __publicField(this, "instrumentByMarketId", /* @__PURE__ */ new Map());
8806
8850
  __publicField(this, "addDetails", (message) => {
8807
8851
  var _a, _b, _c;
@@ -8811,33 +8855,35 @@ class OpenFeedListeners {
8811
8855
  const res = this.instrumentByMarketId.get(marketId.toString());
8812
8856
  return res ?? [void 0, void 0];
8813
8857
  };
8858
+ const includesSymbolSubscription = (arr, item) => {
8859
+ return arr.some(([symbol, type]) => symbol === item[0] && type === item[1]);
8860
+ };
8814
8861
  if (message.subscriptionResponse) {
8815
- const { marketId, symbol, unsubscribe } = message.subscriptionResponse;
8862
+ const { marketId, symbol, unsubscribe, status, subscriptionType } = message.subscriptionResponse;
8816
8863
  if (marketId !== Long.ZERO) {
8817
8864
  [def, symbols] = getInstrumentDefinition(marketId);
8818
- if (!unsubscribe) {
8819
- if (!symbols) {
8820
- symbols = [symbol];
8821
- } else if (!symbols.includes(symbol)) {
8822
- symbols = [...symbols, symbol];
8823
- }
8824
- } else {
8825
- if (symbols) {
8826
- symbols = symbols.filter((s) => s !== symbol);
8827
- }
8828
- if (!symbols) {
8829
- this.instrumentByMarketId.delete(marketId.toString());
8865
+ if ((status == null ? void 0 : status.result) === Result.SUCCESS) {
8866
+ const currentEntry = [symbol, subscriptionType];
8867
+ if (!unsubscribe) {
8868
+ if (!symbols) {
8869
+ symbols = [currentEntry];
8870
+ } else if (!includesSymbolSubscription(symbols, currentEntry)) {
8871
+ symbols = [...symbols, currentEntry];
8872
+ }
8873
+ } else {
8874
+ if (symbols) {
8875
+ symbols = symbols.filter(([s, t]) => !(s === symbol && t === subscriptionType));
8876
+ }
8877
+ if (!symbols) {
8878
+ this.instrumentByMarketId.delete(marketId.toString());
8879
+ }
8830
8880
  }
8831
- this.instrumentBySymbol.delete(symbol);
8881
+ this.instrumentByMarketId.set(marketId.toString(), [def, symbols]);
8832
8882
  }
8833
- this.instrumentByMarketId.set(marketId.toString(), [def, symbols]);
8834
8883
  }
8835
8884
  } else if (message.instrumentDefinition) {
8836
8885
  [def, symbols] = getInstrumentDefinition(message.instrumentDefinition.marketId);
8837
- const { instrumentDefinition } = message;
8838
8886
  this.instrumentByMarketId.set(message.instrumentDefinition.marketId.toString(), [message.instrumentDefinition, symbols]);
8839
- this.instrumentBySymbol.set(message.instrumentDefinition.symbol, instrumentDefinition);
8840
- symbols == null ? void 0 : symbols.forEach((s) => this.instrumentBySymbol.set(s, instrumentDefinition));
8841
8887
  } else if (message.instrumentAction) {
8842
8888
  const { marketId } = ((_a = message.instrumentAction) == null ? void 0 : _a.instrument) ?? {};
8843
8889
  if (message.instrumentAction.action === ActionType.ALIAS_CHANGED && marketId) {
@@ -8846,7 +8892,7 @@ class OpenFeedListeners {
8846
8892
  const newAliasNum = oldAlias.endsWith("*0") ? 0 : Number.parseInt(num, 10) + 1;
8847
8893
  const newAlias = `${root}*${newAliasNum}`;
8848
8894
  [def, symbols] = getInstrumentDefinition(marketId);
8849
- const newSymbols = (symbols == null ? void 0 : symbols.filter((s) => s !== oldAlias)) ?? [];
8895
+ const newSymbols = (symbols == null ? void 0 : symbols.filter(([s]) => s !== oldAlias)) ?? [];
8850
8896
  if (!newSymbols.length) {
8851
8897
  this.instrumentByMarketId.delete(marketId.toString());
8852
8898
  } else {
@@ -8855,7 +8901,7 @@ class OpenFeedListeners {
8855
8901
  const { marketId: newMarketId } = message.instrumentAction.newInstrument ?? {};
8856
8902
  if (newMarketId) {
8857
8903
  const [newDef, newSym] = getInstrumentDefinition(newMarketId);
8858
- const newSymbolsFiltered = (newAlias === oldAlias ? newSym : newSym == null ? void 0 : newSym.filter((s) => s !== newAlias)) ?? [];
8904
+ const newSymbolsFiltered = (newAlias === oldAlias ? newSym : newSym == null ? void 0 : newSym.filter(([s]) => s !== newAlias)) ?? [];
8859
8905
  if (!newSymbolsFiltered.length) {
8860
8906
  this.instrumentByMarketId.delete(newMarketId.toString());
8861
8907
  } else {
@@ -8880,7 +8926,8 @@ class OpenFeedListeners {
8880
8926
  }
8881
8927
  }
8882
8928
  }
8883
- return this.onMessageWithMetadata(message, symbols ?? [], def);
8929
+ const uniqueSymbols = Array.from(new Set((symbols == null ? void 0 : symbols.map(([symbol]) => symbol)) ?? []));
8930
+ return this.onMessageWithMetadata(message, uniqueSymbols, def);
8884
8931
  });
8885
8932
  /* eslint-disable class-methods-use-this */
8886
8933
  __publicField(this, "onConnected", () => {
package/dist/node.js CHANGED
@@ -4934,7 +4934,7 @@ var require_minimal2 = __commonJS({
4934
4934
  }
4935
4935
  });
4936
4936
 
4937
- // src/connection/connection.ts
4937
+ // src/connection/client.ts
4938
4938
  var import_isomorphic_ws = __toESM(require_node(), 1);
4939
4939
 
4940
4940
  // node_modules/long/index.js
@@ -5837,9 +5837,6 @@ Long.fromBytesBE = function fromBytesBE(bytes, unsigned) {
5837
5837
  };
5838
5838
  var long_default = Long;
5839
5839
 
5840
- // src/utilities/messages.ts
5841
- var toT = (obj) => obj;
5842
-
5843
5840
  // generated/openfeed_api.ts
5844
5841
  var import_minimal3 = __toESM(require_minimal2(), 1);
5845
5842
 
@@ -7885,7 +7882,8 @@ function createBaseInstrumentStatus() {
7885
7882
  openingTime: long_default.ZERO,
7886
7883
  note: "",
7887
7884
  tradeDate: 0,
7888
- regulationSHOShortSalePriceTest: 0
7885
+ regulationSHOShortSalePriceTest: 0,
7886
+ priorTradingStatus: 0
7889
7887
  };
7890
7888
  }
7891
7889
  var InstrumentStatusDecode = {
@@ -7932,6 +7930,12 @@ var InstrumentStatusDecode = {
7932
7930
  }
7933
7931
  message.regulationSHOShortSalePriceTest = reader.int32();
7934
7932
  continue;
7933
+ case 15:
7934
+ if (tag !== 120) {
7935
+ break;
7936
+ }
7937
+ message.priorTradingStatus = reader.int32();
7938
+ continue;
7935
7939
  }
7936
7940
  if ((tag & 7) === 4 || tag === 0) {
7937
7941
  break;
@@ -10821,18 +10825,19 @@ var Result = /* @__PURE__ */ ((Result2) => {
10821
10825
  Result2[Result2["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
10822
10826
  return Result2;
10823
10827
  })(Result || {});
10824
- var SubscriptionType = /* @__PURE__ */ ((SubscriptionType2) => {
10825
- SubscriptionType2[SubscriptionType2["ALL"] = 0] = "ALL";
10826
- SubscriptionType2[SubscriptionType2["QUOTE"] = 1] = "QUOTE";
10827
- SubscriptionType2[SubscriptionType2["QUOTE_PARTICIPANT"] = 2] = "QUOTE_PARTICIPANT";
10828
- SubscriptionType2[SubscriptionType2["DEPTH_PRICE"] = 3] = "DEPTH_PRICE";
10829
- SubscriptionType2[SubscriptionType2["DEPTH_ORDER"] = 4] = "DEPTH_ORDER";
10830
- SubscriptionType2[SubscriptionType2["TRADES"] = 5] = "TRADES";
10831
- SubscriptionType2[SubscriptionType2["CUMLATIVE_VOLUME"] = 6] = "CUMLATIVE_VOLUME";
10832
- SubscriptionType2[SubscriptionType2["OHLC"] = 7] = "OHLC";
10833
- SubscriptionType2[SubscriptionType2["OHLC_NON_REGULAR"] = 8] = "OHLC_NON_REGULAR";
10834
- SubscriptionType2[SubscriptionType2["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
10835
- return SubscriptionType2;
10828
+ var SubscriptionType = /* @__PURE__ */ ((SubscriptionType3) => {
10829
+ SubscriptionType3[SubscriptionType3["ALL"] = 0] = "ALL";
10830
+ SubscriptionType3[SubscriptionType3["QUOTE"] = 1] = "QUOTE";
10831
+ SubscriptionType3[SubscriptionType3["QUOTE_PARTICIPANT"] = 2] = "QUOTE_PARTICIPANT";
10832
+ SubscriptionType3[SubscriptionType3["DEPTH_PRICE"] = 3] = "DEPTH_PRICE";
10833
+ SubscriptionType3[SubscriptionType3["DEPTH_ORDER"] = 4] = "DEPTH_ORDER";
10834
+ SubscriptionType3[SubscriptionType3["TRADES"] = 5] = "TRADES";
10835
+ SubscriptionType3[SubscriptionType3["CUMULATIVE_VOLUME"] = 6] = "CUMULATIVE_VOLUME";
10836
+ SubscriptionType3[SubscriptionType3["OHLC"] = 7] = "OHLC";
10837
+ SubscriptionType3[SubscriptionType3["OHLC_NON_REGULAR"] = 8] = "OHLC_NON_REGULAR";
10838
+ SubscriptionType3[SubscriptionType3["SETTLEMENT"] = 9] = "SETTLEMENT";
10839
+ SubscriptionType3[SubscriptionType3["UNRECOGNIZED"] = -1] = "UNRECOGNIZED";
10840
+ return SubscriptionType3;
10836
10841
  })(SubscriptionType || {});
10837
10842
  var SymbolType = /* @__PURE__ */ ((SymbolType2) => {
10838
10843
  SymbolType2[SymbolType2["BARCHART"] = 0] = "BARCHART";
@@ -11537,6 +11542,12 @@ var SubscriptionRequest_RequestEncode = {
11537
11542
  for (const v of message.spreadTypeFilter) {
11538
11543
  writer.uint32(114).string(v);
11539
11544
  }
11545
+ if (message.subscriptionDoNotSendInstruments === true) {
11546
+ writer.uint32(120).bool(message.subscriptionDoNotSendInstruments);
11547
+ }
11548
+ if (message.subscriptionDoNotSendSnapshots === true) {
11549
+ writer.uint32(128).bool(message.subscriptionDoNotSendSnapshots);
11550
+ }
11540
11551
  return writer;
11541
11552
  }
11542
11553
  };
@@ -11740,7 +11751,7 @@ var ListSubscriptionsResponse_SessionDecode = {
11740
11751
  }
11741
11752
  };
11742
11753
  function createBaseListSubscriptionsResponse_Subscription() {
11743
- return { subscriptionId: "", symbolId: "", marketId: long_default.ZERO, symbols: [], exchange: "", root: "" };
11754
+ return { subscriptionId: "", symbolId: "", marketId: long_default.ZERO, symbolCounts: [], exchange: "", root: "" };
11744
11755
  }
11745
11756
  var ListSubscriptionsResponse_SubscriptionDecode = {
11746
11757
  decode(input, length) {
@@ -11772,7 +11783,7 @@ var ListSubscriptionsResponse_SubscriptionDecode = {
11772
11783
  if (tag !== 34) {
11773
11784
  break;
11774
11785
  }
11775
- message.symbols.push(reader.string());
11786
+ message.symbolCounts.push(ListSubscriptionsResponse_SymbolCountDecode.decode(reader, reader.uint32()));
11776
11787
  continue;
11777
11788
  case 10:
11778
11789
  if (tag !== 82) {
@@ -11795,6 +11806,38 @@ var ListSubscriptionsResponse_SubscriptionDecode = {
11795
11806
  return message;
11796
11807
  }
11797
11808
  };
11809
+ function createBaseListSubscriptionsResponse_SymbolCount() {
11810
+ return { symbol: "", count: 0 };
11811
+ }
11812
+ var ListSubscriptionsResponse_SymbolCountDecode = {
11813
+ decode(input, length) {
11814
+ const reader = input instanceof import_minimal3.default.Reader ? input : import_minimal3.default.Reader.create(input);
11815
+ let end = length === void 0 ? reader.len : reader.pos + length;
11816
+ const message = createBaseListSubscriptionsResponse_SymbolCount();
11817
+ while (reader.pos < end) {
11818
+ const tag = reader.uint32();
11819
+ switch (tag >>> 3) {
11820
+ case 1:
11821
+ if (tag !== 10) {
11822
+ break;
11823
+ }
11824
+ message.symbol = reader.string();
11825
+ continue;
11826
+ case 2:
11827
+ if (tag !== 16) {
11828
+ break;
11829
+ }
11830
+ message.count = reader.sint32();
11831
+ continue;
11832
+ }
11833
+ if ((tag & 7) === 4 || tag === 0) {
11834
+ break;
11835
+ }
11836
+ reader.skipType(tag & 7);
11837
+ }
11838
+ return message;
11839
+ }
11840
+ };
11798
11841
  if (import_minimal3.default.util.Long !== long_default) {
11799
11842
  import_minimal3.default.util.Long = long_default;
11800
11843
  import_minimal3.default.configure();
@@ -11836,10 +11879,19 @@ var ResolutionSource = class {
11836
11879
  }
11837
11880
  };
11838
11881
 
11839
- // generated/version.ts
11840
- var version = "1.2.3";
11882
+ // src/utilities/correlation_id.ts
11883
+ var CorrelationId = class {
11884
+ static correlationId = long_default.fromNumber(-1);
11885
+ static create = () => {
11886
+ this.correlationId = this.correlationId.add(1);
11887
+ return this.correlationId;
11888
+ };
11889
+ };
11841
11890
 
11842
- // src/connection/connection.ts
11891
+ // src/utilities/messages.ts
11892
+ var toT = (obj) => obj;
11893
+
11894
+ // src/utilities/communication.ts
11843
11895
  var send = (socket, message) => {
11844
11896
  socket.send(OpenfeedGatewayRequestEncode.encode(toT(message)).finish());
11845
11897
  };
@@ -11856,13 +11908,15 @@ var receive = (msgEvent) => {
11856
11908
  }
11857
11909
  return res;
11858
11910
  };
11859
- var CorrelationId = class {
11860
- static correlationId = long_default.fromNumber(-1);
11861
- static create = () => {
11862
- this.correlationId = this.correlationId.add(1);
11863
- return this.correlationId;
11864
- };
11911
+
11912
+ // src/utilities/constants.ts
11913
+ var TIME = {
11914
+ RECONNECT: 5e3,
11915
+ CONNECTION_TIMEOUT: 15e3,
11916
+ SUBSCRIPTION_RETRY: 100
11865
11917
  };
11918
+
11919
+ // src/connection/errors.ts
11866
11920
  var DuplicateLoginError = class extends Error {
11867
11921
  get name() {
11868
11922
  return this.constructor.name;
@@ -11878,6 +11932,8 @@ var ConnectionDisposedError = class extends Error {
11878
11932
  return this.constructor.name;
11879
11933
  }
11880
11934
  };
11935
+
11936
+ // src/connection/connection.ts
11881
11937
  var OpenFeedConnection = class {
11882
11938
  constructor(connectionToken, socket, listeners, logger) {
11883
11939
  this.connectionToken = connectionToken;
@@ -11901,7 +11957,7 @@ var OpenFeedConnection = class {
11901
11957
  for (; ; ) {
11902
11958
  let timeoutId = null;
11903
11959
  const waitPromise = new Promise((resolve) => {
11904
- timeoutId = setTimeout(resolve, 15e3);
11960
+ timeoutId = setTimeout(resolve, TIME.CONNECTION_TIMEOUT);
11905
11961
  });
11906
11962
  try {
11907
11963
  await Promise.race([waitPromise, this.whenDisconnectedSource.whenCompleted]);
@@ -12029,7 +12085,9 @@ var OpenFeedConnection = class {
12029
12085
  snapshotIntervalSeconds,
12030
12086
  instrumentType: [],
12031
12087
  bulkSubscriptionFilter: [],
12032
- spreadTypeFilter: []
12088
+ spreadTypeFilter: [],
12089
+ subscriptionDoNotSendInstruments: false,
12090
+ subscriptionDoNotSendSnapshots: false
12033
12091
  };
12034
12092
  if (symbols) {
12035
12093
  for (const symbol of symbols) {
@@ -12088,7 +12146,7 @@ var OpenFeedConnection = class {
12088
12146
  throw new Error(`Subscription ID ${subscriptionId} does not exist.`);
12089
12147
  }
12090
12148
  const [originalRequest, sub] = subscription;
12091
- return this.fireUnsubscribeWhenReady(originalRequest, sub);
12149
+ this.fireUnsubscribeWhenReady(originalRequest, sub);
12092
12150
  };
12093
12151
  // We are keeping this fire and forget, because our problems
12094
12152
  // would be caused by disconnection, and reconnect will clean up the rest
@@ -12173,6 +12231,29 @@ var OpenFeedConnection = class {
12173
12231
  whenDisconnected = () => this.whenDisconnectedSource.whenCompleted;
12174
12232
  dispose = () => this.disconnect(new ConnectionDisposedError("Disposed"));
12175
12233
  };
12234
+
12235
+ // generated/version.ts
12236
+ var version = "1.3.2";
12237
+
12238
+ // src/utilities/client_version.ts
12239
+ var getClientVersion = async (clientId) => {
12240
+ var _a, _b, _c, _d, _e, _f;
12241
+ let platformDescription;
12242
+ if (typeof window !== "undefined") {
12243
+ platformDescription = navigator.userAgent;
12244
+ } else {
12245
+ const os = await import("os");
12246
+ try {
12247
+ platformDescription = `Node.js ${process.version}; ${(_a = os.version) == null ? void 0 : _a.call(os)} ${(_b = os.release) == null ? void 0 : _b.call(os)}; ${(_c = os.arch) == null ? void 0 : _c.call(os)};`;
12248
+ } catch (e) {
12249
+ platformDescription = `Unknown OS; ${((_d = os.version) == null ? void 0 : _d.call(os)) ?? ""} ${((_e = os.release) == null ? void 0 : _e.call(os)) ?? ""}; ${((_f = os.arch) == null ? void 0 : _f.call(os)) ?? ""};`;
12250
+ }
12251
+ }
12252
+ const clientVersion = `sdk-js:${version};client-id:${clientId ?? "default"};platform:${platformDescription}`;
12253
+ return clientVersion;
12254
+ };
12255
+
12256
+ // src/connection/client.ts
12176
12257
  var OpenFeedClient = class {
12177
12258
  constructor(url, username, password, listeners, logger, clientId) {
12178
12259
  this.url = url;
@@ -12192,21 +12273,9 @@ var OpenFeedClient = class {
12192
12273
  subscribeResetSource = new ResolutionSource();
12193
12274
  subscriptions = /* @__PURE__ */ new Map();
12194
12275
  onOpen = async () => {
12195
- var _a, _b, _c, _d, _e, _f;
12196
12276
  if (!this.socket)
12197
12277
  return;
12198
- let platformDescription;
12199
- if (typeof window !== "undefined") {
12200
- platformDescription = navigator.userAgent;
12201
- } else {
12202
- const os = await import("os");
12203
- try {
12204
- platformDescription = `Node.js ${process.version}; ${(_a = os.version) == null ? void 0 : _a.call(os)} ${(_b = os.release) == null ? void 0 : _b.call(os)}; ${(_c = os.arch) == null ? void 0 : _c.call(os)};`;
12205
- } catch (e) {
12206
- platformDescription = `Unknown OS; ${((_d = os.version) == null ? void 0 : _d.call(os)) ?? ""} ${((_e = os.release) == null ? void 0 : _e.call(os)) ?? ""}; ${((_f = os.arch) == null ? void 0 : _f.call(os)) ?? ""};`;
12207
- }
12208
- }
12209
- const clientVersion = `sdk-js:${version};client-id:${this.clientId ?? "default"};platform:${platformDescription}`;
12278
+ const clientVersion = await getClientVersion(this.clientId);
12210
12279
  const loginRequest = {
12211
12280
  loginRequest: {
12212
12281
  correlationId: CorrelationId.create(),
@@ -12268,7 +12337,6 @@ var OpenFeedClient = class {
12268
12337
  runConnectLoop = async () => {
12269
12338
  var _a, _b;
12270
12339
  for (; ; ) {
12271
- let timeoutId = null;
12272
12340
  if (this.socket) {
12273
12341
  if (this.socket.readyState !== import_isomorphic_ws.default.CLOSED && this.socket.readyState !== import_isomorphic_ws.default.CLOSING) {
12274
12342
  this.socket.close(1e3, "Closed from socket loop");
@@ -12318,15 +12386,9 @@ var OpenFeedClient = class {
12318
12386
  this.loopResetSource = new ResolutionSource();
12319
12387
  this.subscribeResetSource.resolve();
12320
12388
  this.subscribeResetSource = new ResolutionSource();
12321
- try {
12322
- await new Promise((resolve) => {
12323
- timeoutId = setTimeout(resolve, 5e3);
12324
- });
12325
- } finally {
12326
- if (timeoutId) {
12327
- clearTimeout(timeoutId);
12328
- }
12329
- }
12389
+ await new Promise((resolve) => {
12390
+ setTimeout(resolve, TIME.RECONNECT);
12391
+ });
12330
12392
  }
12331
12393
  };
12332
12394
  cleanUp = () => {
@@ -12339,11 +12401,10 @@ var OpenFeedClient = class {
12339
12401
  runSubscribeLoop = async (service, subscriptionType, snapshotIntervalSeconds, symbols, marketIds, exchanges, channels, cancelSource) => {
12340
12402
  var _a;
12341
12403
  for (; ; ) {
12342
- let timeoutId = null;
12343
12404
  try {
12344
12405
  const connection = await Promise.race([this.connection, cancelSource.whenCompleted]);
12345
12406
  if (cancelSource.completed || /* can't actually happen */
12346
- !(connection instanceof OpenFeedConnection)) {
12407
+ !connection) {
12347
12408
  return;
12348
12409
  }
12349
12410
  const subscriptionId = connection.subscribe(
@@ -12366,12 +12427,8 @@ var OpenFeedClient = class {
12366
12427
  } catch (error) {
12367
12428
  (_a = this.logger) == null ? void 0 : _a.warn("Subscription error:", error);
12368
12429
  await new Promise((resolve) => {
12369
- timeoutId = setTimeout(resolve, 100);
12430
+ setTimeout(resolve, TIME.SUBSCRIPTION_RETRY);
12370
12431
  });
12371
- } finally {
12372
- if (timeoutId) {
12373
- clearTimeout(timeoutId);
12374
- }
12375
12432
  }
12376
12433
  }
12377
12434
  };
@@ -12427,7 +12484,6 @@ var IDGetters = [
12427
12484
  }
12428
12485
  ];
12429
12486
  var OpenFeedListeners = class {
12430
- instrumentBySymbol = /* @__PURE__ */ new Map();
12431
12487
  instrumentByMarketId = /* @__PURE__ */ new Map();
12432
12488
  constructor() {
12433
12489
  this.onMessage = this.addDetails;
@@ -12440,33 +12496,35 @@ var OpenFeedListeners = class {
12440
12496
  const res = this.instrumentByMarketId.get(marketId.toString());
12441
12497
  return res ?? [void 0, void 0];
12442
12498
  };
12499
+ const includesSymbolSubscription = (arr, item) => {
12500
+ return arr.some(([symbol, type]) => symbol === item[0] && type === item[1]);
12501
+ };
12443
12502
  if (message.subscriptionResponse) {
12444
- const { marketId, symbol, unsubscribe } = message.subscriptionResponse;
12503
+ const { marketId, symbol, unsubscribe, status, subscriptionType } = message.subscriptionResponse;
12445
12504
  if (marketId !== long_default.ZERO) {
12446
12505
  [def, symbols] = getInstrumentDefinition(marketId);
12447
- if (!unsubscribe) {
12448
- if (!symbols) {
12449
- symbols = [symbol];
12450
- } else if (!symbols.includes(symbol)) {
12451
- symbols = [...symbols, symbol];
12452
- }
12453
- } else {
12454
- if (symbols) {
12455
- symbols = symbols.filter((s) => s !== symbol);
12456
- }
12457
- if (!symbols) {
12458
- this.instrumentByMarketId.delete(marketId.toString());
12506
+ if ((status == null ? void 0 : status.result) === 1 /* SUCCESS */) {
12507
+ const currentEntry = [symbol, subscriptionType];
12508
+ if (!unsubscribe) {
12509
+ if (!symbols) {
12510
+ symbols = [currentEntry];
12511
+ } else if (!includesSymbolSubscription(symbols, currentEntry)) {
12512
+ symbols = [...symbols, currentEntry];
12513
+ }
12514
+ } else {
12515
+ if (symbols) {
12516
+ symbols = symbols.filter(([s, t]) => !(s === symbol && t === subscriptionType));
12517
+ }
12518
+ if (!symbols) {
12519
+ this.instrumentByMarketId.delete(marketId.toString());
12520
+ }
12459
12521
  }
12460
- this.instrumentBySymbol.delete(symbol);
12522
+ this.instrumentByMarketId.set(marketId.toString(), [def, symbols]);
12461
12523
  }
12462
- this.instrumentByMarketId.set(marketId.toString(), [def, symbols]);
12463
12524
  }
12464
12525
  } else if (message.instrumentDefinition) {
12465
12526
  [def, symbols] = getInstrumentDefinition(message.instrumentDefinition.marketId);
12466
- const { instrumentDefinition } = message;
12467
12527
  this.instrumentByMarketId.set(message.instrumentDefinition.marketId.toString(), [message.instrumentDefinition, symbols]);
12468
- this.instrumentBySymbol.set(message.instrumentDefinition.symbol, instrumentDefinition);
12469
- symbols == null ? void 0 : symbols.forEach((s) => this.instrumentBySymbol.set(s, instrumentDefinition));
12470
12528
  } else if (message.instrumentAction) {
12471
12529
  const { marketId } = ((_a = message.instrumentAction) == null ? void 0 : _a.instrument) ?? {};
12472
12530
  if (message.instrumentAction.action === 4 /* ALIAS_CHANGED */ && marketId) {
@@ -12475,7 +12533,7 @@ var OpenFeedListeners = class {
12475
12533
  const newAliasNum = oldAlias.endsWith("*0") ? 0 : Number.parseInt(num, 10) + 1;
12476
12534
  const newAlias = `${root}*${newAliasNum}`;
12477
12535
  [def, symbols] = getInstrumentDefinition(marketId);
12478
- const newSymbols = (symbols == null ? void 0 : symbols.filter((s) => s !== oldAlias)) ?? [];
12536
+ const newSymbols = (symbols == null ? void 0 : symbols.filter(([s]) => s !== oldAlias)) ?? [];
12479
12537
  if (!newSymbols.length) {
12480
12538
  this.instrumentByMarketId.delete(marketId.toString());
12481
12539
  } else {
@@ -12484,7 +12542,7 @@ var OpenFeedListeners = class {
12484
12542
  const { marketId: newMarketId } = message.instrumentAction.newInstrument ?? {};
12485
12543
  if (newMarketId) {
12486
12544
  const [newDef, newSym] = getInstrumentDefinition(newMarketId);
12487
- const newSymbolsFiltered = (newAlias === oldAlias ? newSym : newSym == null ? void 0 : newSym.filter((s) => s !== newAlias)) ?? [];
12545
+ const newSymbolsFiltered = (newAlias === oldAlias ? newSym : newSym == null ? void 0 : newSym.filter(([s]) => s !== newAlias)) ?? [];
12488
12546
  if (!newSymbolsFiltered.length) {
12489
12547
  this.instrumentByMarketId.delete(newMarketId.toString());
12490
12548
  } else {
@@ -12509,7 +12567,8 @@ var OpenFeedListeners = class {
12509
12567
  }
12510
12568
  }
12511
12569
  }
12512
- return this.onMessageWithMetadata(message, symbols ?? [], def);
12570
+ const uniqueSymbols = Array.from(new Set((symbols == null ? void 0 : symbols.map(([symbol]) => symbol)) ?? []));
12571
+ return this.onMessageWithMetadata(message, uniqueSymbols, def);
12513
12572
  };
12514
12573
  /* eslint-disable class-methods-use-this */
12515
12574
  onConnected = () => {
@@ -0,0 +1,32 @@
1
+ import Long from "long";
2
+ import type { SubscriptionType } from "@gen/openfeed_api";
3
+ import type { Service } from "@gen/openfeed";
4
+ import { IOpenFeedClient, IOpenFeedConnection, IOpenFeedLogger } from "./interfaces";
5
+ import { OpenFeedListeners } from "./listeners";
6
+ export declare class OpenFeedClient implements IOpenFeedClient {
7
+ private readonly url;
8
+ private readonly username;
9
+ private readonly password;
10
+ private readonly listeners;
11
+ private readonly logger?;
12
+ private readonly clientId?;
13
+ private socket;
14
+ private _connection;
15
+ private whenConnectedInternalSource;
16
+ private whenConnectedSource;
17
+ private loopResetSource;
18
+ private subscribeResetSource;
19
+ private readonly subscriptions;
20
+ constructor(url: string, username: string, password: string, listeners: OpenFeedListeners, logger?: IOpenFeedLogger | undefined, clientId?: string | undefined);
21
+ private onOpen;
22
+ private onMessage;
23
+ private onError;
24
+ private onClose;
25
+ private runConnectLoop;
26
+ private cleanUp;
27
+ private runSubscribeLoop;
28
+ subscribe: (service: Service, subscriptionType: SubscriptionType, snapshotIntervalSeconds: number, symbols?: string[] | null, marketIds?: Long[] | null, exchanges?: string[] | null, channels?: number[] | null) => Long;
29
+ unsubscribe: (subscriptionId: Long) => void;
30
+ get connection(): Promise<IOpenFeedConnection>;
31
+ dispose: () => void;
32
+ }
@@ -1,32 +1,34 @@
1
+ import WebSocket from "isomorphic-ws";
1
2
  import Long from "long";
2
- import type { SubscriptionType } from "@gen/openfeed_api";
3
+ import type { ExchangeResponse_Exchange, InstrumentReferenceResponse, SubscriptionType } from "@gen/openfeed_api";
4
+ import type { InstrumentDefinition } from "@gen/openfeed_instrument";
3
5
  import type { Service } from "@gen/openfeed";
4
- import { IOpenFeedClient, IOpenFeedConnection, IOpenFeedLogger } from "./connection_interfaces";
6
+ import { IOpenFeedConnection, IOpenFeedLogger, OpenFeedInstrumentReferenceRequest, OpenFeedInstrumentRequest } from "./interfaces";
5
7
  import { OpenFeedListeners } from "./listeners";
6
- export declare class OpenFeedClient implements IOpenFeedClient {
7
- private readonly url;
8
- private readonly username;
9
- private readonly password;
8
+ export declare class OpenFeedConnection implements IOpenFeedConnection {
9
+ private readonly connectionToken;
10
+ private readonly socket;
10
11
  private readonly listeners;
11
12
  private readonly logger?;
12
- private readonly clientId?;
13
- private socket;
14
- private _connection;
15
- private whenConnectedInternalSource;
16
- private whenConnectedSource;
17
- private loopResetSource;
18
- private subscribeResetSource;
19
- private readonly subscriptions;
20
- constructor(url: string, username: string, password: string, listeners: OpenFeedListeners, logger?: IOpenFeedLogger | undefined, clientId?: string | undefined);
21
- private onOpen;
13
+ private readonly subscriptionRequests;
14
+ private readonly exchangeRequests;
15
+ private readonly instrumentRequests;
16
+ private readonly definitionsInFlight;
17
+ private readonly instrumentReferenceRequests;
18
+ private readonly whenDisconnectedSource;
19
+ constructor(connectionToken: string, socket: WebSocket, listeners: OpenFeedListeners, logger?: IOpenFeedLogger | undefined);
20
+ private messageTriggered;
21
+ private runConnectionWatchLoop;
22
22
  private onMessage;
23
+ private disconnect;
23
24
  private onError;
24
25
  private onClose;
25
- private runConnectLoop;
26
- private cleanUp;
27
- private runSubscribeLoop;
28
26
  subscribe: (service: Service, subscriptionType: SubscriptionType, snapshotIntervalSeconds: number, symbols?: string[] | null, marketIds?: Long[] | null, exchanges?: string[] | null, channels?: number[] | null) => Long;
29
27
  unsubscribe: (subscriptionId: Long) => void;
30
- get connection(): Promise<IOpenFeedConnection>;
28
+ private fireUnsubscribeWhenReady;
29
+ getExchanges: () => Promise<ExchangeResponse_Exchange[]>;
30
+ getInstrument: (request: OpenFeedInstrumentRequest) => Promise<InstrumentDefinition[]>;
31
+ getInstrumentReference: (request: OpenFeedInstrumentReferenceRequest) => Promise<InstrumentReferenceResponse>;
32
+ whenDisconnected: () => Promise<void>;
31
33
  dispose: () => void;
32
34
  }
@@ -0,0 +1,9 @@
1
+ export declare class DuplicateLoginError extends Error {
2
+ get name(): string;
3
+ }
4
+ export declare class InvalidCredentialsError extends Error {
5
+ get name(): string;
6
+ }
7
+ export declare class ConnectionDisposedError extends Error {
8
+ get name(): string;
9
+ }
@@ -1,9 +1,8 @@
1
1
  import { OpenfeedGatewayMessage } from "@gen/openfeed_api";
2
2
  import { InstrumentDefinition } from "@gen/openfeed_instrument";
3
3
  import { HeartBeat } from "@gen/openfeed";
4
- import { IOpenFeedConnection } from "./connection_interfaces";
4
+ import { IOpenFeedConnection } from "./interfaces";
5
5
  export declare class OpenFeedListeners {
6
- private readonly instrumentBySymbol;
7
6
  private readonly instrumentByMarketId;
8
7
  constructor();
9
8
  private addDetails;
@@ -1,4 +1,4 @@
1
- export * from "./connection/connection";
2
- export * from "./connection/connection_interfaces";
1
+ export * from "./connection/client";
2
+ export * from "./connection/interfaces";
3
3
  export * from "./connection/listeners";
4
4
  export * from "../generated/index";
@@ -0,0 +1 @@
1
+ export declare const getClientVersion: (clientId?: string) => Promise<string>;
@@ -0,0 +1,5 @@
1
+ import WebSocket from "isomorphic-ws";
2
+ import { OptionalUndefined } from "@src/utilities/messages";
3
+ import type { OpenfeedGatewayMessage, OpenfeedGatewayRequest } from "@gen/openfeed_api";
4
+ export declare const send: (socket: WebSocket, message: OptionalUndefined<OpenfeedGatewayRequest>) => void;
5
+ export declare const receive: (msgEvent: WebSocket.MessageEvent) => OpenfeedGatewayMessage[];
@@ -0,0 +1,5 @@
1
+ export declare const TIME: {
2
+ RECONNECT: number;
3
+ CONNECTION_TIMEOUT: number;
4
+ SUBSCRIPTION_RETRY: number;
5
+ };
@@ -0,0 +1,5 @@
1
+ import Long from "long";
2
+ export declare class CorrelationId {
3
+ private static correlationId;
4
+ static create: () => Long;
5
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openfeed/sdk-js",
3
- "version": "1.2.3",
3
+ "version": "1.3.2",
4
4
  "description": "JavaScript SDK for Barchart OpenFeed",
5
5
  "main": "dist/node.js",
6
6
  "browser": "dist/index.js",
@@ -11,10 +11,11 @@
11
11
  "license": "MIT",
12
12
  "scripts": {
13
13
  "prepare": "husky install",
14
+ "upgrade:proto": "yarn upgrade proto",
14
15
  "generate:proto": "cd node_modules\\proto && ..\\..\\protoc --plugin=..\\..\\node_modules\\.bin\\protoc-gen-ts_proto --ts_proto_opt=outputJsonMethods=false --ts_proto_opt=outputPartialMethods=false --ts_proto_opt=exportCommonSymbols=false --ts_proto_opt=esModuleInterop=true --ts_proto_opt=forceLong=long --ts_proto_opt=useExactTypes=false --ts_proto_out=../../generated *.proto",
15
16
  "generate:version": "genversion --es6 -s -d ./generated/version.ts",
16
17
  "generate:process": "tsx ./scripts/process.ts",
17
- "generate": "yarn generate:proto && yarn generate:process",
18
+ "generate": "yarn upgrade:proto && yarn generate:proto && yarn generate:process",
18
19
  "build:clear": "rimraf dist",
19
20
  "build:node": "esbuild --bundle --outfile=dist/node.js --platform=node --target=node16 --format=esm --banner:js=\"import { createRequire } from 'module';const require = createRequire(import.meta.url);\" src/index.ts",
20
21
  "build:ts": "yarn generate:version && vite build",
@@ -22,7 +23,8 @@
22
23
  "build:test-release": "standard-version --dry-run",
23
24
  "build:prepare-release": "standard-version -t ''",
24
25
  "run:browser": "yarn generate:version && vite dev",
25
- "run:node": "yarn generate:version && tsx ./src/test.ts"
26
+ "run:node": "yarn generate:version && tsx ./src/test.ts",
27
+ "test": "jest"
26
28
  },
27
29
  "devDependencies": {
28
30
  "@commitlint/cli": "^18.4.3",
@@ -49,7 +51,8 @@
49
51
  "ts-proto": "^1.156.7",
50
52
  "tsx": "^3.12.7",
51
53
  "typescript": "^5.2.2",
52
- "vite": "^4.4.9"
54
+ "vite": "^4.4.9",
55
+ "vite-plugin-checker": "^0.8.0"
53
56
  },
54
57
  "packageManager": "yarn@1.22.19",
55
58
  "dependencies": {
package/tsconfig.json CHANGED
@@ -20,5 +20,5 @@
20
20
  "@gen/*": ["./generated/*"]
21
21
  }
22
22
  },
23
- "include": ["./src", "./generated", "./scripts/"]
23
+ "include": ["./src", "./generated", "./scripts/", "./test/"]
24
24
  }