@binance/common 2.1.0 → 2.2.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 +70 -9
- package/dist/index.d.ts +70 -9
- package/dist/index.js +151 -42
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +148 -43
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -140,6 +140,42 @@ function randomString() {
|
|
|
140
140
|
return crypto.default.randomBytes(16).toString("hex");
|
|
141
141
|
}
|
|
142
142
|
/**
|
|
143
|
+
* Generates a cryptographically secure random 32-bit unsigned integer.
|
|
144
|
+
*
|
|
145
|
+
* Uses the Web Crypto API to generate a random value between 0 and 4,294,967,295 (2^32 - 1).
|
|
146
|
+
*
|
|
147
|
+
* @returns A random 32-bit unsigned integer.
|
|
148
|
+
*/
|
|
149
|
+
function randomInteger() {
|
|
150
|
+
const array = new Uint32Array(1);
|
|
151
|
+
crypto.default.getRandomValues(array);
|
|
152
|
+
return array[0];
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Normalizes a stream ID to ensure it is valid, generating a random ID if needed.
|
|
156
|
+
*
|
|
157
|
+
* For string inputs:
|
|
158
|
+
* - Returns the input if it's a valid 32-character hexadecimal string (case-insensitive)
|
|
159
|
+
* - Otherwise, generates a new random hexadecimal string using `randomString()`
|
|
160
|
+
*
|
|
161
|
+
* For number inputs:
|
|
162
|
+
* - Returns the input if it's a finite, non-negative integer within the safe integer range
|
|
163
|
+
* - Otherwise, generates a new random integer using `randomInteger()`
|
|
164
|
+
*
|
|
165
|
+
* For null or undefined inputs:
|
|
166
|
+
* - Generates a new random hexadecimal string using `randomString()`
|
|
167
|
+
*
|
|
168
|
+
* @param id - The stream ID to normalize (string, number, null, or undefined).
|
|
169
|
+
* @param streamIdIsStrictlyNumber - Boolean forcing an id to be a number or not.
|
|
170
|
+
* @returns A valid stream ID as either a 32-character hexadecimal string or a safe integer.
|
|
171
|
+
*/
|
|
172
|
+
function normalizeStreamId(id, streamIdIsStrictlyNumber) {
|
|
173
|
+
const isValidNumber = typeof id === "number" && Number.isFinite(id) && Number.isInteger(id) && id >= 0 && id <= Number.MAX_SAFE_INTEGER;
|
|
174
|
+
if (streamIdIsStrictlyNumber || typeof id === "number") return isValidNumber ? id : randomInteger();
|
|
175
|
+
if (typeof id === "string") return id && /^[0-9a-f]{32}$/i.test(id) ? id : randomString();
|
|
176
|
+
return randomString();
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
143
179
|
* Validates the provided time unit string and returns it if it is either 'MILLISECOND' or 'MICROSECOND'.
|
|
144
180
|
*
|
|
145
181
|
* @param timeUnit - The time unit string to be validated.
|
|
@@ -682,7 +718,9 @@ const DERIVATIVES_TRADING_USDS_FUTURES_WS_API_TESTNET_URL = "wss://testnet.binan
|
|
|
682
718
|
const DERIVATIVES_TRADING_USDS_FUTURES_WS_STREAMS_PROD_URL = "wss://fstream.binance.com";
|
|
683
719
|
const DERIVATIVES_TRADING_USDS_FUTURES_WS_STREAMS_TESTNET_URL = "wss://stream.binancefuture.com";
|
|
684
720
|
const DERIVATIVES_TRADING_OPTIONS_REST_API_PROD_URL = "https://eapi.binance.com";
|
|
685
|
-
const
|
|
721
|
+
const DERIVATIVES_TRADING_OPTIONS_REST_API_TESTNET_URL = "https://testnet.binancefuture.com";
|
|
722
|
+
const DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_PROD_URL = "wss://fstream.binance.com";
|
|
723
|
+
const DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_TESTNET_URL = "wss://fstream.binancefuture.com";
|
|
686
724
|
const DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_PROD_URL = "https://papi.binance.com";
|
|
687
725
|
const DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_TESTNET_URL = "https://testnet.binancefuture.com";
|
|
688
726
|
const DERIVATIVES_TRADING_PORTFOLIO_MARGIN_WS_STREAMS_PROD_URL = "wss://fstream.binance.com/pm";
|
|
@@ -944,10 +982,11 @@ var WebsocketCommon = class WebsocketCommon extends WebsocketEventEmitter {
|
|
|
944
982
|
* In 'single' mode, returns the first connection in the pool.
|
|
945
983
|
* In 'pool' mode, filters and returns connections that are ready for use.
|
|
946
984
|
* @param allowNonEstablishedWebsockets - Optional flag to include non-established WebSocket connections.
|
|
985
|
+
* @param urlPath - Optional URL path to filter connections.
|
|
947
986
|
* @returns An array of available WebSocket connections.
|
|
948
987
|
*/
|
|
949
|
-
getAvailableConnections(allowNonEstablishedWebsockets = false) {
|
|
950
|
-
if (this.mode === "single") return [this.connectionPool[0]];
|
|
988
|
+
getAvailableConnections(allowNonEstablishedWebsockets = false, urlPath) {
|
|
989
|
+
if (this.mode === "single" && !urlPath) return [this.connectionPool[0]];
|
|
951
990
|
return this.connectionPool.filter((connection) => this.isConnectionReady(connection, allowNonEstablishedWebsockets));
|
|
952
991
|
}
|
|
953
992
|
/**
|
|
@@ -956,10 +995,14 @@ var WebsocketCommon = class WebsocketCommon extends WebsocketEventEmitter {
|
|
|
956
995
|
* If the connection mode is 'pool', it returns an available connection from the pool,
|
|
957
996
|
* using a round-robin selection strategy. If no available connections are found, it throws an error.
|
|
958
997
|
* @param allowNonEstablishedWebsockets - A boolean indicating whether to allow connections that are not established.
|
|
998
|
+
* @param urlPath - An optional URL path to filter connections.
|
|
959
999
|
* @returns {WebsocketConnection} The selected WebSocket connection.
|
|
960
1000
|
*/
|
|
961
|
-
getConnection(allowNonEstablishedWebsockets = false) {
|
|
962
|
-
const availableConnections = this.getAvailableConnections(allowNonEstablishedWebsockets)
|
|
1001
|
+
getConnection(allowNonEstablishedWebsockets = false, urlPath) {
|
|
1002
|
+
const availableConnections = this.getAvailableConnections(allowNonEstablishedWebsockets, urlPath).filter((connection) => {
|
|
1003
|
+
if (urlPath) return connection.urlPath === urlPath;
|
|
1004
|
+
return true;
|
|
1005
|
+
});
|
|
963
1006
|
if (availableConnections.length === 0) throw new Error("No available Websocket connections are ready.");
|
|
964
1007
|
const selectedConnection = availableConnections[this.roundRobinIndex % availableConnections.length];
|
|
965
1008
|
this.roundRobinIndex = (this.roundRobinIndex + 1) % availableConnections.length;
|
|
@@ -1157,14 +1200,15 @@ var WebsocketCommon = class WebsocketCommon extends WebsocketEventEmitter {
|
|
|
1157
1200
|
/**
|
|
1158
1201
|
* Connects all WebSocket connections in the pool
|
|
1159
1202
|
* @param url - The Websocket server URL.
|
|
1203
|
+
* @param connections - An optional array of WebSocket connections to connect. If not provided, all connections in the pool are connected.
|
|
1160
1204
|
* @returns A promise that resolves when all connections are established.
|
|
1161
1205
|
*/
|
|
1162
|
-
async connectPool(url) {
|
|
1163
|
-
const connectPromises = this.connectionPool.map((connection) => new Promise((resolve, reject) => {
|
|
1206
|
+
async connectPool(url, connections) {
|
|
1207
|
+
const connectPromises = (connections ?? this.connectionPool).map((connection) => new Promise((resolve, reject) => {
|
|
1164
1208
|
this.initConnect(url, false, connection);
|
|
1165
|
-
connection.ws?.
|
|
1166
|
-
connection.ws?.
|
|
1167
|
-
connection.ws?.
|
|
1209
|
+
connection.ws?.once("open", () => resolve());
|
|
1210
|
+
connection.ws?.once("error", (err) => reject(err));
|
|
1211
|
+
connection.ws?.once("close", () => reject(/* @__PURE__ */ new Error("Connection closed unexpectedly.")));
|
|
1168
1212
|
}));
|
|
1169
1213
|
await Promise.all(connectPromises);
|
|
1170
1214
|
}
|
|
@@ -1443,21 +1487,50 @@ var WebsocketAPIBase = class extends WebsocketCommon {
|
|
|
1443
1487
|
}
|
|
1444
1488
|
};
|
|
1445
1489
|
var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
1446
|
-
constructor(configuration, connectionPool = []) {
|
|
1490
|
+
constructor(configuration, connectionPool = [], urlPaths = []) {
|
|
1447
1491
|
super(configuration, connectionPool);
|
|
1448
1492
|
this.streamConnectionMap = /* @__PURE__ */ new Map();
|
|
1493
|
+
this.streamIdIsStrictlyNumber = false;
|
|
1449
1494
|
this.streamCallbackMap = /* @__PURE__ */ new Map();
|
|
1450
1495
|
this.logger = Logger.getInstance();
|
|
1451
1496
|
this.configuration = configuration;
|
|
1452
1497
|
this.wsURL = configuration.wsURL;
|
|
1498
|
+
this.urlPaths = urlPaths;
|
|
1499
|
+
this.ensurePoolSizeForUrlPaths();
|
|
1500
|
+
}
|
|
1501
|
+
/**
|
|
1502
|
+
* Ensures the connection pool has the required size based on the configured mode and number of URL paths.
|
|
1503
|
+
*
|
|
1504
|
+
* If no URL paths are configured, the method returns early without modifications.
|
|
1505
|
+
* In 'pool' mode, the pool size is multiplied by the number of URL paths.
|
|
1506
|
+
* In 'single' mode, only one connection per URL path is maintained.
|
|
1507
|
+
*
|
|
1508
|
+
* New connections are initialized with unique IDs and default state flags when the pool
|
|
1509
|
+
* size is less than the expected size.
|
|
1510
|
+
*
|
|
1511
|
+
* @private
|
|
1512
|
+
* @returns {void}
|
|
1513
|
+
*/
|
|
1514
|
+
ensurePoolSizeForUrlPaths() {
|
|
1515
|
+
if (this.urlPaths.length === 0) return;
|
|
1516
|
+
const expected = ((this.configuration?.mode ?? "single") === "pool" && this.configuration?.poolSize ? this.configuration.poolSize : 1) * this.urlPaths.length;
|
|
1517
|
+
while (this.connectionPool.length < expected) this.connectionPool.push({
|
|
1518
|
+
id: randomString(),
|
|
1519
|
+
closeInitiated: false,
|
|
1520
|
+
reconnectionPending: false,
|
|
1521
|
+
renewalPending: false,
|
|
1522
|
+
pendingRequests: /* @__PURE__ */ new Map(),
|
|
1523
|
+
pendingSubscriptions: []
|
|
1524
|
+
});
|
|
1453
1525
|
}
|
|
1454
1526
|
/**
|
|
1455
1527
|
* Formats the WebSocket URL for a given stream or streams.
|
|
1456
1528
|
* @param streams - Array of stream names to include in the URL.
|
|
1529
|
+
* @param urlPath - Optional URL path to include in the WebSocket URL.
|
|
1457
1530
|
* @returns The formatted WebSocket URL with the provided streams.
|
|
1458
1531
|
*/
|
|
1459
|
-
prepareURL(streams = []) {
|
|
1460
|
-
let url = `${this.wsURL}/stream?streams=${streams.join("/")}`;
|
|
1532
|
+
prepareURL(streams = [], urlPath) {
|
|
1533
|
+
let url = `${urlPath ? `${this.wsURL}/${urlPath}` : this.wsURL}/stream?streams=${streams.join("/")}`;
|
|
1461
1534
|
if (this.configuration?.timeUnit) try {
|
|
1462
1535
|
const _timeUnit = validateTimeUnit(this.configuration.timeUnit);
|
|
1463
1536
|
url = `${url}${url.includes("?") ? "&" : "?"}timeUnit=${_timeUnit}`;
|
|
@@ -1473,22 +1546,24 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
|
1473
1546
|
* @returns The formatted WebSocket URL with streams and optional parameters.
|
|
1474
1547
|
*/
|
|
1475
1548
|
getReconnectURL(url, targetConnection) {
|
|
1476
|
-
const streams = Array.from(this.streamConnectionMap.keys()).filter((stream) => this.streamConnectionMap.get(stream) === targetConnection);
|
|
1477
|
-
return this.prepareURL(streams);
|
|
1549
|
+
const streams = Array.from(this.streamConnectionMap.keys()).filter((stream) => this.streamConnectionMap.get(stream) === targetConnection).map((key) => key.includes("::") ? key.split("::").slice(1).join("::") : key);
|
|
1550
|
+
return this.prepareURL(streams, targetConnection?.urlPath);
|
|
1478
1551
|
}
|
|
1479
1552
|
/**
|
|
1480
1553
|
* Handles subscription to streams and assigns them to specific connections
|
|
1481
1554
|
* @param streams Array of stream names to subscribe to
|
|
1555
|
+
* @param urlPath Optional URL path for the streams
|
|
1482
1556
|
* @returns Map of connections to streams
|
|
1483
1557
|
*/
|
|
1484
|
-
handleStreamAssignment(streams) {
|
|
1558
|
+
handleStreamAssignment(streams, urlPath) {
|
|
1485
1559
|
const connectionStreamMap = /* @__PURE__ */ new Map();
|
|
1486
1560
|
streams.forEach((stream) => {
|
|
1487
|
-
|
|
1488
|
-
|
|
1561
|
+
const key = this.streamKey(stream, urlPath);
|
|
1562
|
+
if (!this.streamCallbackMap.has(key)) this.streamCallbackMap.set(key, /* @__PURE__ */ new Set());
|
|
1563
|
+
let connection = this.streamConnectionMap.get(key);
|
|
1489
1564
|
if (!connection || connection.closeInitiated || connection.reconnectionPending) {
|
|
1490
|
-
connection = this.getConnection(true);
|
|
1491
|
-
this.streamConnectionMap.set(
|
|
1565
|
+
connection = this.getConnection(true, urlPath);
|
|
1566
|
+
this.streamConnectionMap.set(key, connection);
|
|
1492
1567
|
}
|
|
1493
1568
|
if (!connectionStreamMap.has(connection)) connectionStreamMap.set(connection, []);
|
|
1494
1569
|
connectionStreamMap.get(connection)?.push(stream);
|
|
@@ -1505,7 +1580,7 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
|
1505
1580
|
const payload = {
|
|
1506
1581
|
method: "SUBSCRIBE",
|
|
1507
1582
|
params: streams,
|
|
1508
|
-
id:
|
|
1583
|
+
id: normalizeStreamId(id, this.streamIdIsStrictlyNumber)
|
|
1509
1584
|
};
|
|
1510
1585
|
this.logger.debug("SUBSCRIBE", payload);
|
|
1511
1586
|
this.send(JSON.stringify(payload), void 0, false, 0, connection);
|
|
@@ -1534,7 +1609,10 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
|
1534
1609
|
try {
|
|
1535
1610
|
const parsedData = (0, json_with_bigint.JSONParse)(data);
|
|
1536
1611
|
const streamName = parsedData?.stream;
|
|
1537
|
-
if (streamName
|
|
1612
|
+
if (streamName) {
|
|
1613
|
+
const key = this.streamKey(streamName, connection?.urlPath);
|
|
1614
|
+
if (this.streamCallbackMap.has(key)) this.streamCallbackMap.get(key)?.forEach((callback) => callback(parsedData.data));
|
|
1615
|
+
}
|
|
1538
1616
|
} catch (error) {
|
|
1539
1617
|
this.logger.error("Failed to parse WebSocket message:", data, error);
|
|
1540
1618
|
}
|
|
@@ -1552,6 +1630,15 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
|
1552
1630
|
super.onOpen(url, targetConnection, oldWSConnection);
|
|
1553
1631
|
}
|
|
1554
1632
|
/**
|
|
1633
|
+
* Generates a stream key by combining a stream name with an optional URL path.
|
|
1634
|
+
* @param stream - The stream name to use as the key or suffix.
|
|
1635
|
+
* @param urlPath - Optional URL path to prepend to the stream name.
|
|
1636
|
+
* @returns A stream key in the format `urlPath::stream` if urlPath is provided, otherwise just the stream name.
|
|
1637
|
+
*/
|
|
1638
|
+
streamKey(stream, urlPath) {
|
|
1639
|
+
return urlPath ? `${urlPath}::${stream}` : stream;
|
|
1640
|
+
}
|
|
1641
|
+
/**
|
|
1555
1642
|
* Connects to the WebSocket server and subscribes to the specified streams.
|
|
1556
1643
|
* This method returns a Promise that resolves when the connection is established,
|
|
1557
1644
|
* or rejects with an error if the connection fails to be established within 10 seconds.
|
|
@@ -1564,7 +1651,15 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
|
1564
1651
|
const timeout = setTimeout(() => {
|
|
1565
1652
|
reject(/* @__PURE__ */ new Error("Websocket connection timed out"));
|
|
1566
1653
|
}, 1e4);
|
|
1567
|
-
|
|
1654
|
+
const basePoolSize = (this.configuration?.mode ?? "single") === "pool" && this.configuration?.poolSize ? this.configuration.poolSize : 1;
|
|
1655
|
+
const connections = this.urlPaths.length > 0 ? this.urlPaths.map((path, i) => {
|
|
1656
|
+
const start = i * basePoolSize;
|
|
1657
|
+
const end = start + basePoolSize;
|
|
1658
|
+
const subset = this.connectionPool.slice(start, end);
|
|
1659
|
+
subset.forEach((c) => c.urlPath = path);
|
|
1660
|
+
return this.connectPool(this.prepareURL(streams, path), subset);
|
|
1661
|
+
}) : [this.connectPool(this.prepareURL(streams))];
|
|
1662
|
+
Promise.all(connections).then(() => resolve()).catch((error) => reject(error)).finally(() => clearTimeout(timeout));
|
|
1568
1663
|
});
|
|
1569
1664
|
}
|
|
1570
1665
|
/**
|
|
@@ -1581,17 +1676,21 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
|
1581
1676
|
* Handles both single and pool modes
|
|
1582
1677
|
* @param stream Single stream name or array of stream names to subscribe to
|
|
1583
1678
|
* @param id Optional subscription ID
|
|
1679
|
+
* @param urlPath Optional URL path for the streams
|
|
1584
1680
|
* @returns void
|
|
1585
1681
|
*/
|
|
1586
|
-
subscribe(stream, id) {
|
|
1587
|
-
const streams = (Array.isArray(stream) ? stream : [stream]).filter((stream$1) =>
|
|
1588
|
-
|
|
1682
|
+
subscribe(stream, id, urlPath) {
|
|
1683
|
+
const streams = (Array.isArray(stream) ? stream : [stream]).filter((stream$1) => {
|
|
1684
|
+
const key = this.streamKey(stream$1, urlPath);
|
|
1685
|
+
return !this.streamConnectionMap.has(key);
|
|
1686
|
+
});
|
|
1687
|
+
this.handleStreamAssignment(streams, urlPath).forEach((assignedStreams, connection) => {
|
|
1589
1688
|
if (!this.isConnected(connection)) {
|
|
1590
|
-
this.logger.info(`Connection ${connection.id} is not ready. Queuing subscription for streams: ${
|
|
1591
|
-
connection.pendingSubscriptions?.push(...
|
|
1689
|
+
this.logger.info(`Connection ${connection.id} is not ready. Queuing subscription for streams: ${assignedStreams}`);
|
|
1690
|
+
connection.pendingSubscriptions?.push(...assignedStreams);
|
|
1592
1691
|
return;
|
|
1593
1692
|
}
|
|
1594
|
-
this.sendSubscriptionPayload(connection,
|
|
1693
|
+
this.sendSubscriptionPayload(connection, assignedStreams, id);
|
|
1595
1694
|
});
|
|
1596
1695
|
}
|
|
1597
1696
|
/**
|
|
@@ -1599,25 +1698,27 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
|
1599
1698
|
* Handles both single and pool modes
|
|
1600
1699
|
* @param stream Single stream name or array of stream names to unsubscribe from
|
|
1601
1700
|
* @param id Optional unsubscription ID
|
|
1701
|
+
* @param urlPath Optional URL path for the streams
|
|
1602
1702
|
* @returns void
|
|
1603
1703
|
*/
|
|
1604
|
-
unsubscribe(stream, id) {
|
|
1704
|
+
unsubscribe(stream, id, urlPath) {
|
|
1605
1705
|
(Array.isArray(stream) ? stream : [stream]).forEach((stream$1) => {
|
|
1606
|
-
const
|
|
1706
|
+
const key = this.streamKey(stream$1, urlPath);
|
|
1707
|
+
const connection = this.streamConnectionMap.get(key);
|
|
1607
1708
|
if (!connection || !connection.ws || !this.isConnected(connection)) {
|
|
1608
1709
|
this.logger.warn(`Stream ${stream$1} not associated with an active connection.`);
|
|
1609
1710
|
return;
|
|
1610
1711
|
}
|
|
1611
|
-
if (!this.streamCallbackMap.has(
|
|
1712
|
+
if (!this.streamCallbackMap.has(key) || this.streamCallbackMap.get(key)?.size === 0) {
|
|
1612
1713
|
const payload = {
|
|
1613
1714
|
method: "UNSUBSCRIBE",
|
|
1614
1715
|
params: [stream$1],
|
|
1615
|
-
id:
|
|
1716
|
+
id: normalizeStreamId(id, this.streamIdIsStrictlyNumber)
|
|
1616
1717
|
};
|
|
1617
1718
|
this.logger.debug("UNSUBSCRIBE", payload);
|
|
1618
1719
|
this.send(JSON.stringify(payload), void 0, false, 0, connection);
|
|
1619
|
-
this.streamConnectionMap.delete(
|
|
1620
|
-
this.streamCallbackMap.delete(
|
|
1720
|
+
this.streamConnectionMap.delete(key);
|
|
1721
|
+
this.streamCallbackMap.delete(key);
|
|
1621
1722
|
}
|
|
1622
1723
|
});
|
|
1623
1724
|
}
|
|
@@ -1627,7 +1728,9 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
|
1627
1728
|
* @returns `true` if the stream is currently subscribed, `false` otherwise.
|
|
1628
1729
|
*/
|
|
1629
1730
|
isSubscribed(stream) {
|
|
1630
|
-
|
|
1731
|
+
if (this.streamConnectionMap.has(stream)) return true;
|
|
1732
|
+
for (const key of this.streamConnectionMap.keys()) if (key.endsWith(`::${stream}`)) return true;
|
|
1733
|
+
return false;
|
|
1631
1734
|
}
|
|
1632
1735
|
};
|
|
1633
1736
|
/**
|
|
@@ -1637,10 +1740,12 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
|
1637
1740
|
* @param {WebsocketAPIBase | WebsocketStreamsBase} websocketBase The WebSocket base instance
|
|
1638
1741
|
* @param {string} streamOrId The stream identifier
|
|
1639
1742
|
* @param {string} [id] Optional additional identifier
|
|
1743
|
+
* @param {string} [urlPath] Optional URL path for the stream
|
|
1640
1744
|
* @returns {WebsocketStream<T>} A stream handler with methods to register callbacks and unsubscribe
|
|
1641
1745
|
*/
|
|
1642
|
-
function createStreamHandler(websocketBase, streamOrId, id) {
|
|
1643
|
-
|
|
1746
|
+
function createStreamHandler(websocketBase, streamOrId, id, urlPath) {
|
|
1747
|
+
const key = websocketBase instanceof WebsocketStreamsBase ? websocketBase.streamKey(streamOrId, urlPath) : streamOrId;
|
|
1748
|
+
if (websocketBase instanceof WebsocketStreamsBase) websocketBase.subscribe(streamOrId, id, urlPath);
|
|
1644
1749
|
let registeredCallback;
|
|
1645
1750
|
return {
|
|
1646
1751
|
on: (event, callback) => {
|
|
@@ -1650,14 +1755,14 @@ function createStreamHandler(websocketBase, streamOrId, id) {
|
|
|
1650
1755
|
websocketBase.logger.error(`Error in stream callback: ${err}`);
|
|
1651
1756
|
});
|
|
1652
1757
|
};
|
|
1653
|
-
const callbackSet = websocketBase.streamCallbackMap.get(
|
|
1758
|
+
const callbackSet = websocketBase.streamCallbackMap.get(key) ?? /* @__PURE__ */ new Set();
|
|
1654
1759
|
callbackSet.add(registeredCallback);
|
|
1655
|
-
websocketBase.streamCallbackMap.set(
|
|
1760
|
+
websocketBase.streamCallbackMap.set(key, callbackSet);
|
|
1656
1761
|
}
|
|
1657
1762
|
},
|
|
1658
1763
|
unsubscribe: () => {
|
|
1659
|
-
if (registeredCallback) websocketBase.streamCallbackMap.get(
|
|
1660
|
-
if (websocketBase instanceof WebsocketStreamsBase) websocketBase.unsubscribe(streamOrId, id);
|
|
1764
|
+
if (registeredCallback) websocketBase.streamCallbackMap.get(key)?.delete(registeredCallback);
|
|
1765
|
+
if (websocketBase instanceof WebsocketStreamsBase) websocketBase.unsubscribe(streamOrId, id, urlPath);
|
|
1661
1766
|
}
|
|
1662
1767
|
};
|
|
1663
1768
|
}
|
|
@@ -1680,7 +1785,9 @@ exports.DERIVATIVES_TRADING_COIN_FUTURES_WS_API_TESTNET_URL = DERIVATIVES_TRADIN
|
|
|
1680
1785
|
exports.DERIVATIVES_TRADING_COIN_FUTURES_WS_STREAMS_PROD_URL = DERIVATIVES_TRADING_COIN_FUTURES_WS_STREAMS_PROD_URL;
|
|
1681
1786
|
exports.DERIVATIVES_TRADING_COIN_FUTURES_WS_STREAMS_TESTNET_URL = DERIVATIVES_TRADING_COIN_FUTURES_WS_STREAMS_TESTNET_URL;
|
|
1682
1787
|
exports.DERIVATIVES_TRADING_OPTIONS_REST_API_PROD_URL = DERIVATIVES_TRADING_OPTIONS_REST_API_PROD_URL;
|
|
1788
|
+
exports.DERIVATIVES_TRADING_OPTIONS_REST_API_TESTNET_URL = DERIVATIVES_TRADING_OPTIONS_REST_API_TESTNET_URL;
|
|
1683
1789
|
exports.DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_PROD_URL = DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_PROD_URL;
|
|
1790
|
+
exports.DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_TESTNET_URL = DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_TESTNET_URL;
|
|
1684
1791
|
exports.DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_REST_API_PROD_URL = DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_REST_API_PROD_URL;
|
|
1685
1792
|
exports.DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_WS_STREAMS_PROD_URL = DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_WS_STREAMS_PROD_URL;
|
|
1686
1793
|
exports.DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_PROD_URL = DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_PROD_URL;
|
|
@@ -1742,8 +1849,10 @@ exports.getSignature = getSignature;
|
|
|
1742
1849
|
exports.getTimestamp = getTimestamp;
|
|
1743
1850
|
exports.httpRequestFunction = httpRequestFunction;
|
|
1744
1851
|
exports.normalizeScientificNumbers = normalizeScientificNumbers;
|
|
1852
|
+
exports.normalizeStreamId = normalizeStreamId;
|
|
1745
1853
|
exports.parseCustomHeaders = parseCustomHeaders;
|
|
1746
1854
|
exports.parseRateLimitHeaders = parseRateLimitHeaders;
|
|
1855
|
+
exports.randomInteger = randomInteger;
|
|
1747
1856
|
exports.randomString = randomString;
|
|
1748
1857
|
exports.removeEmptyValue = removeEmptyValue;
|
|
1749
1858
|
exports.replaceWebsocketStreamsPlaceholders = replaceWebsocketStreamsPlaceholders;
|