@binance/common 1.1.2 → 1.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/README.md +1 -0
- package/dist/index.d.mts +91 -22
- package/dist/index.d.ts +91 -22
- package/dist/index.js +520 -406
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +512 -406
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -38,7 +38,7 @@ __export(index_exports, {
|
|
|
38
38
|
COPY_TRADING_REST_API_PROD_URL: () => COPY_TRADING_REST_API_PROD_URL,
|
|
39
39
|
CRYPTO_LOAN_REST_API_PROD_URL: () => CRYPTO_LOAN_REST_API_PROD_URL,
|
|
40
40
|
ConfigurationRestAPI: () => ConfigurationRestAPI,
|
|
41
|
-
ConfigurationWebsocketAPI: () =>
|
|
41
|
+
ConfigurationWebsocketAPI: () => ConfigurationWebsocketAPI2,
|
|
42
42
|
ConfigurationWebsocketStreams: () => ConfigurationWebsocketStreams,
|
|
43
43
|
ConnectorClientError: () => ConnectorClientError,
|
|
44
44
|
DERIVATIVES_TRADING_COIN_FUTURES_REST_API_PROD_URL: () => DERIVATIVES_TRADING_COIN_FUTURES_REST_API_PROD_URL,
|
|
@@ -50,8 +50,11 @@ __export(index_exports, {
|
|
|
50
50
|
DERIVATIVES_TRADING_OPTIONS_REST_API_PROD_URL: () => DERIVATIVES_TRADING_OPTIONS_REST_API_PROD_URL,
|
|
51
51
|
DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_PROD_URL: () => DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_PROD_URL,
|
|
52
52
|
DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_REST_API_PROD_URL: () => DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_REST_API_PROD_URL,
|
|
53
|
+
DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_WS_STREAMS_PROD_URL: () => DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_WS_STREAMS_PROD_URL,
|
|
53
54
|
DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_PROD_URL: () => DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_PROD_URL,
|
|
54
55
|
DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_TESTNET_URL: () => DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_TESTNET_URL,
|
|
56
|
+
DERIVATIVES_TRADING_PORTFOLIO_MARGIN_WS_STREAMS_PROD_URL: () => DERIVATIVES_TRADING_PORTFOLIO_MARGIN_WS_STREAMS_PROD_URL,
|
|
57
|
+
DERIVATIVES_TRADING_PORTFOLIO_MARGIN_WS_STREAMS_TESTNET_URL: () => DERIVATIVES_TRADING_PORTFOLIO_MARGIN_WS_STREAMS_TESTNET_URL,
|
|
55
58
|
DERIVATIVES_TRADING_USDS_FUTURES_REST_API_PROD_URL: () => DERIVATIVES_TRADING_USDS_FUTURES_REST_API_PROD_URL,
|
|
56
59
|
DERIVATIVES_TRADING_USDS_FUTURES_REST_API_TESTNET_URL: () => DERIVATIVES_TRADING_USDS_FUTURES_REST_API_TESTNET_URL,
|
|
57
60
|
DERIVATIVES_TRADING_USDS_FUTURES_WS_API_PROD_URL: () => DERIVATIVES_TRADING_USDS_FUTURES_WS_API_PROD_URL,
|
|
@@ -65,6 +68,8 @@ __export(index_exports, {
|
|
|
65
68
|
LogLevel: () => LogLevel,
|
|
66
69
|
Logger: () => Logger,
|
|
67
70
|
MARGIN_TRADING_REST_API_PROD_URL: () => MARGIN_TRADING_REST_API_PROD_URL,
|
|
71
|
+
MARGIN_TRADING_RISK_WS_STREAMS_PROD_URL: () => MARGIN_TRADING_RISK_WS_STREAMS_PROD_URL,
|
|
72
|
+
MARGIN_TRADING_WS_STREAMS_PROD_URL: () => MARGIN_TRADING_WS_STREAMS_PROD_URL,
|
|
68
73
|
MINING_REST_API_PROD_URL: () => MINING_REST_API_PROD_URL,
|
|
69
74
|
NFT_REST_API_PROD_URL: () => NFT_REST_API_PROD_URL,
|
|
70
75
|
NetworkError: () => NetworkError,
|
|
@@ -97,16 +102,19 @@ __export(index_exports, {
|
|
|
97
102
|
assertParamExists: () => assertParamExists,
|
|
98
103
|
buildQueryString: () => buildQueryString,
|
|
99
104
|
buildUserAgent: () => buildUserAgent,
|
|
105
|
+
buildWebsocketAPIMessage: () => buildWebsocketAPIMessage,
|
|
100
106
|
clearSignerCache: () => clearSignerCache,
|
|
101
107
|
createStreamHandler: () => createStreamHandler,
|
|
102
108
|
delay: () => delay,
|
|
103
109
|
getSignature: () => getSignature,
|
|
104
110
|
getTimestamp: () => getTimestamp,
|
|
105
111
|
httpRequestFunction: () => httpRequestFunction,
|
|
112
|
+
parseCustomHeaders: () => parseCustomHeaders,
|
|
106
113
|
parseRateLimitHeaders: () => parseRateLimitHeaders,
|
|
107
114
|
randomString: () => randomString,
|
|
108
115
|
removeEmptyValue: () => removeEmptyValue,
|
|
109
116
|
replaceWebsocketStreamsPlaceholders: () => replaceWebsocketStreamsPlaceholders,
|
|
117
|
+
sanitizeHeaderValue: () => sanitizeHeaderValue,
|
|
110
118
|
sendRequest: () => sendRequest,
|
|
111
119
|
setFlattenedQueryParams: () => setFlattenedQueryParams,
|
|
112
120
|
setSearchParams: () => setSearchParams,
|
|
@@ -117,252 +125,6 @@ __export(index_exports, {
|
|
|
117
125
|
});
|
|
118
126
|
module.exports = __toCommonJS(index_exports);
|
|
119
127
|
|
|
120
|
-
// src/configuration.ts
|
|
121
|
-
var ConfigurationRestAPI = class {
|
|
122
|
-
constructor(param = { apiKey: "" }) {
|
|
123
|
-
this.apiKey = param.apiKey;
|
|
124
|
-
this.apiSecret = param.apiSecret;
|
|
125
|
-
this.basePath = param.basePath;
|
|
126
|
-
this.keepAlive = param.keepAlive ?? true;
|
|
127
|
-
this.compression = param.compression ?? true;
|
|
128
|
-
this.retries = param.retries ?? 3;
|
|
129
|
-
this.backoff = param.backoff ?? 1e3;
|
|
130
|
-
this.privateKey = param.privateKey;
|
|
131
|
-
this.privateKeyPassphrase = param.privateKeyPassphrase;
|
|
132
|
-
this.timeUnit = param.timeUnit;
|
|
133
|
-
this.baseOptions = {
|
|
134
|
-
timeout: param.timeout ?? 1e3,
|
|
135
|
-
proxy: param.proxy && {
|
|
136
|
-
host: param.proxy.host,
|
|
137
|
-
port: param.proxy.port,
|
|
138
|
-
auth: param.proxy.auth
|
|
139
|
-
},
|
|
140
|
-
httpsAgent: param.httpsAgent ?? false,
|
|
141
|
-
headers: {
|
|
142
|
-
"Content-Type": "application/json",
|
|
143
|
-
"X-MBX-APIKEY": param.apiKey
|
|
144
|
-
}
|
|
145
|
-
};
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
|
-
var ConfigurationWebsocketAPI = class {
|
|
149
|
-
constructor(param = { apiKey: "" }) {
|
|
150
|
-
this.apiKey = param.apiKey;
|
|
151
|
-
this.apiSecret = param.apiSecret;
|
|
152
|
-
this.wsURL = param.wsURL;
|
|
153
|
-
this.timeout = param.timeout ?? 5e3;
|
|
154
|
-
this.reconnectDelay = param.reconnectDelay ?? 5e3;
|
|
155
|
-
this.compression = param.compression ?? true;
|
|
156
|
-
this.agent = param.agent ?? false;
|
|
157
|
-
this.mode = param.mode ?? "single";
|
|
158
|
-
this.poolSize = param.poolSize ?? 1;
|
|
159
|
-
this.privateKey = param.privateKey;
|
|
160
|
-
this.privateKeyPassphrase = param.privateKeyPassphrase;
|
|
161
|
-
this.timeUnit = param.timeUnit;
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
var ConfigurationWebsocketStreams = class {
|
|
165
|
-
constructor(param = {}) {
|
|
166
|
-
this.wsURL = param.wsURL;
|
|
167
|
-
this.reconnectDelay = param.reconnectDelay ?? 5e3;
|
|
168
|
-
this.compression = param.compression ?? true;
|
|
169
|
-
this.agent = param.agent ?? false;
|
|
170
|
-
this.mode = param.mode ?? "single";
|
|
171
|
-
this.poolSize = param.poolSize ?? 1;
|
|
172
|
-
this.timeUnit = param.timeUnit;
|
|
173
|
-
}
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
// src/constants.ts
|
|
177
|
-
var TimeUnit = {
|
|
178
|
-
MILLISECOND: "MILLISECOND",
|
|
179
|
-
millisecond: "millisecond",
|
|
180
|
-
MICROSECOND: "MICROSECOND",
|
|
181
|
-
microsecond: "microsecond"
|
|
182
|
-
};
|
|
183
|
-
var ALGO_REST_API_PROD_URL = "https://api.binance.com";
|
|
184
|
-
var AUTO_INVEST_REST_API_PROD_URL = "https://api.binance.com";
|
|
185
|
-
var C2C_REST_API_PROD_URL = "https://api.binance.com";
|
|
186
|
-
var CONVERT_REST_API_PROD_URL = "https://api.binance.com";
|
|
187
|
-
var COPY_TRADING_REST_API_PROD_URL = "https://api.binance.com";
|
|
188
|
-
var CRYPTO_LOAN_REST_API_PROD_URL = "https://api.binance.com";
|
|
189
|
-
var DERIVATIVES_TRADING_COIN_FUTURES_REST_API_PROD_URL = "https://dapi.binance.com";
|
|
190
|
-
var DERIVATIVES_TRADING_COIN_FUTURES_REST_API_TESTNET_URL = "https://testnet.binancefuture.com";
|
|
191
|
-
var DERIVATIVES_TRADING_COIN_FUTURES_WS_API_PROD_URL = "wss://ws-dapi.binance.com/ws-dapi/v1";
|
|
192
|
-
var DERIVATIVES_TRADING_COIN_FUTURES_WS_API_TESTNET_URL = "wss://testnet.binancefuture.com/ws-dapi/v1";
|
|
193
|
-
var DERIVATIVES_TRADING_COIN_FUTURES_WS_STREAMS_PROD_URL = "wss://dstream.binance.com";
|
|
194
|
-
var DERIVATIVES_TRADING_COIN_FUTURES_WS_STREAMS_TESTNET_URL = "wss://dstream.binancefuture.com";
|
|
195
|
-
var DERIVATIVES_TRADING_USDS_FUTURES_REST_API_PROD_URL = "https://fapi.binance.com";
|
|
196
|
-
var DERIVATIVES_TRADING_USDS_FUTURES_REST_API_TESTNET_URL = "https://testnet.binancefuture.com";
|
|
197
|
-
var DERIVATIVES_TRADING_USDS_FUTURES_WS_API_PROD_URL = "wss://ws-fapi.binance.com/ws-fapi/v1";
|
|
198
|
-
var DERIVATIVES_TRADING_USDS_FUTURES_WS_API_TESTNET_URL = "wss://testnet.binancefuture.com/ws-fapi/v1";
|
|
199
|
-
var DERIVATIVES_TRADING_USDS_FUTURES_WS_STREAMS_PROD_URL = "wss://fstream.binance.com";
|
|
200
|
-
var DERIVATIVES_TRADING_USDS_FUTURES_WS_STREAMS_TESTNET_URL = "wss://stream.binancefuture.com";
|
|
201
|
-
var DERIVATIVES_TRADING_OPTIONS_REST_API_PROD_URL = "https://eapi.binance.com";
|
|
202
|
-
var DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_PROD_URL = "wss://nbstream.binance.com/eoptions";
|
|
203
|
-
var DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_PROD_URL = "https://papi.binance.com";
|
|
204
|
-
var DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_TESTNET_URL = "https://testnet.binancefuture.com";
|
|
205
|
-
var DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_REST_API_PROD_URL = "https://api.binance.com";
|
|
206
|
-
var DUAL_INVESTMENT_REST_API_PROD_URL = "https://api.binance.com";
|
|
207
|
-
var FIAT_REST_API_PROD_URL = "https://api.binance.com";
|
|
208
|
-
var GIFT_CARD_REST_API_PROD_URL = "https://api.binance.com";
|
|
209
|
-
var MARGIN_TRADING_REST_API_PROD_URL = "https://api.binance.com";
|
|
210
|
-
var MINING_REST_API_PROD_URL = "https://api.binance.com";
|
|
211
|
-
var NFT_REST_API_PROD_URL = "https://api.binance.com";
|
|
212
|
-
var PAY_REST_API_PROD_URL = "https://api.binance.com";
|
|
213
|
-
var REBATE_REST_API_PROD_URL = "https://api.binance.com";
|
|
214
|
-
var SIMPLE_EARN_REST_API_PROD_URL = "https://api.binance.com";
|
|
215
|
-
var SPOT_REST_API_PROD_URL = "https://api.binance.com";
|
|
216
|
-
var SPOT_REST_API_TESTNET_URL = "https://testnet.binance.vision";
|
|
217
|
-
var SPOT_WS_API_PROD_URL = "wss://ws-api.binance.com:443/ws-api/v3";
|
|
218
|
-
var SPOT_WS_API_TESTNET_URL = "wss://ws-api.testnet.binance.vision/ws-api/v3";
|
|
219
|
-
var SPOT_WS_STREAMS_PROD_URL = "wss://stream.binance.com:9443";
|
|
220
|
-
var SPOT_WS_STREAMS_TESTNET_URL = "wss://stream.testnet.binance.vision";
|
|
221
|
-
var SPOT_REST_API_MARKET_URL = "https://data-api.binance.vision";
|
|
222
|
-
var SPOT_WS_STREAMS_MARKET_URL = "wss://data-stream.binance.vision";
|
|
223
|
-
var STAKING_REST_API_PROD_URL = "https://api.binance.com";
|
|
224
|
-
var SUB_ACCOUNT_REST_API_PROD_URL = "https://api.binance.com";
|
|
225
|
-
var VIP_LOAN_REST_API_PROD_URL = "https://api.binance.com";
|
|
226
|
-
var WALLET_REST_API_PROD_URL = "https://api.binance.com";
|
|
227
|
-
|
|
228
|
-
// src/errors.ts
|
|
229
|
-
var ConnectorClientError = class _ConnectorClientError extends Error {
|
|
230
|
-
constructor(msg) {
|
|
231
|
-
super(msg || "An unexpected error occurred.");
|
|
232
|
-
Object.setPrototypeOf(this, _ConnectorClientError.prototype);
|
|
233
|
-
this.name = "ConnectorClientError";
|
|
234
|
-
}
|
|
235
|
-
};
|
|
236
|
-
var RequiredError = class _RequiredError extends Error {
|
|
237
|
-
constructor(field, msg) {
|
|
238
|
-
super(msg || `Required parameter ${field} was null or undefined.`);
|
|
239
|
-
this.field = field;
|
|
240
|
-
Object.setPrototypeOf(this, _RequiredError.prototype);
|
|
241
|
-
this.name = "RequiredError";
|
|
242
|
-
}
|
|
243
|
-
};
|
|
244
|
-
var UnauthorizedError = class _UnauthorizedError extends Error {
|
|
245
|
-
constructor(msg) {
|
|
246
|
-
super(msg || "Unauthorized access. Authentication required.");
|
|
247
|
-
Object.setPrototypeOf(this, _UnauthorizedError.prototype);
|
|
248
|
-
this.name = "UnauthorizedError";
|
|
249
|
-
}
|
|
250
|
-
};
|
|
251
|
-
var ForbiddenError = class _ForbiddenError extends Error {
|
|
252
|
-
constructor(msg) {
|
|
253
|
-
super(msg || "Access to the requested resource is forbidden.");
|
|
254
|
-
Object.setPrototypeOf(this, _ForbiddenError.prototype);
|
|
255
|
-
this.name = "ForbiddenError";
|
|
256
|
-
}
|
|
257
|
-
};
|
|
258
|
-
var TooManyRequestsError = class _TooManyRequestsError extends Error {
|
|
259
|
-
constructor(msg) {
|
|
260
|
-
super(msg || "Too many requests. You are being rate-limited.");
|
|
261
|
-
Object.setPrototypeOf(this, _TooManyRequestsError.prototype);
|
|
262
|
-
this.name = "TooManyRequestsError";
|
|
263
|
-
}
|
|
264
|
-
};
|
|
265
|
-
var RateLimitBanError = class _RateLimitBanError extends Error {
|
|
266
|
-
constructor(msg) {
|
|
267
|
-
super(msg || "The IP address has been banned for exceeding rate limits.");
|
|
268
|
-
Object.setPrototypeOf(this, _RateLimitBanError.prototype);
|
|
269
|
-
this.name = "RateLimitBanError";
|
|
270
|
-
}
|
|
271
|
-
};
|
|
272
|
-
var ServerError = class _ServerError extends Error {
|
|
273
|
-
constructor(msg, statusCode) {
|
|
274
|
-
super(msg || "An internal server error occurred.");
|
|
275
|
-
this.statusCode = statusCode;
|
|
276
|
-
Object.setPrototypeOf(this, _ServerError.prototype);
|
|
277
|
-
this.name = "ServerError";
|
|
278
|
-
}
|
|
279
|
-
};
|
|
280
|
-
var NetworkError = class _NetworkError extends Error {
|
|
281
|
-
constructor(msg) {
|
|
282
|
-
super(msg || "A network error occurred.");
|
|
283
|
-
Object.setPrototypeOf(this, _NetworkError.prototype);
|
|
284
|
-
this.name = "NetworkError";
|
|
285
|
-
}
|
|
286
|
-
};
|
|
287
|
-
var NotFoundError = class _NotFoundError extends Error {
|
|
288
|
-
constructor(msg) {
|
|
289
|
-
super(msg || "The requested resource was not found.");
|
|
290
|
-
Object.setPrototypeOf(this, _NotFoundError.prototype);
|
|
291
|
-
this.name = "NotFoundError";
|
|
292
|
-
}
|
|
293
|
-
};
|
|
294
|
-
var BadRequestError = class _BadRequestError extends Error {
|
|
295
|
-
constructor(msg) {
|
|
296
|
-
super(msg || "The request was invalid or cannot be otherwise served.");
|
|
297
|
-
Object.setPrototypeOf(this, _BadRequestError.prototype);
|
|
298
|
-
this.name = "BadRequestError";
|
|
299
|
-
}
|
|
300
|
-
};
|
|
301
|
-
|
|
302
|
-
// src/logger.ts
|
|
303
|
-
var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
304
|
-
LogLevel2["NONE"] = "";
|
|
305
|
-
LogLevel2["DEBUG"] = "debug";
|
|
306
|
-
LogLevel2["INFO"] = "info";
|
|
307
|
-
LogLevel2["WARN"] = "warn";
|
|
308
|
-
LogLevel2["ERROR"] = "error";
|
|
309
|
-
return LogLevel2;
|
|
310
|
-
})(LogLevel || {});
|
|
311
|
-
var Logger = class _Logger {
|
|
312
|
-
constructor() {
|
|
313
|
-
this.minLogLevel = "info" /* INFO */;
|
|
314
|
-
this.levelsOrder = [
|
|
315
|
-
"" /* NONE */,
|
|
316
|
-
"debug" /* DEBUG */,
|
|
317
|
-
"info" /* INFO */,
|
|
318
|
-
"warn" /* WARN */,
|
|
319
|
-
"error" /* ERROR */
|
|
320
|
-
];
|
|
321
|
-
}
|
|
322
|
-
static getInstance() {
|
|
323
|
-
if (!_Logger.instance) {
|
|
324
|
-
_Logger.instance = new _Logger();
|
|
325
|
-
}
|
|
326
|
-
return _Logger.instance;
|
|
327
|
-
}
|
|
328
|
-
setMinLogLevel(level) {
|
|
329
|
-
if (!this.isValidLogLevel(level)) {
|
|
330
|
-
throw new Error(`Invalid log level: ${level}`);
|
|
331
|
-
}
|
|
332
|
-
this.minLogLevel = level;
|
|
333
|
-
}
|
|
334
|
-
isValidLogLevel(level) {
|
|
335
|
-
return this.levelsOrder.includes(level);
|
|
336
|
-
}
|
|
337
|
-
log(level, ...message) {
|
|
338
|
-
if (level === "" /* NONE */ || !this.allowLevelLog(level)) {
|
|
339
|
-
return;
|
|
340
|
-
}
|
|
341
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
342
|
-
console[level](`[${timestamp}] [${level.toLowerCase()}]`, ...message);
|
|
343
|
-
}
|
|
344
|
-
allowLevelLog(level) {
|
|
345
|
-
if (!this.isValidLogLevel(level)) {
|
|
346
|
-
throw new Error(`Invalid log level: ${level}`);
|
|
347
|
-
}
|
|
348
|
-
const currentLevelIndex = this.levelsOrder.indexOf(level);
|
|
349
|
-
const minLevelIndex = this.levelsOrder.indexOf(this.minLogLevel);
|
|
350
|
-
return currentLevelIndex >= minLevelIndex;
|
|
351
|
-
}
|
|
352
|
-
debug(...message) {
|
|
353
|
-
this.log("debug" /* DEBUG */, ...message);
|
|
354
|
-
}
|
|
355
|
-
info(...message) {
|
|
356
|
-
this.log("info" /* INFO */, ...message);
|
|
357
|
-
}
|
|
358
|
-
warn(...message) {
|
|
359
|
-
this.log("warn" /* WARN */, ...message);
|
|
360
|
-
}
|
|
361
|
-
error(...message) {
|
|
362
|
-
this.log("error" /* ERROR */, ...message);
|
|
363
|
-
}
|
|
364
|
-
};
|
|
365
|
-
|
|
366
128
|
// src/utils.ts
|
|
367
129
|
var import_crypto = __toESM(require("crypto"));
|
|
368
130
|
var import_fs = __toESM(require("fs"));
|
|
@@ -581,141 +343,431 @@ var httpRequestFunction = async function(axiosArgs, configuration) {
|
|
|
581
343
|
}
|
|
582
344
|
}
|
|
583
345
|
}
|
|
584
|
-
throw lastError;
|
|
346
|
+
throw lastError;
|
|
347
|
+
};
|
|
348
|
+
var parseRateLimitHeaders = function(headers) {
|
|
349
|
+
const rateLimits = [];
|
|
350
|
+
const parseIntervalDetails = (key) => {
|
|
351
|
+
const match = key.match(/x-mbx-used-weight-(\d+)([smhd])|x-mbx-order-count-(\d+)([smhd])/i);
|
|
352
|
+
if (!match) return null;
|
|
353
|
+
const intervalNum = parseInt(match[1] || match[3], 10);
|
|
354
|
+
const intervalLetter = (match[2] || match[4])?.toUpperCase();
|
|
355
|
+
let interval;
|
|
356
|
+
switch (intervalLetter) {
|
|
357
|
+
case "S":
|
|
358
|
+
interval = "SECOND";
|
|
359
|
+
break;
|
|
360
|
+
case "M":
|
|
361
|
+
interval = "MINUTE";
|
|
362
|
+
break;
|
|
363
|
+
case "H":
|
|
364
|
+
interval = "HOUR";
|
|
365
|
+
break;
|
|
366
|
+
case "D":
|
|
367
|
+
interval = "DAY";
|
|
368
|
+
break;
|
|
369
|
+
default:
|
|
370
|
+
return null;
|
|
371
|
+
}
|
|
372
|
+
return { interval, intervalNum };
|
|
373
|
+
};
|
|
374
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
375
|
+
const normalizedKey = key.toLowerCase();
|
|
376
|
+
if (value === void 0) continue;
|
|
377
|
+
if (normalizedKey.startsWith("x-mbx-used-weight-")) {
|
|
378
|
+
const details = parseIntervalDetails(normalizedKey);
|
|
379
|
+
if (details) {
|
|
380
|
+
rateLimits.push({
|
|
381
|
+
rateLimitType: "REQUEST_WEIGHT",
|
|
382
|
+
interval: details.interval,
|
|
383
|
+
intervalNum: details.intervalNum,
|
|
384
|
+
count: parseInt(value, 10)
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
} else if (normalizedKey.startsWith("x-mbx-order-count-")) {
|
|
388
|
+
const details = parseIntervalDetails(normalizedKey);
|
|
389
|
+
if (details) {
|
|
390
|
+
rateLimits.push({
|
|
391
|
+
rateLimitType: "ORDERS",
|
|
392
|
+
interval: details.interval,
|
|
393
|
+
intervalNum: details.intervalNum,
|
|
394
|
+
count: parseInt(value, 10)
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
if (headers["retry-after"]) {
|
|
400
|
+
const retryAfter = parseInt(headers["retry-after"], 10);
|
|
401
|
+
for (const limit of rateLimits) {
|
|
402
|
+
limit.retryAfter = retryAfter;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
return rateLimits;
|
|
406
|
+
};
|
|
407
|
+
var sendRequest = function(configuration, endpoint, method, params = {}, timeUnit, options = {}) {
|
|
408
|
+
const localVarUrlObj = new URL(endpoint, configuration?.basePath);
|
|
409
|
+
const localVarRequestOptions = {
|
|
410
|
+
method,
|
|
411
|
+
...configuration?.baseOptions
|
|
412
|
+
};
|
|
413
|
+
const localVarQueryParameter = { ...params };
|
|
414
|
+
if (options.isSigned) {
|
|
415
|
+
const timestamp = getTimestamp();
|
|
416
|
+
localVarQueryParameter["timestamp"] = timestamp;
|
|
417
|
+
const signature = getSignature(configuration, localVarQueryParameter);
|
|
418
|
+
if (signature) {
|
|
419
|
+
localVarQueryParameter["signature"] = signature;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
|
423
|
+
if (timeUnit && localVarRequestOptions.headers) {
|
|
424
|
+
const _timeUnit = validateTimeUnit(timeUnit);
|
|
425
|
+
localVarRequestOptions.headers = {
|
|
426
|
+
...localVarRequestOptions.headers,
|
|
427
|
+
"X-MBX-TIME-UNIT": _timeUnit
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
return httpRequestFunction(
|
|
431
|
+
{
|
|
432
|
+
url: toPathString(localVarUrlObj),
|
|
433
|
+
options: localVarRequestOptions
|
|
434
|
+
},
|
|
435
|
+
configuration
|
|
436
|
+
);
|
|
437
|
+
};
|
|
438
|
+
function removeEmptyValue(obj) {
|
|
439
|
+
if (!(obj instanceof Object)) return {};
|
|
440
|
+
return Object.fromEntries(
|
|
441
|
+
Object.entries(obj).filter(
|
|
442
|
+
([, value]) => value !== null && value !== void 0 && value !== ""
|
|
443
|
+
)
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
function sortObject(obj) {
|
|
447
|
+
return Object.keys(obj).sort().reduce((res, key) => {
|
|
448
|
+
res[key] = obj[key];
|
|
449
|
+
return res;
|
|
450
|
+
}, {});
|
|
451
|
+
}
|
|
452
|
+
function replaceWebsocketStreamsPlaceholders(str, variables) {
|
|
453
|
+
const normalizedVariables = Object.keys(variables).reduce(
|
|
454
|
+
(acc, key) => {
|
|
455
|
+
const normalizedKey = key.toLowerCase().replace(/[-_]/g, "");
|
|
456
|
+
acc[normalizedKey] = variables[key];
|
|
457
|
+
return acc;
|
|
458
|
+
},
|
|
459
|
+
{}
|
|
460
|
+
);
|
|
461
|
+
return str.replace(/(@)?<([^>]+)>/g, (match, precedingAt, fieldName) => {
|
|
462
|
+
const normalizedFieldName = fieldName.toLowerCase().replace(/[-_]/g, "");
|
|
463
|
+
if (Object.prototype.hasOwnProperty.call(normalizedVariables, normalizedFieldName) && normalizedVariables[normalizedFieldName] != null) {
|
|
464
|
+
const value = normalizedVariables[normalizedFieldName];
|
|
465
|
+
switch (normalizedFieldName) {
|
|
466
|
+
case "symbol":
|
|
467
|
+
case "windowsize":
|
|
468
|
+
return value.toLowerCase();
|
|
469
|
+
case "updatespeed":
|
|
470
|
+
return `@${value}`;
|
|
471
|
+
default:
|
|
472
|
+
return (precedingAt || "") + value;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
return "";
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
function buildUserAgent(packageName, packageVersion) {
|
|
479
|
+
return `${packageName}/${packageVersion} (Node.js/${process.version}; ${(0, import_os.platform)()}; ${(0, import_os.arch)()})`;
|
|
480
|
+
}
|
|
481
|
+
function buildWebsocketAPIMessage(configuration, method, payload, options, skipAuth = false) {
|
|
482
|
+
const id = payload.id && /^[0-9a-f]{32}$/.test(payload.id) ? payload.id : randomString();
|
|
483
|
+
delete payload.id;
|
|
484
|
+
let params = removeEmptyValue(payload);
|
|
485
|
+
if ((options.withApiKey || options.isSigned) && !skipAuth) params.apiKey = configuration.apiKey;
|
|
486
|
+
if (options.isSigned) {
|
|
487
|
+
params.timestamp = getTimestamp();
|
|
488
|
+
params = sortObject(params);
|
|
489
|
+
if (!skipAuth) params.signature = getSignature(configuration, params);
|
|
490
|
+
}
|
|
491
|
+
return { id, method, params };
|
|
492
|
+
}
|
|
493
|
+
function sanitizeHeaderValue(value) {
|
|
494
|
+
const sanitizeOne = (v) => {
|
|
495
|
+
if (/\r|\n/.test(v)) throw new Error(`Invalid header value (contains CR/LF): "${v}"`);
|
|
496
|
+
return v;
|
|
497
|
+
};
|
|
498
|
+
return Array.isArray(value) ? value.map(sanitizeOne) : sanitizeOne(value);
|
|
499
|
+
}
|
|
500
|
+
function parseCustomHeaders(headers) {
|
|
501
|
+
if (!headers || Object.keys(headers).length === 0) return {};
|
|
502
|
+
const forbidden = /* @__PURE__ */ new Set(["host", "authorization", "cookie", ":method", ":path"]);
|
|
503
|
+
const parsedHeaders = {};
|
|
504
|
+
for (const [rawName, rawValue] of Object.entries(headers || {})) {
|
|
505
|
+
const name = rawName.trim();
|
|
506
|
+
if (forbidden.has(name.toLowerCase())) {
|
|
507
|
+
console.warn(`Dropping forbidden header: ${name}`);
|
|
508
|
+
continue;
|
|
509
|
+
}
|
|
510
|
+
try {
|
|
511
|
+
parsedHeaders[name] = sanitizeHeaderValue(rawValue);
|
|
512
|
+
} catch {
|
|
513
|
+
continue;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
return parsedHeaders;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// src/configuration.ts
|
|
520
|
+
var ConfigurationRestAPI = class {
|
|
521
|
+
constructor(param = { apiKey: "" }) {
|
|
522
|
+
this.apiKey = param.apiKey;
|
|
523
|
+
this.apiSecret = param.apiSecret;
|
|
524
|
+
this.basePath = param.basePath;
|
|
525
|
+
this.keepAlive = param.keepAlive ?? true;
|
|
526
|
+
this.compression = param.compression ?? true;
|
|
527
|
+
this.retries = param.retries ?? 3;
|
|
528
|
+
this.backoff = param.backoff ?? 1e3;
|
|
529
|
+
this.privateKey = param.privateKey;
|
|
530
|
+
this.privateKeyPassphrase = param.privateKeyPassphrase;
|
|
531
|
+
this.timeUnit = param.timeUnit;
|
|
532
|
+
this.baseOptions = {
|
|
533
|
+
timeout: param.timeout ?? 1e3,
|
|
534
|
+
proxy: param.proxy && {
|
|
535
|
+
host: param.proxy.host,
|
|
536
|
+
port: param.proxy.port,
|
|
537
|
+
auth: param.proxy.auth
|
|
538
|
+
},
|
|
539
|
+
httpsAgent: param.httpsAgent ?? false,
|
|
540
|
+
headers: {
|
|
541
|
+
...parseCustomHeaders(param.customHeaders || {}),
|
|
542
|
+
"Content-Type": "application/json",
|
|
543
|
+
"X-MBX-APIKEY": param.apiKey
|
|
544
|
+
}
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
};
|
|
548
|
+
var ConfigurationWebsocketAPI2 = class {
|
|
549
|
+
constructor(param = { apiKey: "" }) {
|
|
550
|
+
this.apiKey = param.apiKey;
|
|
551
|
+
this.apiSecret = param.apiSecret;
|
|
552
|
+
this.wsURL = param.wsURL;
|
|
553
|
+
this.timeout = param.timeout ?? 5e3;
|
|
554
|
+
this.reconnectDelay = param.reconnectDelay ?? 5e3;
|
|
555
|
+
this.compression = param.compression ?? true;
|
|
556
|
+
this.agent = param.agent ?? false;
|
|
557
|
+
this.mode = param.mode ?? "single";
|
|
558
|
+
this.poolSize = param.poolSize ?? 1;
|
|
559
|
+
this.privateKey = param.privateKey;
|
|
560
|
+
this.privateKeyPassphrase = param.privateKeyPassphrase;
|
|
561
|
+
this.timeUnit = param.timeUnit;
|
|
562
|
+
this.autoSessionReLogon = param.autoSessionReLogon ?? true;
|
|
563
|
+
}
|
|
564
|
+
};
|
|
565
|
+
var ConfigurationWebsocketStreams = class {
|
|
566
|
+
constructor(param = {}) {
|
|
567
|
+
this.wsURL = param.wsURL;
|
|
568
|
+
this.reconnectDelay = param.reconnectDelay ?? 5e3;
|
|
569
|
+
this.compression = param.compression ?? true;
|
|
570
|
+
this.agent = param.agent ?? false;
|
|
571
|
+
this.mode = param.mode ?? "single";
|
|
572
|
+
this.poolSize = param.poolSize ?? 1;
|
|
573
|
+
this.timeUnit = param.timeUnit;
|
|
574
|
+
}
|
|
575
|
+
};
|
|
576
|
+
|
|
577
|
+
// src/constants.ts
|
|
578
|
+
var TimeUnit = {
|
|
579
|
+
MILLISECOND: "MILLISECOND",
|
|
580
|
+
millisecond: "millisecond",
|
|
581
|
+
MICROSECOND: "MICROSECOND",
|
|
582
|
+
microsecond: "microsecond"
|
|
583
|
+
};
|
|
584
|
+
var ALGO_REST_API_PROD_URL = "https://api.binance.com";
|
|
585
|
+
var AUTO_INVEST_REST_API_PROD_URL = "https://api.binance.com";
|
|
586
|
+
var C2C_REST_API_PROD_URL = "https://api.binance.com";
|
|
587
|
+
var CONVERT_REST_API_PROD_URL = "https://api.binance.com";
|
|
588
|
+
var COPY_TRADING_REST_API_PROD_URL = "https://api.binance.com";
|
|
589
|
+
var CRYPTO_LOAN_REST_API_PROD_URL = "https://api.binance.com";
|
|
590
|
+
var DERIVATIVES_TRADING_COIN_FUTURES_REST_API_PROD_URL = "https://dapi.binance.com";
|
|
591
|
+
var DERIVATIVES_TRADING_COIN_FUTURES_REST_API_TESTNET_URL = "https://testnet.binancefuture.com";
|
|
592
|
+
var DERIVATIVES_TRADING_COIN_FUTURES_WS_API_PROD_URL = "wss://ws-dapi.binance.com/ws-dapi/v1";
|
|
593
|
+
var DERIVATIVES_TRADING_COIN_FUTURES_WS_API_TESTNET_URL = "wss://testnet.binancefuture.com/ws-dapi/v1";
|
|
594
|
+
var DERIVATIVES_TRADING_COIN_FUTURES_WS_STREAMS_PROD_URL = "wss://dstream.binance.com";
|
|
595
|
+
var DERIVATIVES_TRADING_COIN_FUTURES_WS_STREAMS_TESTNET_URL = "wss://dstream.binancefuture.com";
|
|
596
|
+
var DERIVATIVES_TRADING_USDS_FUTURES_REST_API_PROD_URL = "https://fapi.binance.com";
|
|
597
|
+
var DERIVATIVES_TRADING_USDS_FUTURES_REST_API_TESTNET_URL = "https://testnet.binancefuture.com";
|
|
598
|
+
var DERIVATIVES_TRADING_USDS_FUTURES_WS_API_PROD_URL = "wss://ws-fapi.binance.com/ws-fapi/v1";
|
|
599
|
+
var DERIVATIVES_TRADING_USDS_FUTURES_WS_API_TESTNET_URL = "wss://testnet.binancefuture.com/ws-fapi/v1";
|
|
600
|
+
var DERIVATIVES_TRADING_USDS_FUTURES_WS_STREAMS_PROD_URL = "wss://fstream.binance.com";
|
|
601
|
+
var DERIVATIVES_TRADING_USDS_FUTURES_WS_STREAMS_TESTNET_URL = "wss://stream.binancefuture.com";
|
|
602
|
+
var DERIVATIVES_TRADING_OPTIONS_REST_API_PROD_URL = "https://eapi.binance.com";
|
|
603
|
+
var DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_PROD_URL = "wss://nbstream.binance.com/eoptions";
|
|
604
|
+
var DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_PROD_URL = "https://papi.binance.com";
|
|
605
|
+
var DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_TESTNET_URL = "https://testnet.binancefuture.com";
|
|
606
|
+
var DERIVATIVES_TRADING_PORTFOLIO_MARGIN_WS_STREAMS_PROD_URL = "wss://fstream.binance.com/pm";
|
|
607
|
+
var DERIVATIVES_TRADING_PORTFOLIO_MARGIN_WS_STREAMS_TESTNET_URL = "wss://fstream.binancefuture.com/pm";
|
|
608
|
+
var DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_REST_API_PROD_URL = "https://api.binance.com";
|
|
609
|
+
var DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_WS_STREAMS_PROD_URL = "wss://fstream.binance.com/pm-classic";
|
|
610
|
+
var DUAL_INVESTMENT_REST_API_PROD_URL = "https://api.binance.com";
|
|
611
|
+
var FIAT_REST_API_PROD_URL = "https://api.binance.com";
|
|
612
|
+
var GIFT_CARD_REST_API_PROD_URL = "https://api.binance.com";
|
|
613
|
+
var MARGIN_TRADING_REST_API_PROD_URL = "https://api.binance.com";
|
|
614
|
+
var MARGIN_TRADING_WS_STREAMS_PROD_URL = "wss://stream.binance.com:9443";
|
|
615
|
+
var MARGIN_TRADING_RISK_WS_STREAMS_PROD_URL = "wss://margin-stream.binance.com";
|
|
616
|
+
var MINING_REST_API_PROD_URL = "https://api.binance.com";
|
|
617
|
+
var NFT_REST_API_PROD_URL = "https://api.binance.com";
|
|
618
|
+
var PAY_REST_API_PROD_URL = "https://api.binance.com";
|
|
619
|
+
var REBATE_REST_API_PROD_URL = "https://api.binance.com";
|
|
620
|
+
var SIMPLE_EARN_REST_API_PROD_URL = "https://api.binance.com";
|
|
621
|
+
var SPOT_REST_API_PROD_URL = "https://api.binance.com";
|
|
622
|
+
var SPOT_REST_API_TESTNET_URL = "https://testnet.binance.vision";
|
|
623
|
+
var SPOT_WS_API_PROD_URL = "wss://ws-api.binance.com:443/ws-api/v3";
|
|
624
|
+
var SPOT_WS_API_TESTNET_URL = "wss://ws-api.testnet.binance.vision/ws-api/v3";
|
|
625
|
+
var SPOT_WS_STREAMS_PROD_URL = "wss://stream.binance.com:9443";
|
|
626
|
+
var SPOT_WS_STREAMS_TESTNET_URL = "wss://stream.testnet.binance.vision";
|
|
627
|
+
var SPOT_REST_API_MARKET_URL = "https://data-api.binance.vision";
|
|
628
|
+
var SPOT_WS_STREAMS_MARKET_URL = "wss://data-stream.binance.vision";
|
|
629
|
+
var STAKING_REST_API_PROD_URL = "https://api.binance.com";
|
|
630
|
+
var SUB_ACCOUNT_REST_API_PROD_URL = "https://api.binance.com";
|
|
631
|
+
var VIP_LOAN_REST_API_PROD_URL = "https://api.binance.com";
|
|
632
|
+
var WALLET_REST_API_PROD_URL = "https://api.binance.com";
|
|
633
|
+
|
|
634
|
+
// src/errors.ts
|
|
635
|
+
var ConnectorClientError = class _ConnectorClientError extends Error {
|
|
636
|
+
constructor(msg) {
|
|
637
|
+
super(msg || "An unexpected error occurred.");
|
|
638
|
+
Object.setPrototypeOf(this, _ConnectorClientError.prototype);
|
|
639
|
+
this.name = "ConnectorClientError";
|
|
640
|
+
}
|
|
641
|
+
};
|
|
642
|
+
var RequiredError = class _RequiredError extends Error {
|
|
643
|
+
constructor(field, msg) {
|
|
644
|
+
super(msg || `Required parameter ${field} was null or undefined.`);
|
|
645
|
+
this.field = field;
|
|
646
|
+
Object.setPrototypeOf(this, _RequiredError.prototype);
|
|
647
|
+
this.name = "RequiredError";
|
|
648
|
+
}
|
|
649
|
+
};
|
|
650
|
+
var UnauthorizedError = class _UnauthorizedError extends Error {
|
|
651
|
+
constructor(msg) {
|
|
652
|
+
super(msg || "Unauthorized access. Authentication required.");
|
|
653
|
+
Object.setPrototypeOf(this, _UnauthorizedError.prototype);
|
|
654
|
+
this.name = "UnauthorizedError";
|
|
655
|
+
}
|
|
656
|
+
};
|
|
657
|
+
var ForbiddenError = class _ForbiddenError extends Error {
|
|
658
|
+
constructor(msg) {
|
|
659
|
+
super(msg || "Access to the requested resource is forbidden.");
|
|
660
|
+
Object.setPrototypeOf(this, _ForbiddenError.prototype);
|
|
661
|
+
this.name = "ForbiddenError";
|
|
662
|
+
}
|
|
585
663
|
};
|
|
586
|
-
var
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
664
|
+
var TooManyRequestsError = class _TooManyRequestsError extends Error {
|
|
665
|
+
constructor(msg) {
|
|
666
|
+
super(msg || "Too many requests. You are being rate-limited.");
|
|
667
|
+
Object.setPrototypeOf(this, _TooManyRequestsError.prototype);
|
|
668
|
+
this.name = "TooManyRequestsError";
|
|
669
|
+
}
|
|
670
|
+
};
|
|
671
|
+
var RateLimitBanError = class _RateLimitBanError extends Error {
|
|
672
|
+
constructor(msg) {
|
|
673
|
+
super(msg || "The IP address has been banned for exceeding rate limits.");
|
|
674
|
+
Object.setPrototypeOf(this, _RateLimitBanError.prototype);
|
|
675
|
+
this.name = "RateLimitBanError";
|
|
676
|
+
}
|
|
677
|
+
};
|
|
678
|
+
var ServerError = class _ServerError extends Error {
|
|
679
|
+
constructor(msg, statusCode) {
|
|
680
|
+
super(msg || "An internal server error occurred.");
|
|
681
|
+
this.statusCode = statusCode;
|
|
682
|
+
Object.setPrototypeOf(this, _ServerError.prototype);
|
|
683
|
+
this.name = "ServerError";
|
|
684
|
+
}
|
|
685
|
+
};
|
|
686
|
+
var NetworkError = class _NetworkError extends Error {
|
|
687
|
+
constructor(msg) {
|
|
688
|
+
super(msg || "A network error occurred.");
|
|
689
|
+
Object.setPrototypeOf(this, _NetworkError.prototype);
|
|
690
|
+
this.name = "NetworkError";
|
|
691
|
+
}
|
|
692
|
+
};
|
|
693
|
+
var NotFoundError = class _NotFoundError extends Error {
|
|
694
|
+
constructor(msg) {
|
|
695
|
+
super(msg || "The requested resource was not found.");
|
|
696
|
+
Object.setPrototypeOf(this, _NotFoundError.prototype);
|
|
697
|
+
this.name = "NotFoundError";
|
|
698
|
+
}
|
|
699
|
+
};
|
|
700
|
+
var BadRequestError = class _BadRequestError extends Error {
|
|
701
|
+
constructor(msg) {
|
|
702
|
+
super(msg || "The request was invalid or cannot be otherwise served.");
|
|
703
|
+
Object.setPrototypeOf(this, _BadRequestError.prototype);
|
|
704
|
+
this.name = "BadRequestError";
|
|
705
|
+
}
|
|
706
|
+
};
|
|
707
|
+
|
|
708
|
+
// src/logger.ts
|
|
709
|
+
var LogLevel = /* @__PURE__ */ ((LogLevel2) => {
|
|
710
|
+
LogLevel2["NONE"] = "";
|
|
711
|
+
LogLevel2["DEBUG"] = "debug";
|
|
712
|
+
LogLevel2["INFO"] = "info";
|
|
713
|
+
LogLevel2["WARN"] = "warn";
|
|
714
|
+
LogLevel2["ERROR"] = "error";
|
|
715
|
+
return LogLevel2;
|
|
716
|
+
})(LogLevel || {});
|
|
717
|
+
var Logger = class _Logger {
|
|
718
|
+
constructor() {
|
|
719
|
+
this.minLogLevel = "info" /* INFO */;
|
|
720
|
+
this.levelsOrder = [
|
|
721
|
+
"" /* NONE */,
|
|
722
|
+
"debug" /* DEBUG */,
|
|
723
|
+
"info" /* INFO */,
|
|
724
|
+
"warn" /* WARN */,
|
|
725
|
+
"error" /* ERROR */
|
|
726
|
+
];
|
|
727
|
+
}
|
|
728
|
+
static getInstance() {
|
|
729
|
+
if (!_Logger.instance) {
|
|
730
|
+
_Logger.instance = new _Logger();
|
|
609
731
|
}
|
|
610
|
-
return
|
|
611
|
-
}
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
if (normalizedKey.startsWith("x-mbx-used-weight-")) {
|
|
616
|
-
const details = parseIntervalDetails(normalizedKey);
|
|
617
|
-
if (details) {
|
|
618
|
-
rateLimits.push({
|
|
619
|
-
rateLimitType: "REQUEST_WEIGHT",
|
|
620
|
-
interval: details.interval,
|
|
621
|
-
intervalNum: details.intervalNum,
|
|
622
|
-
count: parseInt(value, 10)
|
|
623
|
-
});
|
|
624
|
-
}
|
|
625
|
-
} else if (normalizedKey.startsWith("x-mbx-order-count-")) {
|
|
626
|
-
const details = parseIntervalDetails(normalizedKey);
|
|
627
|
-
if (details) {
|
|
628
|
-
rateLimits.push({
|
|
629
|
-
rateLimitType: "ORDERS",
|
|
630
|
-
interval: details.interval,
|
|
631
|
-
intervalNum: details.intervalNum,
|
|
632
|
-
count: parseInt(value, 10)
|
|
633
|
-
});
|
|
634
|
-
}
|
|
732
|
+
return _Logger.instance;
|
|
733
|
+
}
|
|
734
|
+
setMinLogLevel(level) {
|
|
735
|
+
if (!this.isValidLogLevel(level)) {
|
|
736
|
+
throw new Error(`Invalid log level: ${level}`);
|
|
635
737
|
}
|
|
738
|
+
this.minLogLevel = level;
|
|
636
739
|
}
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
740
|
+
isValidLogLevel(level) {
|
|
741
|
+
return this.levelsOrder.includes(level);
|
|
742
|
+
}
|
|
743
|
+
log(level, ...message) {
|
|
744
|
+
if (level === "" /* NONE */ || !this.allowLevelLog(level)) {
|
|
745
|
+
return;
|
|
641
746
|
}
|
|
747
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
748
|
+
console[level](`[${timestamp}] [${level.toLowerCase()}]`, ...message);
|
|
642
749
|
}
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
const localVarUrlObj = new URL(endpoint, configuration?.basePath);
|
|
647
|
-
const localVarRequestOptions = {
|
|
648
|
-
method,
|
|
649
|
-
...configuration?.baseOptions
|
|
650
|
-
};
|
|
651
|
-
const localVarQueryParameter = { ...params };
|
|
652
|
-
if (options.isSigned) {
|
|
653
|
-
const timestamp = getTimestamp();
|
|
654
|
-
localVarQueryParameter["timestamp"] = timestamp;
|
|
655
|
-
const signature = getSignature(configuration, localVarQueryParameter);
|
|
656
|
-
if (signature) {
|
|
657
|
-
localVarQueryParameter["signature"] = signature;
|
|
750
|
+
allowLevelLog(level) {
|
|
751
|
+
if (!this.isValidLogLevel(level)) {
|
|
752
|
+
throw new Error(`Invalid log level: ${level}`);
|
|
658
753
|
}
|
|
754
|
+
const currentLevelIndex = this.levelsOrder.indexOf(level);
|
|
755
|
+
const minLevelIndex = this.levelsOrder.indexOf(this.minLogLevel);
|
|
756
|
+
return currentLevelIndex >= minLevelIndex;
|
|
659
757
|
}
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
758
|
+
debug(...message) {
|
|
759
|
+
this.log("debug" /* DEBUG */, ...message);
|
|
760
|
+
}
|
|
761
|
+
info(...message) {
|
|
762
|
+
this.log("info" /* INFO */, ...message);
|
|
763
|
+
}
|
|
764
|
+
warn(...message) {
|
|
765
|
+
this.log("warn" /* WARN */, ...message);
|
|
766
|
+
}
|
|
767
|
+
error(...message) {
|
|
768
|
+
this.log("error" /* ERROR */, ...message);
|
|
667
769
|
}
|
|
668
|
-
return httpRequestFunction(
|
|
669
|
-
{
|
|
670
|
-
url: toPathString(localVarUrlObj),
|
|
671
|
-
options: localVarRequestOptions
|
|
672
|
-
},
|
|
673
|
-
configuration
|
|
674
|
-
);
|
|
675
770
|
};
|
|
676
|
-
function removeEmptyValue(obj) {
|
|
677
|
-
if (!(obj instanceof Object)) return {};
|
|
678
|
-
return Object.fromEntries(
|
|
679
|
-
Object.entries(obj).filter(
|
|
680
|
-
([, value]) => value !== null && value !== void 0 && value !== ""
|
|
681
|
-
)
|
|
682
|
-
);
|
|
683
|
-
}
|
|
684
|
-
function sortObject(obj) {
|
|
685
|
-
return Object.keys(obj).sort().reduce((res, key) => {
|
|
686
|
-
res[key] = obj[key];
|
|
687
|
-
return res;
|
|
688
|
-
}, {});
|
|
689
|
-
}
|
|
690
|
-
function replaceWebsocketStreamsPlaceholders(str, variables) {
|
|
691
|
-
const normalizedVariables = Object.keys(variables).reduce(
|
|
692
|
-
(acc, key) => {
|
|
693
|
-
const normalizedKey = key.toLowerCase().replace(/[-_]/g, "");
|
|
694
|
-
acc[normalizedKey] = variables[key];
|
|
695
|
-
return acc;
|
|
696
|
-
},
|
|
697
|
-
{}
|
|
698
|
-
);
|
|
699
|
-
return str.replace(/(@)?<([^>]+)>/g, (match, precedingAt, fieldName) => {
|
|
700
|
-
const normalizedFieldName = fieldName.toLowerCase().replace(/[-_]/g, "");
|
|
701
|
-
if (Object.prototype.hasOwnProperty.call(normalizedVariables, normalizedFieldName) && normalizedVariables[normalizedFieldName] != null) {
|
|
702
|
-
const value = normalizedVariables[normalizedFieldName];
|
|
703
|
-
switch (normalizedFieldName) {
|
|
704
|
-
case "symbol":
|
|
705
|
-
case "windowsize":
|
|
706
|
-
return value.toLowerCase();
|
|
707
|
-
case "updatespeed":
|
|
708
|
-
return `@${value}`;
|
|
709
|
-
default:
|
|
710
|
-
return (precedingAt || "") + value;
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
return "";
|
|
714
|
-
});
|
|
715
|
-
}
|
|
716
|
-
function buildUserAgent(packageName, packageVersion) {
|
|
717
|
-
return `${packageName}/${packageVersion} (Node.js/${process.version}; ${(0, import_os.platform)()}; ${(0, import_os.arch)()})`;
|
|
718
|
-
}
|
|
719
771
|
|
|
720
772
|
// src/websocket.ts
|
|
721
773
|
var import_events = require("events");
|
|
@@ -775,6 +827,20 @@ var WebsocketCommon = class _WebsocketCommon extends WebsocketEventEmitter {
|
|
|
775
827
|
});
|
|
776
828
|
}
|
|
777
829
|
}
|
|
830
|
+
/**
|
|
831
|
+
* Retrieves available WebSocket connections based on the connection mode and readiness.
|
|
832
|
+
* In 'single' mode, returns the first connection in the pool.
|
|
833
|
+
* In 'pool' mode, filters and returns connections that are ready for use.
|
|
834
|
+
* @param allowNonEstablishedWebsockets - Optional flag to include non-established WebSocket connections.
|
|
835
|
+
* @returns An array of available WebSocket connections.
|
|
836
|
+
*/
|
|
837
|
+
getAvailableConnections(allowNonEstablishedWebsockets = false) {
|
|
838
|
+
if (this.mode === "single") return [this.connectionPool[0]];
|
|
839
|
+
const availableConnections = this.connectionPool.filter(
|
|
840
|
+
(connection) => this.isConnectionReady(connection, allowNonEstablishedWebsockets)
|
|
841
|
+
);
|
|
842
|
+
return availableConnections;
|
|
843
|
+
}
|
|
778
844
|
/**
|
|
779
845
|
* Gets a WebSocket connection from the pool or single connection.
|
|
780
846
|
* If the connection mode is 'single', it returns the first connection in the pool.
|
|
@@ -784,10 +850,7 @@ var WebsocketCommon = class _WebsocketCommon extends WebsocketEventEmitter {
|
|
|
784
850
|
* @returns {WebsocketConnection} The selected WebSocket connection.
|
|
785
851
|
*/
|
|
786
852
|
getConnection(allowNonEstablishedWebsockets = false) {
|
|
787
|
-
|
|
788
|
-
const availableConnections = this.connectionPool.filter(
|
|
789
|
-
(connection) => this.isConnectionReady(connection, allowNonEstablishedWebsockets)
|
|
790
|
-
);
|
|
853
|
+
const availableConnections = this.getAvailableConnections(allowNonEstablishedWebsockets);
|
|
791
854
|
if (availableConnections.length === 0) {
|
|
792
855
|
throw new Error("No available Websocket connections are ready.");
|
|
793
856
|
}
|
|
@@ -907,6 +970,40 @@ var WebsocketCommon = class _WebsocketCommon extends WebsocketEventEmitter {
|
|
|
907
970
|
WebsocketConnectionToClose.close();
|
|
908
971
|
this.cleanup(WebsocketConnectionToClose);
|
|
909
972
|
}
|
|
973
|
+
/**
|
|
974
|
+
* Attempts to re-establish a session for a WebSocket connection.
|
|
975
|
+
* If a session logon request exists and the connection is not already logged on,
|
|
976
|
+
* it sends an authentication request and updates the connection's logged-on status.
|
|
977
|
+
* @param connection - The WebSocket connection to re-authenticate.
|
|
978
|
+
* @private
|
|
979
|
+
*/
|
|
980
|
+
async sessionReLogon(connection) {
|
|
981
|
+
const req = connection.sessionLogonReq;
|
|
982
|
+
if (req && !connection.isSessionLoggedOn) {
|
|
983
|
+
const data = buildWebsocketAPIMessage(
|
|
984
|
+
this.configuration,
|
|
985
|
+
req.method,
|
|
986
|
+
req.payload,
|
|
987
|
+
req.options
|
|
988
|
+
);
|
|
989
|
+
this.logger.debug(`Session re-logon with connection id: ${connection.id}`, data);
|
|
990
|
+
try {
|
|
991
|
+
await this.send(
|
|
992
|
+
JSON.stringify(data),
|
|
993
|
+
data.id,
|
|
994
|
+
true,
|
|
995
|
+
this.configuration.timeout,
|
|
996
|
+
connection
|
|
997
|
+
);
|
|
998
|
+
connection.isSessionLoggedOn = true;
|
|
999
|
+
} catch (err) {
|
|
1000
|
+
this.logger.error(
|
|
1001
|
+
`Session re-logon with connection id ${connection.id} failed:`,
|
|
1002
|
+
err
|
|
1003
|
+
);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
910
1007
|
/**
|
|
911
1008
|
* Cleans up WebSocket connection resources.
|
|
912
1009
|
* Removes all listeners and clears any associated timers for the provided WebSocket client.
|
|
@@ -931,8 +1028,6 @@ var WebsocketCommon = class _WebsocketCommon extends WebsocketEventEmitter {
|
|
|
931
1028
|
* Handles the opening of a WebSocket connection.
|
|
932
1029
|
* @param url - The URL of the WebSocket server.
|
|
933
1030
|
* @param targetConnection - The WebSocket connection being opened.
|
|
934
|
-
* @param oldConnection - The previous WebSocket connection, if this is a renewal.
|
|
935
|
-
* @param isRenewal - Indicates whether this is a connection renewal.
|
|
936
1031
|
* @param oldWSConnection - The WebSocket client instance associated with the old connection.
|
|
937
1032
|
*/
|
|
938
1033
|
onOpen(url, targetConnection, oldWSConnection) {
|
|
@@ -947,6 +1042,7 @@ var WebsocketCommon = class _WebsocketCommon extends WebsocketEventEmitter {
|
|
|
947
1042
|
} else {
|
|
948
1043
|
this.emit("open", this);
|
|
949
1044
|
}
|
|
1045
|
+
this.sessionReLogon(targetConnection);
|
|
950
1046
|
}
|
|
951
1047
|
/**
|
|
952
1048
|
* Returns the URL to use when reconnecting.
|
|
@@ -1017,10 +1113,12 @@ var WebsocketCommon = class _WebsocketCommon extends WebsocketEventEmitter {
|
|
|
1017
1113
|
);
|
|
1018
1114
|
if (isRenewal) targetConnection.renewalPending = true;
|
|
1019
1115
|
else targetConnection.ws = ws;
|
|
1116
|
+
targetConnection.isSessionLoggedOn = false;
|
|
1020
1117
|
this.scheduleTimer(
|
|
1021
1118
|
ws,
|
|
1022
1119
|
() => {
|
|
1023
1120
|
this.logger.info(`Renewing Websocket connection with id ${targetConnection.id}`);
|
|
1121
|
+
targetConnection.isSessionLoggedOn = false;
|
|
1024
1122
|
this.enqueueReconnection(
|
|
1025
1123
|
targetConnection,
|
|
1026
1124
|
this.getReconnectURL(url, targetConnection),
|
|
@@ -1064,6 +1162,7 @@ var WebsocketCommon = class _WebsocketCommon extends WebsocketEventEmitter {
|
|
|
1064
1162
|
this.logger.info(
|
|
1065
1163
|
`Reconnecting conection with id ${targetConnection.id} to the server.`
|
|
1066
1164
|
);
|
|
1165
|
+
targetConnection.isSessionLoggedOn = false;
|
|
1067
1166
|
targetConnection.reconnectionPending = true;
|
|
1068
1167
|
this.enqueueReconnection(
|
|
1069
1168
|
targetConnection,
|
|
@@ -1099,6 +1198,8 @@ var WebsocketCommon = class _WebsocketCommon extends WebsocketEventEmitter {
|
|
|
1099
1198
|
else {
|
|
1100
1199
|
this.connectionPool.forEach((connection) => {
|
|
1101
1200
|
connection.closeInitiated = true;
|
|
1201
|
+
connection.isSessionLoggedOn = false;
|
|
1202
|
+
connection.sessionLogonReq = void 0;
|
|
1102
1203
|
});
|
|
1103
1204
|
const disconnectPromises = this.connectionPool.map(
|
|
1104
1205
|
(connection) => this.closeConnectionGracefully(connection.ws, connection)
|
|
@@ -1259,37 +1360,43 @@ var WebsocketAPIBase = class extends WebsocketCommon {
|
|
|
1259
1360
|
});
|
|
1260
1361
|
});
|
|
1261
1362
|
}
|
|
1262
|
-
|
|
1263
|
-
* Sends a message to the WebSocket API Server.
|
|
1264
|
-
* Supports both signed and unsigned messages.
|
|
1265
|
-
* @param method The API method to call
|
|
1266
|
-
* @param payload Message parameters and options
|
|
1267
|
-
* @param options Additional requests options (withApiKey, isSigned)
|
|
1268
|
-
* @returns Promise that resolves with the server response
|
|
1269
|
-
* @throws Error if not connected
|
|
1270
|
-
*/
|
|
1271
|
-
sendMessage(method, payload = {}, options = {}) {
|
|
1363
|
+
async sendMessage(method, payload = {}, options = {}) {
|
|
1272
1364
|
if (!this.isConnected()) {
|
|
1273
|
-
|
|
1274
|
-
}
|
|
1275
|
-
const id = payload.id && /^[0-9a-f]{32}$/.test(payload.id) ? payload.id : randomString();
|
|
1276
|
-
delete payload.id;
|
|
1277
|
-
let params = removeEmptyValue(payload);
|
|
1278
|
-
if (options.withApiKey || options.isSigned) {
|
|
1279
|
-
params.apiKey = this.configuration.apiKey;
|
|
1365
|
+
throw new Error("Not connected");
|
|
1280
1366
|
}
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
}
|
|
1286
|
-
const data = {
|
|
1287
|
-
id,
|
|
1367
|
+
const connections = options.isSessionLogon || options.isSessionLogout ? this.getAvailableConnections() : [this.getConnection()];
|
|
1368
|
+
const skipAuth = options.isSessionLogon || options.isSessionLogout ? false : this.configuration.autoSessionReLogon && connections[0].isSessionLoggedOn;
|
|
1369
|
+
const data = buildWebsocketAPIMessage(
|
|
1370
|
+
this.configuration,
|
|
1288
1371
|
method,
|
|
1289
|
-
|
|
1290
|
-
|
|
1372
|
+
payload,
|
|
1373
|
+
options,
|
|
1374
|
+
skipAuth
|
|
1375
|
+
);
|
|
1291
1376
|
this.logger.debug("Send message to Binance WebSocket API Server:", data);
|
|
1292
|
-
|
|
1377
|
+
const responses = await Promise.all(
|
|
1378
|
+
connections.map(
|
|
1379
|
+
(connection) => this.send(
|
|
1380
|
+
JSON.stringify(data),
|
|
1381
|
+
data.id,
|
|
1382
|
+
true,
|
|
1383
|
+
this.configuration.timeout,
|
|
1384
|
+
connection
|
|
1385
|
+
)
|
|
1386
|
+
)
|
|
1387
|
+
);
|
|
1388
|
+
if ((options.isSessionLogon || options.isSessionLogout) && this.configuration.autoSessionReLogon) {
|
|
1389
|
+
connections.forEach((connection) => {
|
|
1390
|
+
if (options.isSessionLogon) {
|
|
1391
|
+
connection.isSessionLoggedOn = true;
|
|
1392
|
+
connection.sessionLogonReq = { method, payload, options };
|
|
1393
|
+
} else {
|
|
1394
|
+
connection.isSessionLoggedOn = false;
|
|
1395
|
+
connection.sessionLogonReq = void 0;
|
|
1396
|
+
}
|
|
1397
|
+
});
|
|
1398
|
+
}
|
|
1399
|
+
return connections.length === 1 ? responses[0] : responses;
|
|
1293
1400
|
}
|
|
1294
1401
|
};
|
|
1295
1402
|
var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
@@ -1401,7 +1508,6 @@ var WebsocketStreamsBase = class extends WebsocketCommon {
|
|
|
1401
1508
|
* @param url The URL of the WebSocket connection.
|
|
1402
1509
|
* @param targetConnection The WebSocket connection that was opened.
|
|
1403
1510
|
* @param oldConnection The previous WebSocket connection, if any.
|
|
1404
|
-
* @param isRenewal Whether the connection is a renewal of an existing connection.
|
|
1405
1511
|
*/
|
|
1406
1512
|
onOpen(url, targetConnection, oldWSConnection) {
|
|
1407
1513
|
this.processPendingSubscriptions(targetConnection);
|
|
@@ -1544,8 +1650,11 @@ function createStreamHandler(websocketBase, streamOrId, id) {
|
|
|
1544
1650
|
DERIVATIVES_TRADING_OPTIONS_REST_API_PROD_URL,
|
|
1545
1651
|
DERIVATIVES_TRADING_OPTIONS_WS_STREAMS_PROD_URL,
|
|
1546
1652
|
DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_REST_API_PROD_URL,
|
|
1653
|
+
DERIVATIVES_TRADING_PORTFOLIO_MARGIN_PRO_WS_STREAMS_PROD_URL,
|
|
1547
1654
|
DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_PROD_URL,
|
|
1548
1655
|
DERIVATIVES_TRADING_PORTFOLIO_MARGIN_REST_API_TESTNET_URL,
|
|
1656
|
+
DERIVATIVES_TRADING_PORTFOLIO_MARGIN_WS_STREAMS_PROD_URL,
|
|
1657
|
+
DERIVATIVES_TRADING_PORTFOLIO_MARGIN_WS_STREAMS_TESTNET_URL,
|
|
1549
1658
|
DERIVATIVES_TRADING_USDS_FUTURES_REST_API_PROD_URL,
|
|
1550
1659
|
DERIVATIVES_TRADING_USDS_FUTURES_REST_API_TESTNET_URL,
|
|
1551
1660
|
DERIVATIVES_TRADING_USDS_FUTURES_WS_API_PROD_URL,
|
|
@@ -1559,6 +1668,8 @@ function createStreamHandler(websocketBase, streamOrId, id) {
|
|
|
1559
1668
|
LogLevel,
|
|
1560
1669
|
Logger,
|
|
1561
1670
|
MARGIN_TRADING_REST_API_PROD_URL,
|
|
1671
|
+
MARGIN_TRADING_RISK_WS_STREAMS_PROD_URL,
|
|
1672
|
+
MARGIN_TRADING_WS_STREAMS_PROD_URL,
|
|
1562
1673
|
MINING_REST_API_PROD_URL,
|
|
1563
1674
|
NFT_REST_API_PROD_URL,
|
|
1564
1675
|
NetworkError,
|
|
@@ -1591,16 +1702,19 @@ function createStreamHandler(websocketBase, streamOrId, id) {
|
|
|
1591
1702
|
assertParamExists,
|
|
1592
1703
|
buildQueryString,
|
|
1593
1704
|
buildUserAgent,
|
|
1705
|
+
buildWebsocketAPIMessage,
|
|
1594
1706
|
clearSignerCache,
|
|
1595
1707
|
createStreamHandler,
|
|
1596
1708
|
delay,
|
|
1597
1709
|
getSignature,
|
|
1598
1710
|
getTimestamp,
|
|
1599
1711
|
httpRequestFunction,
|
|
1712
|
+
parseCustomHeaders,
|
|
1600
1713
|
parseRateLimitHeaders,
|
|
1601
1714
|
randomString,
|
|
1602
1715
|
removeEmptyValue,
|
|
1603
1716
|
replaceWebsocketStreamsPlaceholders,
|
|
1717
|
+
sanitizeHeaderValue,
|
|
1604
1718
|
sendRequest,
|
|
1605
1719
|
setFlattenedQueryParams,
|
|
1606
1720
|
setSearchParams,
|