@binance/common 1.1.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -248,7 +248,54 @@ var Logger = class _Logger {
248
248
  import crypto from "crypto";
249
249
  import fs from "fs";
250
250
  import https from "https";
251
+ import { platform, arch } from "os";
251
252
  import globalAxios from "axios";
253
+ var signerCache = /* @__PURE__ */ new WeakMap();
254
+ var RequestSigner = class {
255
+ constructor(configuration) {
256
+ if (configuration.apiSecret && !configuration.privateKey) {
257
+ this.apiSecret = configuration.apiSecret;
258
+ return;
259
+ }
260
+ if (configuration.privateKey) {
261
+ let privateKey = configuration.privateKey;
262
+ if (typeof privateKey === "string" && fs.existsSync(privateKey)) {
263
+ privateKey = fs.readFileSync(privateKey, "utf-8");
264
+ }
265
+ const keyInput = { key: privateKey };
266
+ if (configuration.privateKeyPassphrase && typeof configuration.privateKeyPassphrase === "string") {
267
+ keyInput.passphrase = configuration.privateKeyPassphrase;
268
+ }
269
+ try {
270
+ this.keyObject = crypto.createPrivateKey(keyInput);
271
+ this.keyType = this.keyObject.asymmetricKeyType;
272
+ } catch {
273
+ throw new Error(
274
+ "Invalid private key. Please provide a valid RSA or ED25519 private key."
275
+ );
276
+ }
277
+ return;
278
+ }
279
+ throw new Error("Either 'apiSecret' or 'privateKey' must be provided for signed requests.");
280
+ }
281
+ sign(queryParams) {
282
+ const params = buildQueryString(queryParams);
283
+ if (this.apiSecret)
284
+ return crypto.createHmac("sha256", this.apiSecret).update(params).digest("hex");
285
+ if (this.keyObject && this.keyType) {
286
+ const data = Buffer.from(params);
287
+ if (this.keyType === "rsa")
288
+ return crypto.sign("RSA-SHA256", data, this.keyObject).toString("base64");
289
+ if (this.keyType === "ed25519")
290
+ return crypto.sign(null, data, this.keyObject).toString("base64");
291
+ throw new Error("Unsupported private key type. Must be RSA or ED25519.");
292
+ }
293
+ throw new Error("Signer is not properly initialized.");
294
+ }
295
+ };
296
+ var clearSignerCache = function() {
297
+ signerCache = /* @__PURE__ */ new WeakMap();
298
+ };
252
299
  function buildQueryString(params) {
253
300
  if (!params) return "";
254
301
  return Object.entries(params).map(stringifyKeyValuePair).join("&");
@@ -275,39 +322,12 @@ function getTimestamp() {
275
322
  return Date.now();
276
323
  }
277
324
  var getSignature = function(configuration, queryParams) {
278
- const params = buildQueryString(queryParams);
279
- let signature = "";
280
- if (configuration?.apiSecret && !configuration?.privateKey) {
281
- signature = crypto.createHmac("sha256", configuration.apiSecret).update(params).digest("hex");
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.");
325
+ let signer = signerCache.get(configuration);
326
+ if (!signer) {
327
+ signer = new RequestSigner(configuration);
328
+ signerCache.set(configuration, signer);
309
329
  }
310
- return signature;
330
+ return signer.sign(queryParams);
311
331
  };
312
332
  var assertParamExists = function(functionName, paramName, paramValue) {
313
333
  if (paramValue === null || paramValue === void 0) {
@@ -319,25 +339,26 @@ var assertParamExists = function(functionName, paramName, paramValue) {
319
339
  };
320
340
  function setFlattenedQueryParams(urlSearchParams, parameter, key = "") {
321
341
  if (parameter == null) return;
342
+ if (Array.isArray(parameter)) {
343
+ if (key)
344
+ urlSearchParams.set(key, JSON.stringify(parameter));
345
+ else
346
+ for (const item of parameter) {
347
+ setFlattenedQueryParams(urlSearchParams, item, "");
348
+ }
349
+ return;
350
+ }
322
351
  if (typeof parameter === "object") {
323
- if (Array.isArray(parameter)) {
324
- parameter.forEach((item) => setFlattenedQueryParams(urlSearchParams, item, key));
325
- } else {
326
- Object.keys(parameter).forEach(
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));
352
+ for (const subKey of Object.keys(parameter)) {
353
+ const subVal = parameter[subKey];
354
+ const newKey = key ? `${key}.${subKey}` : subKey;
355
+ setFlattenedQueryParams(urlSearchParams, subVal, newKey);
339
356
  }
357
+ return;
340
358
  }
359
+ const str = String(parameter);
360
+ if (urlSearchParams.has(key)) urlSearchParams.append(key, str);
361
+ else urlSearchParams.set(key, str);
341
362
  }
342
363
  var setSearchParams = function(url, ...objects) {
343
364
  const searchParams = new URLSearchParams(url.search);
@@ -359,18 +380,13 @@ var httpRequestFunction = async function(axiosArgs, configuration) {
359
380
  ...axiosArgs.options,
360
381
  url: (globalAxios.defaults?.baseURL ? "" : configuration?.basePath ?? "") + axiosArgs.url
361
382
  };
362
- if (configuration?.keepAlive) {
363
- axiosRequestArgs.httpsAgent = new https.Agent({
364
- ...configuration?.baseOptions?.httpsAgent instanceof https.Agent ? configuration.baseOptions.httpsAgent.options : {},
365
- keepAlive: true
366
- });
367
- }
368
- if (configuration?.compression) {
383
+ if (configuration?.keepAlive && !configuration?.baseOptions?.httpsAgent)
384
+ axiosRequestArgs.httpsAgent = new https.Agent({ keepAlive: true });
385
+ if (configuration?.compression)
369
386
  axiosRequestArgs.headers = {
370
387
  ...axiosRequestArgs.headers,
371
388
  "Accept-Encoding": "gzip, deflate, br"
372
389
  };
373
- }
374
390
  const retries = configuration?.retries ?? 0;
375
391
  const backoff = configuration?.backoff ?? 0;
376
392
  let attempt = 0;
@@ -578,6 +594,9 @@ function replaceWebsocketStreamsPlaceholders(str, variables) {
578
594
  return "";
579
595
  });
580
596
  }
597
+ function buildUserAgent(packageName, packageVersion) {
598
+ return `${packageName}/${packageVersion} (Node.js/${process.version}; ${platform()}; ${arch()})`;
599
+ }
581
600
 
582
601
  // src/websocket.ts
583
602
  import { EventEmitter } from "events";
@@ -846,10 +865,13 @@ var WebsocketCommon = class _WebsocketCommon extends WebsocketEventEmitter {
846
865
  * @returns A new WebSocket client instance.
847
866
  */
848
867
  createWebSocket(url) {
849
- return new WebSocketClient(url, {
868
+ const wsClientOptions = {
850
869
  perMessageDeflate: this.configuration?.compression,
851
870
  agent: this.configuration?.agent
852
- });
871
+ };
872
+ if (this.configuration.userAgent)
873
+ wsClientOptions.headers = { "User-Agent": this.configuration.userAgent };
874
+ return new WebSocketClient(url, wsClientOptions);
853
875
  }
854
876
  /**
855
877
  * Initializes a WebSocket connection.
@@ -1448,6 +1470,8 @@ export {
1448
1470
  WebsocketStreamsBase,
1449
1471
  assertParamExists,
1450
1472
  buildQueryString,
1473
+ buildUserAgent,
1474
+ clearSignerCache,
1451
1475
  createStreamHandler,
1452
1476
  delay,
1453
1477
  getSignature,
@@ -1458,6 +1482,7 @@ export {
1458
1482
  removeEmptyValue,
1459
1483
  replaceWebsocketStreamsPlaceholders,
1460
1484
  sendRequest,
1485
+ setFlattenedQueryParams,
1461
1486
  setSearchParams,
1462
1487
  shouldRetryRequest,
1463
1488
  sortObject,