@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.d.mts +56 -16
- package/dist/index.d.ts +56 -16
- package/dist/index.js +132 -54
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +131 -55
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -372,16 +372,17 @@ const httpRequestFunction = async function(axiosArgs, configuration) {
|
|
|
372
372
|
else if (typeof responseData === "object") data = responseData;
|
|
373
373
|
}
|
|
374
374
|
const errorMsg = data.msg;
|
|
375
|
+
const errorCode = typeof data.code === "number" ? data.code : void 0;
|
|
375
376
|
switch (status) {
|
|
376
|
-
case 400: throw new BadRequestError(errorMsg);
|
|
377
|
-
case 401: throw new UnauthorizedError(errorMsg);
|
|
378
|
-
case 403: throw new ForbiddenError(errorMsg);
|
|
379
|
-
case 404: throw new NotFoundError(errorMsg);
|
|
380
|
-
case 418: throw new RateLimitBanError(errorMsg);
|
|
381
|
-
case 429: throw new TooManyRequestsError(errorMsg);
|
|
377
|
+
case 400: throw new BadRequestError(errorMsg, errorCode);
|
|
378
|
+
case 401: throw new UnauthorizedError(errorMsg, errorCode);
|
|
379
|
+
case 403: throw new ForbiddenError(errorMsg, errorCode);
|
|
380
|
+
case 404: throw new NotFoundError(errorMsg, errorCode);
|
|
381
|
+
case 418: throw new RateLimitBanError(errorMsg, errorCode);
|
|
382
|
+
case 429: throw new TooManyRequestsError(errorMsg, errorCode);
|
|
382
383
|
default:
|
|
383
384
|
if (status >= 500 && status < 600) throw new ServerError(`Server error: ${status}`, status);
|
|
384
|
-
throw new ConnectorClientError(errorMsg);
|
|
385
|
+
throw new ConnectorClientError(errorMsg, errorCode);
|
|
385
386
|
}
|
|
386
387
|
} else {
|
|
387
388
|
if (retries > 0 && attempt >= retries) lastError = /* @__PURE__ */ new Error(`Request failed after ${retries} retries`);
|
|
@@ -718,7 +719,9 @@ const DERIVATIVES_TRADING_USDS_FUTURES_WS_API_TESTNET_URL = "wss://testnet.binan
|
|
|
718
719
|
const DERIVATIVES_TRADING_USDS_FUTURES_WS_STREAMS_PROD_URL = "wss://fstream.binance.com";
|
|
719
720
|
const DERIVATIVES_TRADING_USDS_FUTURES_WS_STREAMS_TESTNET_URL = "wss://stream.binancefuture.com";
|
|
720
721
|
const DERIVATIVES_TRADING_OPTIONS_REST_API_PROD_URL = "https://eapi.binance.com";
|
|
721
|
-
const
|
|
722
|
+
const DERIVATIVES_TRADING_OPTIONS_REST_API_TESTNET_URL = "https://testnet.binancefuture.com";
|
|
723
|
+
const DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_PROD_URL = "wss://fstream.binance.com";
|
|
724
|
+
const DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_TESTNET_URL = "wss://fstream.binancefuture.com";
|
|
722
725
|
const DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_PROD_URL = "https://papi.binance.com";
|
|
723
726
|
const DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_TESTNET_URL = "https://testnet.binancefuture.com";
|
|
724
727
|
const DERIVATIVES_TRADING_PORTFOLIO_MARGIN_WS_STREAMS_PROD_URL = "wss://fstream.binance.com/pm";
|
|
@@ -756,10 +759,11 @@ const WALLET_REST_API_PROD_URL = "https://api.binance.com";
|
|
|
756
759
|
* @param msg - An optional error message.
|
|
757
760
|
*/
|
|
758
761
|
var ConnectorClientError = class ConnectorClientError extends Error {
|
|
759
|
-
constructor(msg) {
|
|
762
|
+
constructor(msg, code) {
|
|
760
763
|
super(msg || "An unexpected error occurred.");
|
|
761
764
|
Object.setPrototypeOf(this, ConnectorClientError.prototype);
|
|
762
765
|
this.name = "ConnectorClientError";
|
|
766
|
+
this.code = code;
|
|
763
767
|
}
|
|
764
768
|
};
|
|
765
769
|
/**
|
|
@@ -780,10 +784,11 @@ var RequiredError = class RequiredError extends Error {
|
|
|
780
784
|
* @param msg - An optional error message.
|
|
781
785
|
*/
|
|
782
786
|
var UnauthorizedError = class UnauthorizedError extends Error {
|
|
783
|
-
constructor(msg) {
|
|
787
|
+
constructor(msg, code) {
|
|
784
788
|
super(msg || "Unauthorized access. Authentication required.");
|
|
785
789
|
Object.setPrototypeOf(this, UnauthorizedError.prototype);
|
|
786
790
|
this.name = "UnauthorizedError";
|
|
791
|
+
this.code = code;
|
|
787
792
|
}
|
|
788
793
|
};
|
|
789
794
|
/**
|
|
@@ -791,10 +796,11 @@ var UnauthorizedError = class UnauthorizedError extends Error {
|
|
|
791
796
|
* @param msg - An optional error message.
|
|
792
797
|
*/
|
|
793
798
|
var ForbiddenError = class ForbiddenError extends Error {
|
|
794
|
-
constructor(msg) {
|
|
799
|
+
constructor(msg, code) {
|
|
795
800
|
super(msg || "Access to the requested resource is forbidden.");
|
|
796
801
|
Object.setPrototypeOf(this, ForbiddenError.prototype);
|
|
797
802
|
this.name = "ForbiddenError";
|
|
803
|
+
this.code = code;
|
|
798
804
|
}
|
|
799
805
|
};
|
|
800
806
|
/**
|
|
@@ -802,10 +808,11 @@ var ForbiddenError = class ForbiddenError extends Error {
|
|
|
802
808
|
* @param msg - An optional error message.
|
|
803
809
|
*/
|
|
804
810
|
var TooManyRequestsError = class TooManyRequestsError extends Error {
|
|
805
|
-
constructor(msg) {
|
|
811
|
+
constructor(msg, code) {
|
|
806
812
|
super(msg || "Too many requests. You are being rate-limited.");
|
|
807
813
|
Object.setPrototypeOf(this, TooManyRequestsError.prototype);
|
|
808
814
|
this.name = "TooManyRequestsError";
|
|
815
|
+
this.code = code;
|
|
809
816
|
}
|
|
810
817
|
};
|
|
811
818
|
/**
|
|
@@ -813,10 +820,11 @@ var TooManyRequestsError = class TooManyRequestsError extends Error {
|
|
|
813
820
|
* @param msg - An optional error message.
|
|
814
821
|
*/
|
|
815
822
|
var RateLimitBanError = class RateLimitBanError extends Error {
|
|
816
|
-
constructor(msg) {
|
|
823
|
+
constructor(msg, code) {
|
|
817
824
|
super(msg || "The IP address has been banned for exceeding rate limits.");
|
|
818
825
|
Object.setPrototypeOf(this, RateLimitBanError.prototype);
|
|
819
826
|
this.name = "RateLimitBanError";
|
|
827
|
+
this.code = code;
|
|
820
828
|
}
|
|
821
829
|
};
|
|
822
830
|
/**
|
|
@@ -848,10 +856,11 @@ var NetworkError = class NetworkError extends Error {
|
|
|
848
856
|
* @param msg - An optional error message.
|
|
849
857
|
*/
|
|
850
858
|
var NotFoundError = class NotFoundError extends Error {
|
|
851
|
-
constructor(msg) {
|
|
859
|
+
constructor(msg, code) {
|
|
852
860
|
super(msg || "The requested resource was not found.");
|
|
853
861
|
Object.setPrototypeOf(this, NotFoundError.prototype);
|
|
854
862
|
this.name = "NotFoundError";
|
|
863
|
+
this.code = code;
|
|
855
864
|
}
|
|
856
865
|
};
|
|
857
866
|
/**
|
|
@@ -859,10 +868,11 @@ var NotFoundError = class NotFoundError extends Error {
|
|
|
859
868
|
* @param msg - An optional error message.
|
|
860
869
|
*/
|
|
861
870
|
var BadRequestError = class BadRequestError extends Error {
|
|
862
|
-
constructor(msg) {
|
|
871
|
+
constructor(msg, code) {
|
|
863
872
|
super(msg || "The request was invalid or cannot be otherwise served.");
|
|
864
873
|
Object.setPrototypeOf(this, BadRequestError.prototype);
|
|
865
874
|
this.name = "BadRequestError";
|
|
875
|
+
this.code = code;
|
|
866
876
|
}
|
|
867
877
|
};
|
|
868
878
|
|
|
@@ -980,10 +990,11 @@ var WebsocketCommon = class WebsocketCommon extends WebsocketEventEmitter {
|
|
|
980
990
|
* In 'single' mode, returns the first connection in the pool.
|
|
981
991
|
* In 'pool' mode, filters and returns connections that are ready for use.
|
|
982
992
|
* @param allowNonEstablishedWebsockets - Optional flag to include non-established WebSocket connections.
|
|
993
|
+
* @param urlPath - Optional URL path to filter connections.
|
|
983
994
|
* @returns An array of available WebSocket connections.
|
|
984
995
|
*/
|
|
985
|
-
getAvailableConnections(allowNonEstablishedWebsockets = false) {
|
|
986
|
-
if (this.mode === "single") return [this.connectionPool[0]];
|
|
996
|
+
getAvailableConnections(allowNonEstablishedWebsockets = false, urlPath) {
|
|
997
|
+
if (this.mode === "single" && !urlPath) return [this.connectionPool[0]];
|
|
987
998
|
return this.connectionPool.filter((connection) => this.isConnectionReady(connection, allowNonEstablishedWebsockets));
|
|
988
999
|
}
|
|
989
1000
|
/**
|
|
@@ -992,10 +1003,14 @@ var WebsocketCommon = class WebsocketCommon extends WebsocketEventEmitter {
|
|
|
992
1003
|
* If the connection mode is 'pool', it returns an available connection from the pool,
|
|
993
1004
|
* using a round-robin selection strategy. If no available connections are found, it throws an error.
|
|
994
1005
|
* @param allowNonEstablishedWebsockets - A boolean indicating whether to allow connections that are not established.
|
|
1006
|
+
* @param urlPath - An optional URL path to filter connections.
|
|
995
1007
|
* @returns {WebsocketConnection} The selected WebSocket connection.
|
|
996
1008
|
*/
|
|
997
|
-
getConnection(allowNonEstablishedWebsockets = false) {
|
|
998
|
-
const availableConnections = this.getAvailableConnections(allowNonEstablishedWebsockets)
|
|
1009
|
+
getConnection(allowNonEstablishedWebsockets = false, urlPath) {
|
|
1010
|
+
const availableConnections = this.getAvailableConnections(allowNonEstablishedWebsockets, urlPath).filter((connection) => {
|
|
1011
|
+
if (urlPath) return connection.urlPath === urlPath;
|
|
1012
|
+
return true;
|
|
1013
|
+
});
|
|
999
1014
|
if (availableConnections.length === 0) throw new Error("No available Websocket connections are ready.");
|
|
1000
1015
|
const selectedConnection = availableConnections[this.roundRobinIndex % availableConnections.length];
|
|
1001
1016
|
this.roundRobinIndex = (this.roundRobinIndex + 1) % availableConnections.length;
|
|
@@ -1193,14 +1208,15 @@ var WebsocketCommon = class WebsocketCommon extends WebsocketEventEmitter {
|
|
|
1193
1208
|
/**
|
|
1194
1209
|
* Connects all WebSocket connections in the pool
|
|
1195
1210
|
* @param url - The Websocket server URL.
|
|
1211
|
+
* @param connections - An optional array of WebSocket connections to connect. If not provided, all connections in the pool are connected.
|
|
1196
1212
|
* @returns A promise that resolves when all connections are established.
|
|
1197
1213
|
*/
|
|
1198
|
-
async connectPool(url) {
|
|
1199
|
-
const connectPromises = this.connectionPool.map((connection) => new Promise((resolve, reject) => {
|
|
1214
|
+
async connectPool(url, connections) {
|
|
1215
|
+
const connectPromises = (connections ?? this.connectionPool).map((connection) => new Promise((resolve, reject) => {
|
|
1200
1216
|
this.initConnect(url, false, connection);
|
|
1201
|
-
connection.ws?.
|
|
1202
|
-
connection.ws?.
|
|
1203
|
-
connection.ws?.
|
|
1217
|
+
connection.ws?.once("open", () => resolve());
|
|
1218
|
+
connection.ws?.once("error", (err) => reject(err));
|
|
1219
|
+
connection.ws?.once("close", () => reject(/* @__PURE__ */ new Error("Connection closed unexpectedly.")));
|
|
1204
1220
|
}));
|
|
1205
1221
|
await Promise.all(connectPromises);
|
|
1206
1222
|
}
|
|
@@ -1479,7 +1495,7 @@ var WebsocketAPIBase = class extends WebsocketCommon {
|
|
|
1479
1495
|
}
|
|
1480
1496
|
};
|
|
1481
1497
|
var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
1482
|
-
constructor(configuration, connectionPool = []) {
|
|
1498
|
+
constructor(configuration, connectionPool = [], urlPaths = []) {
|
|
1483
1499
|
super(configuration, connectionPool);
|
|
1484
1500
|
this.streamConnectionMap = /* @__PURE__ */ new Map();
|
|
1485
1501
|
this.streamIdIsStrictlyNumber = false;
|
|
@@ -1487,14 +1503,42 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
|
1487
1503
|
this.logger = Logger.getInstance();
|
|
1488
1504
|
this.configuration = configuration;
|
|
1489
1505
|
this.wsURL = configuration.wsURL;
|
|
1506
|
+
this.urlPaths = urlPaths;
|
|
1507
|
+
this.ensurePoolSizeForUrlPaths();
|
|
1508
|
+
}
|
|
1509
|
+
/**
|
|
1510
|
+
* Ensures the connection pool has the required size based on the configured mode and number of URL paths.
|
|
1511
|
+
*
|
|
1512
|
+
* If no URL paths are configured, the method returns early without modifications.
|
|
1513
|
+
* In 'pool' mode, the pool size is multiplied by the number of URL paths.
|
|
1514
|
+
* In 'single' mode, only one connection per URL path is maintained.
|
|
1515
|
+
*
|
|
1516
|
+
* New connections are initialized with unique IDs and default state flags when the pool
|
|
1517
|
+
* size is less than the expected size.
|
|
1518
|
+
*
|
|
1519
|
+
* @private
|
|
1520
|
+
* @returns {void}
|
|
1521
|
+
*/
|
|
1522
|
+
ensurePoolSizeForUrlPaths() {
|
|
1523
|
+
if (this.urlPaths.length === 0) return;
|
|
1524
|
+
const expected = ((this.configuration?.mode ?? "single") === "pool" && this.configuration?.poolSize ? this.configuration.poolSize : 1) * this.urlPaths.length;
|
|
1525
|
+
while (this.connectionPool.length < expected) this.connectionPool.push({
|
|
1526
|
+
id: randomString(),
|
|
1527
|
+
closeInitiated: false,
|
|
1528
|
+
reconnectionPending: false,
|
|
1529
|
+
renewalPending: false,
|
|
1530
|
+
pendingRequests: /* @__PURE__ */ new Map(),
|
|
1531
|
+
pendingSubscriptions: []
|
|
1532
|
+
});
|
|
1490
1533
|
}
|
|
1491
1534
|
/**
|
|
1492
1535
|
* Formats the WebSocket URL for a given stream or streams.
|
|
1493
1536
|
* @param streams - Array of stream names to include in the URL.
|
|
1537
|
+
* @param urlPath - Optional URL path to include in the WebSocket URL.
|
|
1494
1538
|
* @returns The formatted WebSocket URL with the provided streams.
|
|
1495
1539
|
*/
|
|
1496
|
-
prepareURL(streams = []) {
|
|
1497
|
-
let url = `${this.wsURL}/stream?streams=${streams.join("/")}`;
|
|
1540
|
+
prepareURL(streams = [], urlPath) {
|
|
1541
|
+
let url = `${urlPath ? `${this.wsURL}/${urlPath}` : this.wsURL}/stream?streams=${streams.join("/")}`;
|
|
1498
1542
|
if (this.configuration?.timeUnit) try {
|
|
1499
1543
|
const _timeUnit = validateTimeUnit(this.configuration.timeUnit);
|
|
1500
1544
|
url = `${url}${url.includes("?") ? "&" : "?"}timeUnit=${_timeUnit}`;
|
|
@@ -1510,22 +1554,24 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
|
1510
1554
|
* @returns The formatted WebSocket URL with streams and optional parameters.
|
|
1511
1555
|
*/
|
|
1512
1556
|
getReconnectURL(url, targetConnection) {
|
|
1513
|
-
const streams = Array.from(this.streamConnectionMap.keys()).filter((stream) => this.streamConnectionMap.get(stream) === targetConnection);
|
|
1514
|
-
return this.prepareURL(streams);
|
|
1557
|
+
const streams = Array.from(this.streamConnectionMap.keys()).filter((stream) => this.streamConnectionMap.get(stream) === targetConnection).map((key) => key.includes("::") ? key.split("::").slice(1).join("::") : key);
|
|
1558
|
+
return this.prepareURL(streams, targetConnection?.urlPath);
|
|
1515
1559
|
}
|
|
1516
1560
|
/**
|
|
1517
1561
|
* Handles subscription to streams and assigns them to specific connections
|
|
1518
1562
|
* @param streams Array of stream names to subscribe to
|
|
1563
|
+
* @param urlPath Optional URL path for the streams
|
|
1519
1564
|
* @returns Map of connections to streams
|
|
1520
1565
|
*/
|
|
1521
|
-
handleStreamAssignment(streams) {
|
|
1566
|
+
handleStreamAssignment(streams, urlPath) {
|
|
1522
1567
|
const connectionStreamMap = /* @__PURE__ */ new Map();
|
|
1523
1568
|
streams.forEach((stream) => {
|
|
1524
|
-
|
|
1525
|
-
|
|
1569
|
+
const key = this.streamKey(stream, urlPath);
|
|
1570
|
+
if (!this.streamCallbackMap.has(key)) this.streamCallbackMap.set(key, /* @__PURE__ */ new Set());
|
|
1571
|
+
let connection = this.streamConnectionMap.get(key);
|
|
1526
1572
|
if (!connection || connection.closeInitiated || connection.reconnectionPending) {
|
|
1527
|
-
connection = this.getConnection(true);
|
|
1528
|
-
this.streamConnectionMap.set(
|
|
1573
|
+
connection = this.getConnection(true, urlPath);
|
|
1574
|
+
this.streamConnectionMap.set(key, connection);
|
|
1529
1575
|
}
|
|
1530
1576
|
if (!connectionStreamMap.has(connection)) connectionStreamMap.set(connection, []);
|
|
1531
1577
|
connectionStreamMap.get(connection)?.push(stream);
|
|
@@ -1571,7 +1617,10 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
|
1571
1617
|
try {
|
|
1572
1618
|
const parsedData = (0, json_with_bigint.JSONParse)(data);
|
|
1573
1619
|
const streamName = parsedData?.stream;
|
|
1574
|
-
if (streamName
|
|
1620
|
+
if (streamName) {
|
|
1621
|
+
const key = this.streamKey(streamName, connection?.urlPath);
|
|
1622
|
+
if (this.streamCallbackMap.has(key)) this.streamCallbackMap.get(key)?.forEach((callback) => callback(parsedData.data));
|
|
1623
|
+
}
|
|
1575
1624
|
} catch (error) {
|
|
1576
1625
|
this.logger.error("Failed to parse WebSocket message:", data, error);
|
|
1577
1626
|
}
|
|
@@ -1589,6 +1638,15 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
|
1589
1638
|
super.onOpen(url, targetConnection, oldWSConnection);
|
|
1590
1639
|
}
|
|
1591
1640
|
/**
|
|
1641
|
+
* Generates a stream key by combining a stream name with an optional URL path.
|
|
1642
|
+
* @param stream - The stream name to use as the key or suffix.
|
|
1643
|
+
* @param urlPath - Optional URL path to prepend to the stream name.
|
|
1644
|
+
* @returns A stream key in the format `urlPath::stream` if urlPath is provided, otherwise just the stream name.
|
|
1645
|
+
*/
|
|
1646
|
+
streamKey(stream, urlPath) {
|
|
1647
|
+
return urlPath ? `${urlPath}::${stream}` : stream;
|
|
1648
|
+
}
|
|
1649
|
+
/**
|
|
1592
1650
|
* Connects to the WebSocket server and subscribes to the specified streams.
|
|
1593
1651
|
* This method returns a Promise that resolves when the connection is established,
|
|
1594
1652
|
* or rejects with an error if the connection fails to be established within 10 seconds.
|
|
@@ -1601,7 +1659,15 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
|
1601
1659
|
const timeout = setTimeout(() => {
|
|
1602
1660
|
reject(/* @__PURE__ */ new Error("Websocket connection timed out"));
|
|
1603
1661
|
}, 1e4);
|
|
1604
|
-
|
|
1662
|
+
const basePoolSize = (this.configuration?.mode ?? "single") === "pool" && this.configuration?.poolSize ? this.configuration.poolSize : 1;
|
|
1663
|
+
const connections = this.urlPaths.length > 0 ? this.urlPaths.map((path, i) => {
|
|
1664
|
+
const start = i * basePoolSize;
|
|
1665
|
+
const end = start + basePoolSize;
|
|
1666
|
+
const subset = this.connectionPool.slice(start, end);
|
|
1667
|
+
subset.forEach((c) => c.urlPath = path);
|
|
1668
|
+
return this.connectPool(this.prepareURL(streams, path), subset);
|
|
1669
|
+
}) : [this.connectPool(this.prepareURL(streams))];
|
|
1670
|
+
Promise.all(connections).then(() => resolve()).catch((error) => reject(error)).finally(() => clearTimeout(timeout));
|
|
1605
1671
|
});
|
|
1606
1672
|
}
|
|
1607
1673
|
/**
|
|
@@ -1618,17 +1684,21 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
|
1618
1684
|
* Handles both single and pool modes
|
|
1619
1685
|
* @param stream Single stream name or array of stream names to subscribe to
|
|
1620
1686
|
* @param id Optional subscription ID
|
|
1687
|
+
* @param urlPath Optional URL path for the streams
|
|
1621
1688
|
* @returns void
|
|
1622
1689
|
*/
|
|
1623
|
-
subscribe(stream, id) {
|
|
1624
|
-
const streams = (Array.isArray(stream) ? stream : [stream]).filter((stream$1) =>
|
|
1625
|
-
|
|
1690
|
+
subscribe(stream, id, urlPath) {
|
|
1691
|
+
const streams = (Array.isArray(stream) ? stream : [stream]).filter((stream$1) => {
|
|
1692
|
+
const key = this.streamKey(stream$1, urlPath);
|
|
1693
|
+
return !this.streamConnectionMap.has(key);
|
|
1694
|
+
});
|
|
1695
|
+
this.handleStreamAssignment(streams, urlPath).forEach((assignedStreams, connection) => {
|
|
1626
1696
|
if (!this.isConnected(connection)) {
|
|
1627
|
-
this.logger.info(`Connection ${connection.id} is not ready. Queuing subscription for streams: ${
|
|
1628
|
-
connection.pendingSubscriptions?.push(...
|
|
1697
|
+
this.logger.info(`Connection ${connection.id} is not ready. Queuing subscription for streams: ${assignedStreams}`);
|
|
1698
|
+
connection.pendingSubscriptions?.push(...assignedStreams);
|
|
1629
1699
|
return;
|
|
1630
1700
|
}
|
|
1631
|
-
this.sendSubscriptionPayload(connection,
|
|
1701
|
+
this.sendSubscriptionPayload(connection, assignedStreams, id);
|
|
1632
1702
|
});
|
|
1633
1703
|
}
|
|
1634
1704
|
/**
|
|
@@ -1636,16 +1706,18 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
|
1636
1706
|
* Handles both single and pool modes
|
|
1637
1707
|
* @param stream Single stream name or array of stream names to unsubscribe from
|
|
1638
1708
|
* @param id Optional unsubscription ID
|
|
1709
|
+
* @param urlPath Optional URL path for the streams
|
|
1639
1710
|
* @returns void
|
|
1640
1711
|
*/
|
|
1641
|
-
unsubscribe(stream, id) {
|
|
1712
|
+
unsubscribe(stream, id, urlPath) {
|
|
1642
1713
|
(Array.isArray(stream) ? stream : [stream]).forEach((stream$1) => {
|
|
1643
|
-
const
|
|
1714
|
+
const key = this.streamKey(stream$1, urlPath);
|
|
1715
|
+
const connection = this.streamConnectionMap.get(key);
|
|
1644
1716
|
if (!connection || !connection.ws || !this.isConnected(connection)) {
|
|
1645
1717
|
this.logger.warn(`Stream ${stream$1} not associated with an active connection.`);
|
|
1646
1718
|
return;
|
|
1647
1719
|
}
|
|
1648
|
-
if (!this.streamCallbackMap.has(
|
|
1720
|
+
if (!this.streamCallbackMap.has(key) || this.streamCallbackMap.get(key)?.size === 0) {
|
|
1649
1721
|
const payload = {
|
|
1650
1722
|
method: "UNSUBSCRIBE",
|
|
1651
1723
|
params: [stream$1],
|
|
@@ -1653,8 +1725,8 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
|
1653
1725
|
};
|
|
1654
1726
|
this.logger.debug("UNSUBSCRIBE", payload);
|
|
1655
1727
|
this.send(JSON.stringify(payload), void 0, false, 0, connection);
|
|
1656
|
-
this.streamConnectionMap.delete(
|
|
1657
|
-
this.streamCallbackMap.delete(
|
|
1728
|
+
this.streamConnectionMap.delete(key);
|
|
1729
|
+
this.streamCallbackMap.delete(key);
|
|
1658
1730
|
}
|
|
1659
1731
|
});
|
|
1660
1732
|
}
|
|
@@ -1664,7 +1736,9 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
|
1664
1736
|
* @returns `true` if the stream is currently subscribed, `false` otherwise.
|
|
1665
1737
|
*/
|
|
1666
1738
|
isSubscribed(stream) {
|
|
1667
|
-
|
|
1739
|
+
if (this.streamConnectionMap.has(stream)) return true;
|
|
1740
|
+
for (const key of this.streamConnectionMap.keys()) if (key.endsWith(`::${stream}`)) return true;
|
|
1741
|
+
return false;
|
|
1668
1742
|
}
|
|
1669
1743
|
};
|
|
1670
1744
|
/**
|
|
@@ -1674,10 +1748,12 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
|
1674
1748
|
* @param {WebsocketAPIBase | WebsocketStreamsBase} websocketBase The WebSocket base instance
|
|
1675
1749
|
* @param {string} streamOrId The stream identifier
|
|
1676
1750
|
* @param {string} [id] Optional additional identifier
|
|
1751
|
+
* @param {string} [urlPath] Optional URL path for the stream
|
|
1677
1752
|
* @returns {WebsocketStream<T>} A stream handler with methods to register callbacks and unsubscribe
|
|
1678
1753
|
*/
|
|
1679
|
-
function createStreamHandler(websocketBase, streamOrId, id) {
|
|
1680
|
-
|
|
1754
|
+
function createStreamHandler(websocketBase, streamOrId, id, urlPath) {
|
|
1755
|
+
const key = websocketBase instanceof WebsocketStreamsBase ? websocketBase.streamKey(streamOrId, urlPath) : streamOrId;
|
|
1756
|
+
if (websocketBase instanceof WebsocketStreamsBase) websocketBase.subscribe(streamOrId, id, urlPath);
|
|
1681
1757
|
let registeredCallback;
|
|
1682
1758
|
return {
|
|
1683
1759
|
on: (event, callback) => {
|
|
@@ -1687,14 +1763,14 @@ function createStreamHandler(websocketBase, streamOrId, id) {
|
|
|
1687
1763
|
websocketBase.logger.error(`Error in stream callback: ${err}`);
|
|
1688
1764
|
});
|
|
1689
1765
|
};
|
|
1690
|
-
const callbackSet = websocketBase.streamCallbackMap.get(
|
|
1766
|
+
const callbackSet = websocketBase.streamCallbackMap.get(key) ?? /* @__PURE__ */ new Set();
|
|
1691
1767
|
callbackSet.add(registeredCallback);
|
|
1692
|
-
websocketBase.streamCallbackMap.set(
|
|
1768
|
+
websocketBase.streamCallbackMap.set(key, callbackSet);
|
|
1693
1769
|
}
|
|
1694
1770
|
},
|
|
1695
1771
|
unsubscribe: () => {
|
|
1696
|
-
if (registeredCallback) websocketBase.streamCallbackMap.get(
|
|
1697
|
-
if (websocketBase instanceof WebsocketStreamsBase) websocketBase.unsubscribe(streamOrId, id);
|
|
1772
|
+
if (registeredCallback) websocketBase.streamCallbackMap.get(key)?.delete(registeredCallback);
|
|
1773
|
+
if (websocketBase instanceof WebsocketStreamsBase) websocketBase.unsubscribe(streamOrId, id, urlPath);
|
|
1698
1774
|
}
|
|
1699
1775
|
};
|
|
1700
1776
|
}
|
|
@@ -1717,7 +1793,9 @@ exports.DERIVATIVES_TRADING_COIN_FUTURES_WS_API_TESTNET_URL = DERIVATIVES_TRADIN
|
|
|
1717
1793
|
exports.DERIVATIVES_TRADING_COIN_FUTURES_WS_STREAMS_PROD_URL = DERIVATIVES_TRADING_COIN_FUTURES_WS_STREAMS_PROD_URL;
|
|
1718
1794
|
exports.DERIVATIVES_TRADING_COIN_FUTURES_WS_STREAMS_TESTNET_URL = DERIVATIVES_TRADING_COIN_FUTURES_WS_STREAMS_TESTNET_URL;
|
|
1719
1795
|
exports.DERIVATIVES_TRADING_OPTIONS_REST_API_PROD_URL = DERIVATIVES_TRADING_OPTIONS_REST_API_PROD_URL;
|
|
1796
|
+
exports.DERIVATIVES_TRADING_OPTIONS_REST_API_TESTNET_URL = DERIVATIVES_TRADING_OPTIONS_REST_API_TESTNET_URL;
|
|
1720
1797
|
exports.DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_PROD_URL = DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_PROD_URL;
|
|
1798
|
+
exports.DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_TESTNET_URL = DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_TESTNET_URL;
|
|
1721
1799
|
exports.DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_REST_API_PROD_URL = DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_REST_API_PROD_URL;
|
|
1722
1800
|
exports.DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_WS_STREAMS_PROD_URL = DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_WS_STREAMS_PROD_URL;
|
|
1723
1801
|
exports.DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_PROD_URL = DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_PROD_URL;
|