@binance/common 2.1.1 → 2.3.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/dist/index.mjs CHANGED
@@ -344,16 +344,17 @@ const httpRequestFunction = async function(axiosArgs, configuration) {
344
344
  else if (typeof responseData === "object") data = responseData;
345
345
  }
346
346
  const errorMsg = data.msg;
347
+ const errorCode = typeof data.code === "number" ? data.code : void 0;
347
348
  switch (status) {
348
- case 400: throw new BadRequestError(errorMsg);
349
- case 401: throw new UnauthorizedError(errorMsg);
350
- case 403: throw new ForbiddenError(errorMsg);
351
- case 404: throw new NotFoundError(errorMsg);
352
- case 418: throw new RateLimitBanError(errorMsg);
353
- case 429: throw new TooManyRequestsError(errorMsg);
349
+ case 400: throw new BadRequestError(errorMsg, errorCode);
350
+ case 401: throw new UnauthorizedError(errorMsg, errorCode);
351
+ case 403: throw new ForbiddenError(errorMsg, errorCode);
352
+ case 404: throw new NotFoundError(errorMsg, errorCode);
353
+ case 418: throw new RateLimitBanError(errorMsg, errorCode);
354
+ case 429: throw new TooManyRequestsError(errorMsg, errorCode);
354
355
  default:
355
356
  if (status >= 500 && status < 600) throw new ServerError(`Server error: ${status}`, status);
356
- throw new ConnectorClientError(errorMsg);
357
+ throw new ConnectorClientError(errorMsg, errorCode);
357
358
  }
358
359
  } else {
359
360
  if (retries > 0 && attempt >= retries) lastError = /* @__PURE__ */ new Error(`Request failed after ${retries} retries`);
@@ -690,7 +691,9 @@ const DERIVATIVES_TRADING_USDS_FUTURES_WS_API_TESTNET_URL = "wss://testnet.binan
690
691
  const DERIVATIVES_TRADING_USDS_FUTURES_WS_STREAMS_PROD_URL = "wss://fstream.binance.com";
691
692
  const DERIVATIVES_TRADING_USDS_FUTURES_WS_STREAMS_TESTNET_URL = "wss://stream.binancefuture.com";
692
693
  const DERIVATIVES_TRADING_OPTIONS_REST_API_PROD_URL = "https://eapi.binance.com";
693
- const DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_PROD_URL = "wss://nbstream.binance.com/eoptions";
694
+ const DERIVATIVES_TRADING_OPTIONS_REST_API_TESTNET_URL = "https://testnet.binancefuture.com";
695
+ const DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_PROD_URL = "wss://fstream.binance.com";
696
+ const DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_TESTNET_URL = "wss://fstream.binancefuture.com";
694
697
  const DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_PROD_URL = "https://papi.binance.com";
695
698
  const DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_TESTNET_URL = "https://testnet.binancefuture.com";
696
699
  const DERIVATIVES_TRADING_PORTFOLIO_MARGIN_WS_STREAMS_PROD_URL = "wss://fstream.binance.com/pm";
@@ -728,10 +731,11 @@ const WALLET_REST_API_PROD_URL = "https://api.binance.com";
728
731
  * @param msg - An optional error message.
729
732
  */
730
733
  var ConnectorClientError = class ConnectorClientError extends Error {
731
- constructor(msg) {
734
+ constructor(msg, code) {
732
735
  super(msg || "An unexpected error occurred.");
733
736
  Object.setPrototypeOf(this, ConnectorClientError.prototype);
734
737
  this.name = "ConnectorClientError";
738
+ this.code = code;
735
739
  }
736
740
  };
737
741
  /**
@@ -752,10 +756,11 @@ var RequiredError = class RequiredError extends Error {
752
756
  * @param msg - An optional error message.
753
757
  */
754
758
  var UnauthorizedError = class UnauthorizedError extends Error {
755
- constructor(msg) {
759
+ constructor(msg, code) {
756
760
  super(msg || "Unauthorized access. Authentication required.");
757
761
  Object.setPrototypeOf(this, UnauthorizedError.prototype);
758
762
  this.name = "UnauthorizedError";
763
+ this.code = code;
759
764
  }
760
765
  };
761
766
  /**
@@ -763,10 +768,11 @@ var UnauthorizedError = class UnauthorizedError extends Error {
763
768
  * @param msg - An optional error message.
764
769
  */
765
770
  var ForbiddenError = class ForbiddenError extends Error {
766
- constructor(msg) {
771
+ constructor(msg, code) {
767
772
  super(msg || "Access to the requested resource is forbidden.");
768
773
  Object.setPrototypeOf(this, ForbiddenError.prototype);
769
774
  this.name = "ForbiddenError";
775
+ this.code = code;
770
776
  }
771
777
  };
772
778
  /**
@@ -774,10 +780,11 @@ var ForbiddenError = class ForbiddenError extends Error {
774
780
  * @param msg - An optional error message.
775
781
  */
776
782
  var TooManyRequestsError = class TooManyRequestsError extends Error {
777
- constructor(msg) {
783
+ constructor(msg, code) {
778
784
  super(msg || "Too many requests. You are being rate-limited.");
779
785
  Object.setPrototypeOf(this, TooManyRequestsError.prototype);
780
786
  this.name = "TooManyRequestsError";
787
+ this.code = code;
781
788
  }
782
789
  };
783
790
  /**
@@ -785,10 +792,11 @@ var TooManyRequestsError = class TooManyRequestsError extends Error {
785
792
  * @param msg - An optional error message.
786
793
  */
787
794
  var RateLimitBanError = class RateLimitBanError extends Error {
788
- constructor(msg) {
795
+ constructor(msg, code) {
789
796
  super(msg || "The IP address has been banned for exceeding rate limits.");
790
797
  Object.setPrototypeOf(this, RateLimitBanError.prototype);
791
798
  this.name = "RateLimitBanError";
799
+ this.code = code;
792
800
  }
793
801
  };
794
802
  /**
@@ -820,10 +828,11 @@ var NetworkError = class NetworkError extends Error {
820
828
  * @param msg - An optional error message.
821
829
  */
822
830
  var NotFoundError = class NotFoundError extends Error {
823
- constructor(msg) {
831
+ constructor(msg, code) {
824
832
  super(msg || "The requested resource was not found.");
825
833
  Object.setPrototypeOf(this, NotFoundError.prototype);
826
834
  this.name = "NotFoundError";
835
+ this.code = code;
827
836
  }
828
837
  };
829
838
  /**
@@ -831,10 +840,11 @@ var NotFoundError = class NotFoundError extends Error {
831
840
  * @param msg - An optional error message.
832
841
  */
833
842
  var BadRequestError = class BadRequestError extends Error {
834
- constructor(msg) {
843
+ constructor(msg, code) {
835
844
  super(msg || "The request was invalid or cannot be otherwise served.");
836
845
  Object.setPrototypeOf(this, BadRequestError.prototype);
837
846
  this.name = "BadRequestError";
847
+ this.code = code;
838
848
  }
839
849
  };
840
850
 
@@ -952,10 +962,11 @@ var WebsocketCommon = class WebsocketCommon extends WebsocketEventEmitter {
952
962
  * In 'single' mode, returns the first connection in the pool.
953
963
  * In 'pool' mode, filters and returns connections that are ready for use.
954
964
  * @param allowNonEstablishedWebsockets - Optional flag to include non-established WebSocket connections.
965
+ * @param urlPath - Optional URL path to filter connections.
955
966
  * @returns An array of available WebSocket connections.
956
967
  */
957
- getAvailableConnections(allowNonEstablishedWebsockets = false) {
958
- if (this.mode === "single") return [this.connectionPool[0]];
968
+ getAvailableConnections(allowNonEstablishedWebsockets = false, urlPath) {
969
+ if (this.mode === "single" && !urlPath) return [this.connectionPool[0]];
959
970
  return this.connectionPool.filter((connection) => this.isConnectionReady(connection, allowNonEstablishedWebsockets));
960
971
  }
961
972
  /**
@@ -964,10 +975,14 @@ var WebsocketCommon = class WebsocketCommon extends WebsocketEventEmitter {
964
975
  * If the connection mode is 'pool', it returns an available connection from the pool,
965
976
  * using a round-robin selection strategy. If no available connections are found, it throws an error.
966
977
  * @param allowNonEstablishedWebsockets - A boolean indicating whether to allow connections that are not established.
978
+ * @param urlPath - An optional URL path to filter connections.
967
979
  * @returns {WebsocketConnection} The selected WebSocket connection.
968
980
  */
969
- getConnection(allowNonEstablishedWebsockets = false) {
970
- const availableConnections = this.getAvailableConnections(allowNonEstablishedWebsockets);
981
+ getConnection(allowNonEstablishedWebsockets = false, urlPath) {
982
+ const availableConnections = this.getAvailableConnections(allowNonEstablishedWebsockets, urlPath).filter((connection) => {
983
+ if (urlPath) return connection.urlPath === urlPath;
984
+ return true;
985
+ });
971
986
  if (availableConnections.length === 0) throw new Error("No available Websocket connections are ready.");
972
987
  const selectedConnection = availableConnections[this.roundRobinIndex % availableConnections.length];
973
988
  this.roundRobinIndex = (this.roundRobinIndex + 1) % availableConnections.length;
@@ -1165,14 +1180,15 @@ var WebsocketCommon = class WebsocketCommon extends WebsocketEventEmitter {
1165
1180
  /**
1166
1181
  * Connects all WebSocket connections in the pool
1167
1182
  * @param url - The Websocket server URL.
1183
+ * @param connections - An optional array of WebSocket connections to connect. If not provided, all connections in the pool are connected.
1168
1184
  * @returns A promise that resolves when all connections are established.
1169
1185
  */
1170
- async connectPool(url) {
1171
- const connectPromises = this.connectionPool.map((connection) => new Promise((resolve, reject) => {
1186
+ async connectPool(url, connections) {
1187
+ const connectPromises = (connections ?? this.connectionPool).map((connection) => new Promise((resolve, reject) => {
1172
1188
  this.initConnect(url, false, connection);
1173
- connection.ws?.on("open", () => resolve());
1174
- connection.ws?.on("error", (err) => reject(err));
1175
- connection.ws?.on("close", () => reject(/* @__PURE__ */ new Error("Connection closed unexpectedly.")));
1189
+ connection.ws?.once("open", () => resolve());
1190
+ connection.ws?.once("error", (err) => reject(err));
1191
+ connection.ws?.once("close", () => reject(/* @__PURE__ */ new Error("Connection closed unexpectedly.")));
1176
1192
  }));
1177
1193
  await Promise.all(connectPromises);
1178
1194
  }
@@ -1451,7 +1467,7 @@ var WebsocketAPIBase = class extends WebsocketCommon {
1451
1467
  }
1452
1468
  };
1453
1469
  var WebsocketStreamsBase = class extends WebsocketCommon {
1454
- constructor(configuration, connectionPool = []) {
1470
+ constructor(configuration, connectionPool = [], urlPaths = []) {
1455
1471
  super(configuration, connectionPool);
1456
1472
  this.streamConnectionMap = /* @__PURE__ */ new Map();
1457
1473
  this.streamIdIsStrictlyNumber = false;
@@ -1459,14 +1475,42 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
1459
1475
  this.logger = Logger.getInstance();
1460
1476
  this.configuration = configuration;
1461
1477
  this.wsURL = configuration.wsURL;
1478
+ this.urlPaths = urlPaths;
1479
+ this.ensurePoolSizeForUrlPaths();
1480
+ }
1481
+ /**
1482
+ * Ensures the connection pool has the required size based on the configured mode and number of URL paths.
1483
+ *
1484
+ * If no URL paths are configured, the method returns early without modifications.
1485
+ * In 'pool' mode, the pool size is multiplied by the number of URL paths.
1486
+ * In 'single' mode, only one connection per URL path is maintained.
1487
+ *
1488
+ * New connections are initialized with unique IDs and default state flags when the pool
1489
+ * size is less than the expected size.
1490
+ *
1491
+ * @private
1492
+ * @returns {void}
1493
+ */
1494
+ ensurePoolSizeForUrlPaths() {
1495
+ if (this.urlPaths.length === 0) return;
1496
+ const expected = ((this.configuration?.mode ?? "single") === "pool" && this.configuration?.poolSize ? this.configuration.poolSize : 1) * this.urlPaths.length;
1497
+ while (this.connectionPool.length < expected) this.connectionPool.push({
1498
+ id: randomString(),
1499
+ closeInitiated: false,
1500
+ reconnectionPending: false,
1501
+ renewalPending: false,
1502
+ pendingRequests: /* @__PURE__ */ new Map(),
1503
+ pendingSubscriptions: []
1504
+ });
1462
1505
  }
1463
1506
  /**
1464
1507
  * Formats the WebSocket URL for a given stream or streams.
1465
1508
  * @param streams - Array of stream names to include in the URL.
1509
+ * @param urlPath - Optional URL path to include in the WebSocket URL.
1466
1510
  * @returns The formatted WebSocket URL with the provided streams.
1467
1511
  */
1468
- prepareURL(streams = []) {
1469
- let url = `${this.wsURL}/stream?streams=${streams.join("/")}`;
1512
+ prepareURL(streams = [], urlPath) {
1513
+ let url = `${urlPath ? `${this.wsURL}/${urlPath}` : this.wsURL}/stream?streams=${streams.join("/")}`;
1470
1514
  if (this.configuration?.timeUnit) try {
1471
1515
  const _timeUnit = validateTimeUnit(this.configuration.timeUnit);
1472
1516
  url = `${url}${url.includes("?") ? "&" : "?"}timeUnit=${_timeUnit}`;
@@ -1482,22 +1526,24 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
1482
1526
  * @returns The formatted WebSocket URL with streams and optional parameters.
1483
1527
  */
1484
1528
  getReconnectURL(url, targetConnection) {
1485
- const streams = Array.from(this.streamConnectionMap.keys()).filter((stream) => this.streamConnectionMap.get(stream) === targetConnection);
1486
- return this.prepareURL(streams);
1529
+ const streams = Array.from(this.streamConnectionMap.keys()).filter((stream) => this.streamConnectionMap.get(stream) === targetConnection).map((key) => key.includes("::") ? key.split("::").slice(1).join("::") : key);
1530
+ return this.prepareURL(streams, targetConnection?.urlPath);
1487
1531
  }
1488
1532
  /**
1489
1533
  * Handles subscription to streams and assigns them to specific connections
1490
1534
  * @param streams Array of stream names to subscribe to
1535
+ * @param urlPath Optional URL path for the streams
1491
1536
  * @returns Map of connections to streams
1492
1537
  */
1493
- handleStreamAssignment(streams) {
1538
+ handleStreamAssignment(streams, urlPath) {
1494
1539
  const connectionStreamMap = /* @__PURE__ */ new Map();
1495
1540
  streams.forEach((stream) => {
1496
- if (!this.streamCallbackMap.has(stream)) this.streamCallbackMap.set(stream, /* @__PURE__ */ new Set());
1497
- let connection = this.streamConnectionMap.get(stream);
1541
+ const key = this.streamKey(stream, urlPath);
1542
+ if (!this.streamCallbackMap.has(key)) this.streamCallbackMap.set(key, /* @__PURE__ */ new Set());
1543
+ let connection = this.streamConnectionMap.get(key);
1498
1544
  if (!connection || connection.closeInitiated || connection.reconnectionPending) {
1499
- connection = this.getConnection(true);
1500
- this.streamConnectionMap.set(stream, connection);
1545
+ connection = this.getConnection(true, urlPath);
1546
+ this.streamConnectionMap.set(key, connection);
1501
1547
  }
1502
1548
  if (!connectionStreamMap.has(connection)) connectionStreamMap.set(connection, []);
1503
1549
  connectionStreamMap.get(connection)?.push(stream);
@@ -1543,7 +1589,10 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
1543
1589
  try {
1544
1590
  const parsedData = JSONParse(data);
1545
1591
  const streamName = parsedData?.stream;
1546
- if (streamName && this.streamCallbackMap.has(streamName)) this.streamCallbackMap.get(streamName)?.forEach((callback) => callback(parsedData.data));
1592
+ if (streamName) {
1593
+ const key = this.streamKey(streamName, connection?.urlPath);
1594
+ if (this.streamCallbackMap.has(key)) this.streamCallbackMap.get(key)?.forEach((callback) => callback(parsedData.data));
1595
+ }
1547
1596
  } catch (error) {
1548
1597
  this.logger.error("Failed to parse WebSocket message:", data, error);
1549
1598
  }
@@ -1561,6 +1610,15 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
1561
1610
  super.onOpen(url, targetConnection, oldWSConnection);
1562
1611
  }
1563
1612
  /**
1613
+ * Generates a stream key by combining a stream name with an optional URL path.
1614
+ * @param stream - The stream name to use as the key or suffix.
1615
+ * @param urlPath - Optional URL path to prepend to the stream name.
1616
+ * @returns A stream key in the format `urlPath::stream` if urlPath is provided, otherwise just the stream name.
1617
+ */
1618
+ streamKey(stream, urlPath) {
1619
+ return urlPath ? `${urlPath}::${stream}` : stream;
1620
+ }
1621
+ /**
1564
1622
  * Connects to the WebSocket server and subscribes to the specified streams.
1565
1623
  * This method returns a Promise that resolves when the connection is established,
1566
1624
  * or rejects with an error if the connection fails to be established within 10 seconds.
@@ -1573,7 +1631,15 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
1573
1631
  const timeout = setTimeout(() => {
1574
1632
  reject(/* @__PURE__ */ new Error("Websocket connection timed out"));
1575
1633
  }, 1e4);
1576
- this.connectPool(this.prepareURL(streams)).then(() => resolve()).catch((error) => reject(error)).finally(() => clearTimeout(timeout));
1634
+ const basePoolSize = (this.configuration?.mode ?? "single") === "pool" && this.configuration?.poolSize ? this.configuration.poolSize : 1;
1635
+ const connections = this.urlPaths.length > 0 ? this.urlPaths.map((path, i) => {
1636
+ const start = i * basePoolSize;
1637
+ const end = start + basePoolSize;
1638
+ const subset = this.connectionPool.slice(start, end);
1639
+ subset.forEach((c) => c.urlPath = path);
1640
+ return this.connectPool(this.prepareURL(streams, path), subset);
1641
+ }) : [this.connectPool(this.prepareURL(streams))];
1642
+ Promise.all(connections).then(() => resolve()).catch((error) => reject(error)).finally(() => clearTimeout(timeout));
1577
1643
  });
1578
1644
  }
1579
1645
  /**
@@ -1590,17 +1656,21 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
1590
1656
  * Handles both single and pool modes
1591
1657
  * @param stream Single stream name or array of stream names to subscribe to
1592
1658
  * @param id Optional subscription ID
1659
+ * @param urlPath Optional URL path for the streams
1593
1660
  * @returns void
1594
1661
  */
1595
- subscribe(stream, id) {
1596
- const streams = (Array.isArray(stream) ? stream : [stream]).filter((stream$1) => !this.streamConnectionMap.has(stream$1));
1597
- this.handleStreamAssignment(streams).forEach((streams$1, connection) => {
1662
+ subscribe(stream, id, urlPath) {
1663
+ const streams = (Array.isArray(stream) ? stream : [stream]).filter((stream$1) => {
1664
+ const key = this.streamKey(stream$1, urlPath);
1665
+ return !this.streamConnectionMap.has(key);
1666
+ });
1667
+ this.handleStreamAssignment(streams, urlPath).forEach((assignedStreams, connection) => {
1598
1668
  if (!this.isConnected(connection)) {
1599
- this.logger.info(`Connection ${connection.id} is not ready. Queuing subscription for streams: ${streams$1}`);
1600
- connection.pendingSubscriptions?.push(...streams$1);
1669
+ this.logger.info(`Connection ${connection.id} is not ready. Queuing subscription for streams: ${assignedStreams}`);
1670
+ connection.pendingSubscriptions?.push(...assignedStreams);
1601
1671
  return;
1602
1672
  }
1603
- this.sendSubscriptionPayload(connection, streams$1, id);
1673
+ this.sendSubscriptionPayload(connection, assignedStreams, id);
1604
1674
  });
1605
1675
  }
1606
1676
  /**
@@ -1608,16 +1678,18 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
1608
1678
  * Handles both single and pool modes
1609
1679
  * @param stream Single stream name or array of stream names to unsubscribe from
1610
1680
  * @param id Optional unsubscription ID
1681
+ * @param urlPath Optional URL path for the streams
1611
1682
  * @returns void
1612
1683
  */
1613
- unsubscribe(stream, id) {
1684
+ unsubscribe(stream, id, urlPath) {
1614
1685
  (Array.isArray(stream) ? stream : [stream]).forEach((stream$1) => {
1615
- const connection = this.streamConnectionMap.get(stream$1);
1686
+ const key = this.streamKey(stream$1, urlPath);
1687
+ const connection = this.streamConnectionMap.get(key);
1616
1688
  if (!connection || !connection.ws || !this.isConnected(connection)) {
1617
1689
  this.logger.warn(`Stream ${stream$1} not associated with an active connection.`);
1618
1690
  return;
1619
1691
  }
1620
- if (!this.streamCallbackMap.has(stream$1) || this.streamCallbackMap.get(stream$1)?.size === 0) {
1692
+ if (!this.streamCallbackMap.has(key) || this.streamCallbackMap.get(key)?.size === 0) {
1621
1693
  const payload = {
1622
1694
  method: "UNSUBSCRIBE",
1623
1695
  params: [stream$1],
@@ -1625,8 +1697,8 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
1625
1697
  };
1626
1698
  this.logger.debug("UNSUBSCRIBE", payload);
1627
1699
  this.send(JSON.stringify(payload), void 0, false, 0, connection);
1628
- this.streamConnectionMap.delete(stream$1);
1629
- this.streamCallbackMap.delete(stream$1);
1700
+ this.streamConnectionMap.delete(key);
1701
+ this.streamCallbackMap.delete(key);
1630
1702
  }
1631
1703
  });
1632
1704
  }
@@ -1636,7 +1708,9 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
1636
1708
  * @returns `true` if the stream is currently subscribed, `false` otherwise.
1637
1709
  */
1638
1710
  isSubscribed(stream) {
1639
- return this.streamConnectionMap.has(stream);
1711
+ if (this.streamConnectionMap.has(stream)) return true;
1712
+ for (const key of this.streamConnectionMap.keys()) if (key.endsWith(`::${stream}`)) return true;
1713
+ return false;
1640
1714
  }
1641
1715
  };
1642
1716
  /**
@@ -1646,10 +1720,12 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
1646
1720
  * @param {WebsocketAPIBase | WebsocketStreamsBase} websocketBase The WebSocket base instance
1647
1721
  * @param {string} streamOrId The stream identifier
1648
1722
  * @param {string} [id] Optional additional identifier
1723
+ * @param {string} [urlPath] Optional URL path for the stream
1649
1724
  * @returns {WebsocketStream<T>} A stream handler with methods to register callbacks and unsubscribe
1650
1725
  */
1651
- function createStreamHandler(websocketBase, streamOrId, id) {
1652
- if (websocketBase instanceof WebsocketStreamsBase) websocketBase.subscribe(streamOrId, id);
1726
+ function createStreamHandler(websocketBase, streamOrId, id, urlPath) {
1727
+ const key = websocketBase instanceof WebsocketStreamsBase ? websocketBase.streamKey(streamOrId, urlPath) : streamOrId;
1728
+ if (websocketBase instanceof WebsocketStreamsBase) websocketBase.subscribe(streamOrId, id, urlPath);
1653
1729
  let registeredCallback;
1654
1730
  return {
1655
1731
  on: (event, callback) => {
@@ -1659,18 +1735,18 @@ function createStreamHandler(websocketBase, streamOrId, id) {
1659
1735
  websocketBase.logger.error(`Error in stream callback: ${err}`);
1660
1736
  });
1661
1737
  };
1662
- const callbackSet = websocketBase.streamCallbackMap.get(streamOrId) ?? /* @__PURE__ */ new Set();
1738
+ const callbackSet = websocketBase.streamCallbackMap.get(key) ?? /* @__PURE__ */ new Set();
1663
1739
  callbackSet.add(registeredCallback);
1664
- websocketBase.streamCallbackMap.set(streamOrId, callbackSet);
1740
+ websocketBase.streamCallbackMap.set(key, callbackSet);
1665
1741
  }
1666
1742
  },
1667
1743
  unsubscribe: () => {
1668
- if (registeredCallback) websocketBase.streamCallbackMap.get(streamOrId)?.delete(registeredCallback);
1669
- if (websocketBase instanceof WebsocketStreamsBase) websocketBase.unsubscribe(streamOrId, id);
1744
+ if (registeredCallback) websocketBase.streamCallbackMap.get(key)?.delete(registeredCallback);
1745
+ if (websocketBase instanceof WebsocketStreamsBase) websocketBase.unsubscribe(streamOrId, id, urlPath);
1670
1746
  }
1671
1747
  };
1672
1748
  }
1673
1749
 
1674
1750
  //#endregion
1675
- export { ALGO_REST_API_PROD_URL, BadRequestError, C2C_REST_API_PROD_URL, CONVERT_REST_API_PROD_URL, COPY_TRADING_REST_API_PROD_URL, CRYPTO_LOAN_REST_API_PROD_URL, ConfigurationRestAPI, ConfigurationWebsocketAPI, ConfigurationWebsocketStreams, ConnectorClientError, DERIVATIVES_TRADING_COIN_FUTURES_REST_API_PROD_URL, DERIVATIVES_TRADING_COIN_FUTURES_REST_API_TESTNET_URL, DERIVATIVES_TRADING_COIN_FUTURES_WS_API_PROD_URL, DERIVATIVES_TRADING_COIN_FUTURES_WS_API_TESTNET_URL, DERIVATIVES_TRADING_COIN_FUTURES_WS_STREAMS_PROD_URL, DERIVATIVES_TRADING_COIN_FUTURES_WS_STREAMS_TESTNET_URL, DERIVATIVES_TRADING_OPTIONS_REST_API_PROD_URL, DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_PROD_URL, DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_REST_API_PROD_URL, DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_WS_STREAMS_PROD_URL, DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_PROD_URL, DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_TESTNET_URL, DERIVATIVES_TRADING_PORTFOLIO_MARGIN_WS_STREAMS_PROD_URL, DERIVATIVES_TRADING_PORTFOLIO_MARGIN_WS_STREAMS_TESTNET_URL, DERIVATIVES_TRADING_USDS_FUTURES_REST_API_PROD_URL, DERIVATIVES_TRADING_USDS_FUTURES_REST_API_TESTNET_URL, DERIVATIVES_TRADING_USDS_FUTURES_WS_API_PROD_URL, DERIVATIVES_TRADING_USDS_FUTURES_WS_API_TESTNET_URL, DERIVATIVES_TRADING_USDS_FUTURES_WS_STREAMS_PROD_URL, DERIVATIVES_TRADING_USDS_FUTURES_WS_STREAMS_TESTNET_URL, DUAL_INVESTMENT_REST_API_PROD_URL, FIAT_REST_API_PROD_URL, ForbiddenError, GIFT_CARD_REST_API_PROD_URL, LogLevel, Logger, MARGIN_TRADING_REST_API_PROD_URL, MARGIN_TRADING_RISK_WS_STREAMS_PROD_URL, MARGIN_TRADING_WS_STREAMS_PROD_URL, MINING_REST_API_PROD_URL, NFT_REST_API_PROD_URL, NetworkError, NotFoundError, PAY_REST_API_PROD_URL, REBATE_REST_API_PROD_URL, RateLimitBanError, RequiredError, SIMPLE_EARN_REST_API_PROD_URL, SPOT_REST_API_MARKET_URL, SPOT_REST_API_PROD_URL, SPOT_REST_API_TESTNET_URL, SPOT_WS_API_PROD_URL, SPOT_WS_API_TESTNET_URL, SPOT_WS_STREAMS_MARKET_URL, SPOT_WS_STREAMS_PROD_URL, SPOT_WS_STREAMS_TESTNET_URL, STAKING_REST_API_PROD_URL, SUB_ACCOUNT_REST_API_PROD_URL, ServerError, TimeUnit, TooManyRequestsError, UnauthorizedError, VIP_LOAN_REST_API_PROD_URL, WALLET_REST_API_PROD_URL, WebsocketAPIBase, WebsocketCommon, WebsocketEventEmitter, WebsocketStreamsBase, assertParamExists, buildQueryString, buildUserAgent, buildWebsocketAPIMessage, clearSignerCache, createStreamHandler, delay, getSignature, getTimestamp, httpRequestFunction, normalizeScientificNumbers, normalizeStreamId, parseCustomHeaders, parseRateLimitHeaders, randomInteger, randomString, removeEmptyValue, replaceWebsocketStreamsPlaceholders, sanitizeHeaderValue, sendRequest, setSearchParams, shouldRetryRequest, sortObject, toPathString, validateTimeUnit };
1751
+ export { ALGO_REST_API_PROD_URL, BadRequestError, C2C_REST_API_PROD_URL, CONVERT_REST_API_PROD_URL, COPY_TRADING_REST_API_PROD_URL, CRYPTO_LOAN_REST_API_PROD_URL, ConfigurationRestAPI, ConfigurationWebsocketAPI, ConfigurationWebsocketStreams, ConnectorClientError, DERIVATIVES_TRADING_COIN_FUTURES_REST_API_PROD_URL, DERIVATIVES_TRADING_COIN_FUTURES_REST_API_TESTNET_URL, DERIVATIVES_TRADING_COIN_FUTURES_WS_API_PROD_URL, DERIVATIVES_TRADING_COIN_FUTURES_WS_API_TESTNET_URL, DERIVATIVES_TRADING_COIN_FUTURES_WS_STREAMS_PROD_URL, DERIVATIVES_TRADING_COIN_FUTURES_WS_STREAMS_TESTNET_URL, DERIVATIVES_TRADING_OPTIONS_REST_API_PROD_URL, DERIVATIVES_TRADING_OPTIONS_REST_API_TESTNET_URL, DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_PROD_URL, DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_TESTNET_URL, DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_REST_API_PROD_URL, DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_WS_STREAMS_PROD_URL, DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_PROD_URL, DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_TESTNET_URL, DERIVATIVES_TRADING_PORTFOLIO_MARGIN_WS_STREAMS_PROD_URL, DERIVATIVES_TRADING_PORTFOLIO_MARGIN_WS_STREAMS_TESTNET_URL, DERIVATIVES_TRADING_USDS_FUTURES_REST_API_PROD_URL, DERIVATIVES_TRADING_USDS_FUTURES_REST_API_TESTNET_URL, DERIVATIVES_TRADING_USDS_FUTURES_WS_API_PROD_URL, DERIVATIVES_TRADING_USDS_FUTURES_WS_API_TESTNET_URL, DERIVATIVES_TRADING_USDS_FUTURES_WS_STREAMS_PROD_URL, DERIVATIVES_TRADING_USDS_FUTURES_WS_STREAMS_TESTNET_URL, DUAL_INVESTMENT_REST_API_PROD_URL, FIAT_REST_API_PROD_URL, ForbiddenError, GIFT_CARD_REST_API_PROD_URL, LogLevel, Logger, MARGIN_TRADING_REST_API_PROD_URL, MARGIN_TRADING_RISK_WS_STREAMS_PROD_URL, MARGIN_TRADING_WS_STREAMS_PROD_URL, MINING_REST_API_PROD_URL, NFT_REST_API_PROD_URL, NetworkError, NotFoundError, PAY_REST_API_PROD_URL, REBATE_REST_API_PROD_URL, RateLimitBanError, RequiredError, SIMPLE_EARN_REST_API_PROD_URL, SPOT_REST_API_MARKET_URL, SPOT_REST_API_PROD_URL, SPOT_REST_API_TESTNET_URL, SPOT_WS_API_PROD_URL, SPOT_WS_API_TESTNET_URL, SPOT_WS_STREAMS_MARKET_URL, SPOT_WS_STREAMS_PROD_URL, SPOT_WS_STREAMS_TESTNET_URL, STAKING_REST_API_PROD_URL, SUB_ACCOUNT_REST_API_PROD_URL, ServerError, TimeUnit, TooManyRequestsError, UnauthorizedError, VIP_LOAN_REST_API_PROD_URL, WALLET_REST_API_PROD_URL, WebsocketAPIBase, WebsocketCommon, WebsocketEventEmitter, WebsocketStreamsBase, assertParamExists, buildQueryString, buildUserAgent, buildWebsocketAPIMessage, clearSignerCache, createStreamHandler, delay, getSignature, getTimestamp, httpRequestFunction, normalizeScientificNumbers, normalizeStreamId, parseCustomHeaders, parseRateLimitHeaders, randomInteger, randomString, removeEmptyValue, replaceWebsocketStreamsPlaceholders, sanitizeHeaderValue, sendRequest, setSearchParams, shouldRetryRequest, sortObject, toPathString, validateTimeUnit };
1676
1752
  //# sourceMappingURL=index.mjs.map