@binance/common 1.0.6 → 1.1.1
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 +28 -7
- package/dist/index.d.ts +28 -7
- package/dist/index.js +92 -59
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +90 -59
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -249,6 +249,52 @@ import crypto from "crypto";
|
|
|
249
249
|
import fs from "fs";
|
|
250
250
|
import https from "https";
|
|
251
251
|
import globalAxios from "axios";
|
|
252
|
+
var signerCache = /* @__PURE__ */ new WeakMap();
|
|
253
|
+
var RequestSigner = class {
|
|
254
|
+
constructor(configuration) {
|
|
255
|
+
if (configuration.apiSecret && !configuration.privateKey) {
|
|
256
|
+
this.apiSecret = configuration.apiSecret;
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
if (configuration.privateKey) {
|
|
260
|
+
let privateKey = configuration.privateKey;
|
|
261
|
+
if (typeof privateKey === "string" && fs.existsSync(privateKey)) {
|
|
262
|
+
privateKey = fs.readFileSync(privateKey, "utf-8");
|
|
263
|
+
}
|
|
264
|
+
const keyInput = { key: privateKey };
|
|
265
|
+
if (configuration.privateKeyPassphrase && typeof configuration.privateKeyPassphrase === "string") {
|
|
266
|
+
keyInput.passphrase = configuration.privateKeyPassphrase;
|
|
267
|
+
}
|
|
268
|
+
try {
|
|
269
|
+
this.keyObject = crypto.createPrivateKey(keyInput);
|
|
270
|
+
this.keyType = this.keyObject.asymmetricKeyType;
|
|
271
|
+
} catch {
|
|
272
|
+
throw new Error(
|
|
273
|
+
"Invalid private key. Please provide a valid RSA or ED25519 private key."
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
throw new Error("Either 'apiSecret' or 'privateKey' must be provided for signed requests.");
|
|
279
|
+
}
|
|
280
|
+
sign(queryParams) {
|
|
281
|
+
const params = buildQueryString(queryParams);
|
|
282
|
+
if (this.apiSecret)
|
|
283
|
+
return crypto.createHmac("sha256", this.apiSecret).update(params).digest("hex");
|
|
284
|
+
if (this.keyObject && this.keyType) {
|
|
285
|
+
const data = Buffer.from(params);
|
|
286
|
+
if (this.keyType === "rsa")
|
|
287
|
+
return crypto.sign("RSA-SHA256", data, this.keyObject).toString("base64");
|
|
288
|
+
if (this.keyType === "ed25519")
|
|
289
|
+
return crypto.sign(null, data, this.keyObject).toString("base64");
|
|
290
|
+
throw new Error("Unsupported private key type. Must be RSA or ED25519.");
|
|
291
|
+
}
|
|
292
|
+
throw new Error("Signer is not properly initialized.");
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
var clearSignerCache = function() {
|
|
296
|
+
signerCache = /* @__PURE__ */ new WeakMap();
|
|
297
|
+
};
|
|
252
298
|
function buildQueryString(params) {
|
|
253
299
|
if (!params) return "";
|
|
254
300
|
return Object.entries(params).map(stringifyKeyValuePair).join("&");
|
|
@@ -275,39 +321,12 @@ function getTimestamp() {
|
|
|
275
321
|
return Date.now();
|
|
276
322
|
}
|
|
277
323
|
var getSignature = function(configuration, queryParams) {
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
} else if (configuration?.privateKey) {
|
|
283
|
-
let privateKey = configuration.privateKey;
|
|
284
|
-
if (typeof privateKey === "string" && fs.existsSync(privateKey)) {
|
|
285
|
-
privateKey = fs.readFileSync(privateKey, "utf-8");
|
|
286
|
-
}
|
|
287
|
-
let keyObject;
|
|
288
|
-
try {
|
|
289
|
-
const privateKeyObj = { key: privateKey };
|
|
290
|
-
if (configuration.privateKeyPassphrase && typeof configuration.privateKeyPassphrase === "string") {
|
|
291
|
-
privateKeyObj.passphrase = configuration.privateKeyPassphrase;
|
|
292
|
-
}
|
|
293
|
-
keyObject = crypto.createPrivateKey(privateKeyObj);
|
|
294
|
-
} catch {
|
|
295
|
-
throw new Error(
|
|
296
|
-
"Invalid private key. Please provide a valid RSA or ED25519 private key."
|
|
297
|
-
);
|
|
298
|
-
}
|
|
299
|
-
const keyType = keyObject.asymmetricKeyType;
|
|
300
|
-
if (keyType === "rsa") {
|
|
301
|
-
signature = crypto.sign("RSA-SHA256", Buffer.from(params), keyObject).toString("base64");
|
|
302
|
-
} else if (keyType === "ed25519") {
|
|
303
|
-
signature = crypto.sign(null, Buffer.from(params), keyObject).toString("base64");
|
|
304
|
-
} else {
|
|
305
|
-
throw new Error("Unsupported private key type. Must be RSA or ED25519.");
|
|
306
|
-
}
|
|
307
|
-
} else {
|
|
308
|
-
throw new Error("Either 'apiSecret' or 'privateKey' must be provided for signed requests.");
|
|
324
|
+
let signer = signerCache.get(configuration);
|
|
325
|
+
if (!signer) {
|
|
326
|
+
signer = new RequestSigner(configuration);
|
|
327
|
+
signerCache.set(configuration, signer);
|
|
309
328
|
}
|
|
310
|
-
return
|
|
329
|
+
return signer.sign(queryParams);
|
|
311
330
|
};
|
|
312
331
|
var assertParamExists = function(functionName, paramName, paramValue) {
|
|
313
332
|
if (paramValue === null || paramValue === void 0) {
|
|
@@ -319,25 +338,26 @@ var assertParamExists = function(functionName, paramName, paramValue) {
|
|
|
319
338
|
};
|
|
320
339
|
function setFlattenedQueryParams(urlSearchParams, parameter, key = "") {
|
|
321
340
|
if (parameter == null) return;
|
|
341
|
+
if (Array.isArray(parameter)) {
|
|
342
|
+
if (key)
|
|
343
|
+
urlSearchParams.set(key, JSON.stringify(parameter));
|
|
344
|
+
else
|
|
345
|
+
for (const item of parameter) {
|
|
346
|
+
setFlattenedQueryParams(urlSearchParams, item, "");
|
|
347
|
+
}
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
322
350
|
if (typeof parameter === "object") {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
(currentKey) => setFlattenedQueryParams(
|
|
328
|
-
urlSearchParams,
|
|
329
|
-
parameter[currentKey],
|
|
330
|
-
`${key}${key !== "" ? "." : ""}${currentKey}`
|
|
331
|
-
)
|
|
332
|
-
);
|
|
333
|
-
}
|
|
334
|
-
} else {
|
|
335
|
-
if (urlSearchParams.has(key)) {
|
|
336
|
-
urlSearchParams.append(key, String(parameter));
|
|
337
|
-
} else {
|
|
338
|
-
urlSearchParams.set(key, String(parameter));
|
|
351
|
+
for (const subKey of Object.keys(parameter)) {
|
|
352
|
+
const subVal = parameter[subKey];
|
|
353
|
+
const newKey = key ? `${key}.${subKey}` : subKey;
|
|
354
|
+
setFlattenedQueryParams(urlSearchParams, subVal, newKey);
|
|
339
355
|
}
|
|
356
|
+
return;
|
|
340
357
|
}
|
|
358
|
+
const str = String(parameter);
|
|
359
|
+
if (urlSearchParams.has(key)) urlSearchParams.append(key, str);
|
|
360
|
+
else urlSearchParams.set(key, str);
|
|
341
361
|
}
|
|
342
362
|
var setSearchParams = function(url, ...objects) {
|
|
343
363
|
const searchParams = new URLSearchParams(url.search);
|
|
@@ -359,18 +379,13 @@ var httpRequestFunction = async function(axiosArgs, configuration) {
|
|
|
359
379
|
...axiosArgs.options,
|
|
360
380
|
url: (globalAxios.defaults?.baseURL ? "" : configuration?.basePath ?? "") + axiosArgs.url
|
|
361
381
|
};
|
|
362
|
-
if (configuration?.keepAlive)
|
|
363
|
-
axiosRequestArgs.httpsAgent = new https.Agent({
|
|
364
|
-
|
|
365
|
-
keepAlive: true
|
|
366
|
-
});
|
|
367
|
-
}
|
|
368
|
-
if (configuration?.compression) {
|
|
382
|
+
if (configuration?.keepAlive && !configuration?.baseOptions?.httpsAgent)
|
|
383
|
+
axiosRequestArgs.httpsAgent = new https.Agent({ keepAlive: true });
|
|
384
|
+
if (configuration?.compression)
|
|
369
385
|
axiosRequestArgs.headers = {
|
|
370
386
|
...axiosRequestArgs.headers,
|
|
371
387
|
"Accept-Encoding": "gzip, deflate, br"
|
|
372
388
|
};
|
|
373
|
-
}
|
|
374
389
|
const retries = configuration?.retries ?? 0;
|
|
375
390
|
const backoff = configuration?.backoff ?? 0;
|
|
376
391
|
let attempt = 0;
|
|
@@ -383,7 +398,13 @@ var httpRequestFunction = async function(axiosArgs, configuration) {
|
|
|
383
398
|
});
|
|
384
399
|
const rateLimits = parseRateLimitHeaders(response.headers);
|
|
385
400
|
return {
|
|
386
|
-
data: async () =>
|
|
401
|
+
data: async () => {
|
|
402
|
+
try {
|
|
403
|
+
return JSON.parse(response.data);
|
|
404
|
+
} catch (err) {
|
|
405
|
+
throw new Error(`Failed to parse JSON response: ${err}`);
|
|
406
|
+
}
|
|
407
|
+
},
|
|
387
408
|
status: response.status,
|
|
388
409
|
headers: response.headers,
|
|
389
410
|
rateLimits
|
|
@@ -404,7 +425,11 @@ var httpRequestFunction = async function(axiosArgs, configuration) {
|
|
|
404
425
|
let data = {};
|
|
405
426
|
if (responseData && responseData !== null) {
|
|
406
427
|
if (typeof responseData === "string" && responseData !== "")
|
|
407
|
-
|
|
428
|
+
try {
|
|
429
|
+
data = JSON.parse(responseData);
|
|
430
|
+
} catch {
|
|
431
|
+
data = {};
|
|
432
|
+
}
|
|
408
433
|
else if (typeof responseData === "object")
|
|
409
434
|
data = responseData;
|
|
410
435
|
}
|
|
@@ -1353,7 +1378,11 @@ function createStreamHandler(websocketBase, streamOrId, id) {
|
|
|
1353
1378
|
return {
|
|
1354
1379
|
on: (event, callback) => {
|
|
1355
1380
|
if (event === "message") {
|
|
1356
|
-
registeredCallback = (data) =>
|
|
1381
|
+
registeredCallback = (data) => {
|
|
1382
|
+
Promise.resolve(callback(data)).catch((err) => {
|
|
1383
|
+
websocketBase.logger.error(`Error in stream callback: ${err}`);
|
|
1384
|
+
});
|
|
1385
|
+
};
|
|
1357
1386
|
const callbackSet = websocketBase.streamCallbackMap.get(streamOrId) ?? /* @__PURE__ */ new Set();
|
|
1358
1387
|
callbackSet.add(registeredCallback);
|
|
1359
1388
|
websocketBase.streamCallbackMap.set(streamOrId, callbackSet);
|
|
@@ -1434,6 +1463,7 @@ export {
|
|
|
1434
1463
|
WebsocketStreamsBase,
|
|
1435
1464
|
assertParamExists,
|
|
1436
1465
|
buildQueryString,
|
|
1466
|
+
clearSignerCache,
|
|
1437
1467
|
createStreamHandler,
|
|
1438
1468
|
delay,
|
|
1439
1469
|
getSignature,
|
|
@@ -1444,6 +1474,7 @@ export {
|
|
|
1444
1474
|
removeEmptyValue,
|
|
1445
1475
|
replaceWebsocketStreamsPlaceholders,
|
|
1446
1476
|
sendRequest,
|
|
1477
|
+
setFlattenedQueryParams,
|
|
1447
1478
|
setSearchParams,
|
|
1448
1479
|
shouldRetryRequest,
|
|
1449
1480
|
sortObject,
|