@yuants/vendor-binance 0.14.7 → 0.14.8

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.
@@ -1,5 +1,5 @@
1
1
  var _a;
2
- import { fetch, selectHTTPProxyIpRoundRobinAsync } from '@yuants/http-services';
2
+ import { acquireProxyBucket, fetch } from '@yuants/http-services';
3
3
  import { GlobalPrometheusRegistry, Terminal } from '@yuants/protocol';
4
4
  import { encodeHex, encodePath, formatTime, HmacSHA256, newError, tokenBucket, } from '@yuants/utils';
5
5
  const MetricBinanceApiUsedWeight = GlobalPrometheusRegistry.gauge('binance_api_used_weight', '');
@@ -33,6 +33,11 @@ export const BINANCE_TOKEN_BUCKET_OPTIONS_BY_ID = {
33
33
  refillInterval: 60000,
34
34
  refillAmount: 1200,
35
35
  },
36
+ 'fapi.binance.comfundingRate': {
37
+ capacity: 500,
38
+ refillInterval: 300000,
39
+ refillAmount: 500,
40
+ },
36
41
  };
37
42
  export const getTokenBucketOptions = (baseKey) => BINANCE_TOKEN_BUCKET_OPTIONS_BY_ID[baseKey];
38
43
  export const spotAPIBucket = tokenBucket('api.binance.com', BINANCE_TOKEN_BUCKET_OPTIONS_BY_ID['api.binance.com']);
@@ -53,12 +58,32 @@ const resolveLocalPublicIp = () => {
53
58
  }
54
59
  return 'public-ip-unknown';
55
60
  };
56
- export const createRequestContext = async () => {
61
+ export const createRequestContext = async (baseKey, weight) => {
57
62
  if (shouldUseHttpProxy) {
58
- const ip = await selectHTTPProxyIpRoundRobinAsync(terminal);
59
- return { ip };
63
+ const { ip, terminalId, bucketKey } = acquireProxyBucket({
64
+ baseKey,
65
+ weight,
66
+ terminal,
67
+ getBucketOptions: (resolvedBaseKey) => {
68
+ const options = getTokenBucketOptions(resolvedBaseKey);
69
+ if (!options) {
70
+ throw newError('E_BUCKET_OPTIONS_CONFLICT', {
71
+ stage: 'acquire',
72
+ reason: 'missing_bucket_options',
73
+ base_key: resolvedBaseKey,
74
+ });
75
+ }
76
+ return options;
77
+ },
78
+ });
79
+ return { ip, terminalId, bucketKey, acquireWeight: 0 };
60
80
  }
61
- return { ip: resolveLocalPublicIp() };
81
+ const ip = resolveLocalPublicIp();
82
+ return {
83
+ ip,
84
+ bucketKey: buildTokenBucketKey(baseKey, ip),
85
+ acquireWeight: weight,
86
+ };
62
87
  };
63
88
  // 每个接口单独进行主动限流控制
64
89
  const mapPathToRetryAfterUntil = {};
@@ -122,11 +147,16 @@ const callApi = async (method, endpoint, params, credential, requestContext) =>
122
147
  }
123
148
  MetricBinanceApiCounter.labels({ path: url.pathname, terminal_id: terminal.terminal_id }).inc();
124
149
  const proxyIp = shouldUseHttpProxy ? requestContext === null || requestContext === void 0 ? void 0 : requestContext.ip : undefined;
150
+ const proxyTerminalId = shouldUseHttpProxy ? requestContext === null || requestContext === void 0 ? void 0 : requestContext.terminalId : undefined;
125
151
  const res = await fetchImpl(url.href, shouldUseHttpProxy
126
152
  ? {
127
153
  method,
128
154
  headers,
129
- labels: proxyIp ? { ip: proxyIp } : undefined,
155
+ labels: proxyIp && proxyTerminalId
156
+ ? { ip: proxyIp, terminal_id: proxyTerminalId }
157
+ : proxyIp
158
+ ? { ip: proxyIp }
159
+ : undefined,
130
160
  terminal,
131
161
  }
132
162
  : {
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { fetch, selectHTTPProxyIpRoundRobinAsync } from '@yuants/http-services';\nimport { GlobalPrometheusRegistry, Terminal } from '@yuants/protocol';\nimport {\n encodeHex,\n encodePath,\n formatTime,\n HmacSHA256,\n newError,\n tokenBucket,\n type TokenBucketOptions,\n} from '@yuants/utils';\n\nconst MetricBinanceApiUsedWeight = GlobalPrometheusRegistry.gauge('binance_api_used_weight', '');\nconst MetricBinanceApiCounter = GlobalPrometheusRegistry.counter('binance_api_request_total', '');\nconst terminal = Terminal.fromNodeEnv();\nconst shouldUseHttpProxy = process.env.USE_HTTP_PROXY === 'true';\nconst fetchImpl = shouldUseHttpProxy ? fetch : globalThis.fetch ?? fetch;\nconst MISSING_PUBLIC_IP_LOG_INTERVAL = 3_600_000;\nconst missingPublicIpLogAtByTerminalId = new Map<string, number>();\n\nif (shouldUseHttpProxy) {\n globalThis.fetch = fetch;\n}\n\ntype HttpMethod = 'GET' | 'POST' | 'DELETE' | 'PUT';\n\ntype RequestParams = Record<string, string | number | boolean | undefined>;\n\nexport interface IRequestContext {\n ip: string;\n}\n\nexport interface ICredential {\n access_key: string;\n secret_key: string;\n}\n\nexport interface IApiError {\n code: number;\n msg: string;\n}\n\nexport const BINANCE_TOKEN_BUCKET_OPTIONS_BY_ID: Record<string, TokenBucketOptions> = {\n 'api.binance.com': {\n capacity: 6000,\n refillInterval: 60_000,\n refillAmount: 6000,\n },\n 'fapi.binance.com': {\n capacity: 2400,\n refillInterval: 60_000,\n refillAmount: 2400,\n },\n 'papi.binance.com': {\n capacity: 6000,\n refillInterval: 60_000,\n refillAmount: 6000,\n },\n 'order/unified/minute': {\n capacity: 1200,\n refillInterval: 60_000,\n refillAmount: 1200,\n },\n};\n\nexport const getTokenBucketOptions = (baseKey: string): TokenBucketOptions | undefined =>\n BINANCE_TOKEN_BUCKET_OPTIONS_BY_ID[baseKey];\n\nexport const spotAPIBucket = tokenBucket(\n 'api.binance.com',\n BINANCE_TOKEN_BUCKET_OPTIONS_BY_ID['api.binance.com'],\n);\n\nexport const futureAPIBucket = tokenBucket(\n 'fapi.binance.com',\n BINANCE_TOKEN_BUCKET_OPTIONS_BY_ID['fapi.binance.com'],\n);\n\nexport const unifiedAPIBucket = tokenBucket(\n 'papi.binance.com',\n BINANCE_TOKEN_BUCKET_OPTIONS_BY_ID['papi.binance.com'],\n);\n\nexport const unifiedOrderAPIBucket = tokenBucket(\n 'order/unified/minute',\n BINANCE_TOKEN_BUCKET_OPTIONS_BY_ID['order/unified/minute'],\n);\n\nexport const buildTokenBucketKey = (baseKey: string, ip: string): string => encodePath([baseKey, ip]);\n\nconst resolveLocalPublicIp = (): string => {\n const ip = terminal.terminalInfo.tags?.public_ip?.trim();\n if (ip) return ip;\n const now = Date.now();\n const lastLoggedAt = missingPublicIpLogAtByTerminalId.get(terminal.terminal_id) ?? 0;\n if (now - lastLoggedAt > MISSING_PUBLIC_IP_LOG_INTERVAL) {\n missingPublicIpLogAtByTerminalId.set(terminal.terminal_id, now);\n console.info(formatTime(Date.now()), 'missing terminal public_ip tag, fallback to public-ip-unknown');\n }\n return 'public-ip-unknown';\n};\n\nexport const createRequestContext = async (): Promise<IRequestContext> => {\n if (shouldUseHttpProxy) {\n const ip = await selectHTTPProxyIpRoundRobinAsync(terminal);\n return { ip };\n }\n return { ip: resolveLocalPublicIp() };\n};\n\n// 每个接口单独进行主动限流控制\nconst mapPathToRetryAfterUntil: Record<string, number> = {};\n\nexport const isApiError = <T>(value: T | IApiError): value is IApiError =>\n typeof (value as IApiError)?.code === 'number' && typeof (value as IApiError)?.msg === 'string';\n\nconst appendParams = (url: URL, params?: RequestParams) => {\n if (!params) return;\n const entries = Object.entries(params).filter(([, value]) => value !== undefined);\n const timestampEntry = entries.find(([key]) => key === 'timestamp');\n const restEntries = entries.filter(([key]) => key !== 'timestamp');\n restEntries\n .sort(([keyA], [keyB]) => keyA.localeCompare(keyB))\n .forEach(([key, value]) => {\n url.searchParams.set(key, String(value));\n });\n if (timestampEntry) {\n url.searchParams.set(timestampEntry[0], String(timestampEntry[1]));\n }\n};\n\nconst callApi = async <T>(\n method: HttpMethod,\n endpoint: string,\n params?: RequestParams,\n credential?: ICredential,\n requestContext?: IRequestContext,\n): Promise<T> => {\n if (shouldUseHttpProxy && !requestContext) {\n throw newError('E_PROXY_TARGET_NOT_FOUND', { reason: 'Missing request context' });\n }\n const url = new URL(endpoint);\n const normalizedParams: RequestParams = { ...params };\n if (credential) {\n if (normalizedParams.recvWindow === undefined) {\n // FYI https://developers.binance.com/docs/derivatives/usds-margined-futures/general-info#timing-security\n normalizedParams.recvWindow = 5000;\n }\n if (normalizedParams.timestamp === undefined) {\n normalizedParams.timestamp = Date.now();\n }\n }\n appendParams(url, normalizedParams);\n\n let headers: Record<string, string> | undefined;\n if (credential) {\n const signData = url.search.slice(1);\n\n const signature = encodeHex(\n await HmacSHA256(new TextEncoder().encode(signData), new TextEncoder().encode(credential.secret_key)),\n );\n url.searchParams.set('signature', signature);\n headers = {\n 'Content-Type': 'application/json;charset=utf-8',\n 'X-MBX-APIKEY': credential.access_key,\n };\n console.info(formatTime(Date.now()), 'request', method, url.host, url.pathname);\n } else {\n console.info(formatTime(Date.now()), 'request', method, url.host, url.pathname);\n }\n\n const retryAfterUntil = mapPathToRetryAfterUntil[endpoint];\n\n if (retryAfterUntil) {\n if (Date.now() <= retryAfterUntil) {\n // 主动限流\n throw newError('ACTIVE_RATE_LIMIT', {\n wait_time: `${retryAfterUntil - Date.now()}ms`,\n retryAfterUntil,\n url: `${url.host}${url.pathname}`,\n });\n }\n delete mapPathToRetryAfterUntil[endpoint];\n }\n\n MetricBinanceApiCounter.labels({ path: url.pathname, terminal_id: terminal.terminal_id }).inc();\n\n const proxyIp = shouldUseHttpProxy ? requestContext?.ip : undefined;\n const res = await fetchImpl(\n url.href,\n shouldUseHttpProxy\n ? {\n method,\n headers,\n labels: proxyIp ? { ip: proxyIp } : undefined,\n terminal,\n }\n : {\n method,\n headers,\n },\n );\n const usedWeight1M = res.headers.get('x-mbx-used-weight-1m');\n const retryAfter = res.headers.get('Retry-After');\n if (retryAfter) {\n mapPathToRetryAfterUntil[endpoint] = Date.now() + parseInt(retryAfter, 10) * 1000;\n }\n console.info(\n formatTime(Date.now()),\n 'response',\n method,\n url.host,\n url.pathname,\n `status=${res.status}`,\n retryAfter ? `retryAfter=${retryAfter}` : '',\n `usedWeight1M=${usedWeight1M ?? 'N/A'}`,\n );\n if (usedWeight1M) {\n MetricBinanceApiUsedWeight.labels({ path: endpoint, terminal_id: terminal.terminal_id }).set(\n +usedWeight1M,\n );\n }\n return res.json() as Promise<T>;\n};\n\nexport const requestPublic = <T>(\n method: HttpMethod,\n endpoint: string,\n params?: RequestParams,\n requestContext?: IRequestContext,\n) => callApi<T>(method, endpoint, params, undefined, requestContext);\n\nexport const requestPrivate = <T>(\n credential: ICredential,\n method: HttpMethod,\n endpoint: string,\n params?: RequestParams,\n requestContext?: IRequestContext,\n) => callApi<T>(method, endpoint, params, credential, requestContext);\n\nexport const getDefaultCredential = (): ICredential => {\n const access_key = process.env.ACCESS_KEY;\n const secret_key = process.env.SECRET_KEY;\n if (!access_key || !secret_key) {\n throw new Error('Missing Binance credential: ACCESS_KEY and SECRET_KEY must be set');\n }\n return { access_key, secret_key };\n};\n"]}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { acquireProxyBucket, fetch } from '@yuants/http-services';\nimport { GlobalPrometheusRegistry, Terminal } from '@yuants/protocol';\nimport {\n encodeHex,\n encodePath,\n formatTime,\n HmacSHA256,\n newError,\n tokenBucket,\n type TokenBucketOptions,\n} from '@yuants/utils';\n\nconst MetricBinanceApiUsedWeight = GlobalPrometheusRegistry.gauge('binance_api_used_weight', '');\nconst MetricBinanceApiCounter = GlobalPrometheusRegistry.counter('binance_api_request_total', '');\nconst terminal = Terminal.fromNodeEnv();\nconst shouldUseHttpProxy = process.env.USE_HTTP_PROXY === 'true';\nconst fetchImpl = shouldUseHttpProxy ? fetch : globalThis.fetch ?? fetch;\nconst MISSING_PUBLIC_IP_LOG_INTERVAL = 3_600_000;\nconst missingPublicIpLogAtByTerminalId = new Map<string, number>();\n\nif (shouldUseHttpProxy) {\n globalThis.fetch = fetch;\n}\n\ntype HttpMethod = 'GET' | 'POST' | 'DELETE' | 'PUT';\n\ntype RequestParams = Record<string, string | number | boolean | undefined>;\n\nexport interface IRequestContext {\n ip: string;\n terminalId?: string;\n bucketKey: string;\n acquireWeight: number;\n}\n\nexport interface ICredential {\n access_key: string;\n secret_key: string;\n}\n\nexport interface IApiError {\n code: number;\n msg: string;\n}\n\nexport const BINANCE_TOKEN_BUCKET_OPTIONS_BY_ID: Record<string, TokenBucketOptions> = {\n 'api.binance.com': {\n capacity: 6000,\n refillInterval: 60_000,\n refillAmount: 6000,\n },\n 'fapi.binance.com': {\n capacity: 2400,\n refillInterval: 60_000,\n refillAmount: 2400,\n },\n 'papi.binance.com': {\n capacity: 6000,\n refillInterval: 60_000,\n refillAmount: 6000,\n },\n 'order/unified/minute': {\n capacity: 1200,\n refillInterval: 60_000,\n refillAmount: 1200,\n },\n 'fapi.binance.comfundingRate': {\n capacity: 500,\n refillInterval: 300_000,\n refillAmount: 500,\n },\n};\n\nexport const getTokenBucketOptions = (baseKey: string): TokenBucketOptions | undefined =>\n BINANCE_TOKEN_BUCKET_OPTIONS_BY_ID[baseKey];\n\nexport const spotAPIBucket = tokenBucket(\n 'api.binance.com',\n BINANCE_TOKEN_BUCKET_OPTIONS_BY_ID['api.binance.com'],\n);\n\nexport const futureAPIBucket = tokenBucket(\n 'fapi.binance.com',\n BINANCE_TOKEN_BUCKET_OPTIONS_BY_ID['fapi.binance.com'],\n);\n\nexport const unifiedAPIBucket = tokenBucket(\n 'papi.binance.com',\n BINANCE_TOKEN_BUCKET_OPTIONS_BY_ID['papi.binance.com'],\n);\n\nexport const unifiedOrderAPIBucket = tokenBucket(\n 'order/unified/minute',\n BINANCE_TOKEN_BUCKET_OPTIONS_BY_ID['order/unified/minute'],\n);\n\nexport const buildTokenBucketKey = (baseKey: string, ip: string): string => encodePath([baseKey, ip]);\n\nconst resolveLocalPublicIp = (): string => {\n const ip = terminal.terminalInfo.tags?.public_ip?.trim();\n if (ip) return ip;\n const now = Date.now();\n const lastLoggedAt = missingPublicIpLogAtByTerminalId.get(terminal.terminal_id) ?? 0;\n if (now - lastLoggedAt > MISSING_PUBLIC_IP_LOG_INTERVAL) {\n missingPublicIpLogAtByTerminalId.set(terminal.terminal_id, now);\n console.info(formatTime(Date.now()), 'missing terminal public_ip tag, fallback to public-ip-unknown');\n }\n return 'public-ip-unknown';\n};\n\nexport const createRequestContext = async (baseKey: string, weight: number): Promise<IRequestContext> => {\n if (shouldUseHttpProxy) {\n const { ip, terminalId, bucketKey } = acquireProxyBucket({\n baseKey,\n weight,\n terminal,\n getBucketOptions: (resolvedBaseKey) => {\n const options = getTokenBucketOptions(resolvedBaseKey);\n if (!options) {\n throw newError('E_BUCKET_OPTIONS_CONFLICT', {\n stage: 'acquire',\n reason: 'missing_bucket_options',\n base_key: resolvedBaseKey,\n });\n }\n return options;\n },\n });\n return { ip, terminalId, bucketKey, acquireWeight: 0 };\n }\n const ip = resolveLocalPublicIp();\n return {\n ip,\n bucketKey: buildTokenBucketKey(baseKey, ip),\n acquireWeight: weight,\n };\n};\n\n// 每个接口单独进行主动限流控制\nconst mapPathToRetryAfterUntil: Record<string, number> = {};\n\nexport const isApiError = <T>(value: T | IApiError): value is IApiError =>\n typeof (value as IApiError)?.code === 'number' && typeof (value as IApiError)?.msg === 'string';\n\nconst appendParams = (url: URL, params?: RequestParams) => {\n if (!params) return;\n const entries = Object.entries(params).filter(([, value]) => value !== undefined);\n const timestampEntry = entries.find(([key]) => key === 'timestamp');\n const restEntries = entries.filter(([key]) => key !== 'timestamp');\n restEntries\n .sort(([keyA], [keyB]) => keyA.localeCompare(keyB))\n .forEach(([key, value]) => {\n url.searchParams.set(key, String(value));\n });\n if (timestampEntry) {\n url.searchParams.set(timestampEntry[0], String(timestampEntry[1]));\n }\n};\n\nconst callApi = async <T>(\n method: HttpMethod,\n endpoint: string,\n params?: RequestParams,\n credential?: ICredential,\n requestContext?: IRequestContext,\n): Promise<T> => {\n if (shouldUseHttpProxy && !requestContext) {\n throw newError('E_PROXY_TARGET_NOT_FOUND', { reason: 'Missing request context' });\n }\n const url = new URL(endpoint);\n const normalizedParams: RequestParams = { ...params };\n if (credential) {\n if (normalizedParams.recvWindow === undefined) {\n // FYI https://developers.binance.com/docs/derivatives/usds-margined-futures/general-info#timing-security\n normalizedParams.recvWindow = 5000;\n }\n if (normalizedParams.timestamp === undefined) {\n normalizedParams.timestamp = Date.now();\n }\n }\n appendParams(url, normalizedParams);\n\n let headers: Record<string, string> | undefined;\n if (credential) {\n const signData = url.search.slice(1);\n\n const signature = encodeHex(\n await HmacSHA256(new TextEncoder().encode(signData), new TextEncoder().encode(credential.secret_key)),\n );\n url.searchParams.set('signature', signature);\n headers = {\n 'Content-Type': 'application/json;charset=utf-8',\n 'X-MBX-APIKEY': credential.access_key,\n };\n console.info(formatTime(Date.now()), 'request', method, url.host, url.pathname);\n } else {\n console.info(formatTime(Date.now()), 'request', method, url.host, url.pathname);\n }\n\n const retryAfterUntil = mapPathToRetryAfterUntil[endpoint];\n\n if (retryAfterUntil) {\n if (Date.now() <= retryAfterUntil) {\n // 主动限流\n throw newError('ACTIVE_RATE_LIMIT', {\n wait_time: `${retryAfterUntil - Date.now()}ms`,\n retryAfterUntil,\n url: `${url.host}${url.pathname}`,\n });\n }\n delete mapPathToRetryAfterUntil[endpoint];\n }\n\n MetricBinanceApiCounter.labels({ path: url.pathname, terminal_id: terminal.terminal_id }).inc();\n\n const proxyIp = shouldUseHttpProxy ? requestContext?.ip : undefined;\n const proxyTerminalId = shouldUseHttpProxy ? requestContext?.terminalId : undefined;\n const res = await fetchImpl(\n url.href,\n shouldUseHttpProxy\n ? {\n method,\n headers,\n labels:\n proxyIp && proxyTerminalId\n ? { ip: proxyIp, terminal_id: proxyTerminalId }\n : proxyIp\n ? { ip: proxyIp }\n : undefined,\n terminal,\n }\n : {\n method,\n headers,\n },\n );\n const usedWeight1M = res.headers.get('x-mbx-used-weight-1m');\n const retryAfter = res.headers.get('Retry-After');\n if (retryAfter) {\n mapPathToRetryAfterUntil[endpoint] = Date.now() + parseInt(retryAfter, 10) * 1000;\n }\n console.info(\n formatTime(Date.now()),\n 'response',\n method,\n url.host,\n url.pathname,\n `status=${res.status}`,\n retryAfter ? `retryAfter=${retryAfter}` : '',\n `usedWeight1M=${usedWeight1M ?? 'N/A'}`,\n );\n if (usedWeight1M) {\n MetricBinanceApiUsedWeight.labels({ path: endpoint, terminal_id: terminal.terminal_id }).set(\n +usedWeight1M,\n );\n }\n return res.json() as Promise<T>;\n};\n\nexport const requestPublic = <T>(\n method: HttpMethod,\n endpoint: string,\n params?: RequestParams,\n requestContext?: IRequestContext,\n) => callApi<T>(method, endpoint, params, undefined, requestContext);\n\nexport const requestPrivate = <T>(\n credential: ICredential,\n method: HttpMethod,\n endpoint: string,\n params?: RequestParams,\n requestContext?: IRequestContext,\n) => callApi<T>(method, endpoint, params, credential, requestContext);\n\nexport const getDefaultCredential = (): ICredential => {\n const access_key = process.env.ACCESS_KEY;\n const secret_key = process.env.SECRET_KEY;\n if (!access_key || !secret_key) {\n throw new Error('Missing Binance credential: ACCESS_KEY and SECRET_KEY must be set');\n }\n return { access_key, secret_key };\n};\n"]}
@@ -1,5 +1,5 @@
1
1
  import { scopeError, tokenBucket } from '@yuants/utils';
2
- import { buildTokenBucketKey, createRequestContext, getDefaultCredential, getTokenBucketOptions, requestPrivate, } from './client';
2
+ import { createRequestContext, getDefaultCredential, getTokenBucketOptions, requestPrivate, } from './client';
3
3
  /**
4
4
  * 查询账户信息(USER_DATA)
5
5
  *
@@ -13,9 +13,9 @@ export const getUnifiedAccountInfo = async (credential) => {
13
13
  const endpoint = 'https://papi.binance.com/papi/v1/account';
14
14
  const url = new URL(endpoint);
15
15
  const weight = 20;
16
- const requestContext = await createRequestContext();
17
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
18
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions('order/unified/minute')).acquireSync(weight));
16
+ const requestContext = await createRequestContext('order/unified/minute', weight);
17
+ const bucketKey = requestContext.bucketKey;
18
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions('order/unified/minute')).acquireSync(requestContext.acquireWeight));
19
19
  return requestPrivate(credential, 'GET', endpoint, undefined, requestContext);
20
20
  };
21
21
  /**
@@ -31,9 +31,9 @@ export const getUnifiedUmAccount = async (credential) => {
31
31
  const endpoint = 'https://papi.binance.com/papi/v1/um/account';
32
32
  const url = new URL(endpoint);
33
33
  const weight = 5;
34
- const requestContext = await createRequestContext();
35
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
36
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions('order/unified/minute')).acquireSync(weight));
34
+ const requestContext = await createRequestContext('order/unified/minute', weight);
35
+ const bucketKey = requestContext.bucketKey;
36
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions('order/unified/minute')).acquireSync(requestContext.acquireWeight));
37
37
  return requestPrivate(credential, 'GET', endpoint, undefined, requestContext);
38
38
  };
39
39
  /**
@@ -49,8 +49,8 @@ export const getUnifiedUmOpenOrders = async (credential, params) => {
49
49
  const endpoint = 'https://papi.binance.com/papi/v1/um/openOrders';
50
50
  const url = new URL(endpoint);
51
51
  const weight = (params === null || params === void 0 ? void 0 : params.symbol) ? 1 : 40;
52
- const requestContext = await createRequestContext();
53
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
52
+ const requestContext = await createRequestContext(url.host, weight);
53
+ const bucketKey = requestContext.bucketKey;
54
54
  scopeError('BINANCE_API_RATE_LIMIT', {
55
55
  method: 'GET',
56
56
  endpoint,
@@ -59,7 +59,7 @@ export const getUnifiedUmOpenOrders = async (credential, params) => {
59
59
  bucketId: bucketKey,
60
60
  weight,
61
61
  hasSymbol: !!(params === null || params === void 0 ? void 0 : params.symbol),
62
- }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
62
+ }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
63
63
  return requestPrivate(credential, 'GET', endpoint, params, requestContext);
64
64
  };
65
65
  /**
@@ -75,9 +75,9 @@ export const getUnifiedAccountBalance = async (credential, params) => {
75
75
  const endpoint = 'https://papi.binance.com/papi/v1/balance';
76
76
  const url = new URL(endpoint);
77
77
  const weight = 20;
78
- const requestContext = await createRequestContext();
79
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
80
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
78
+ const requestContext = await createRequestContext(url.host, weight);
79
+ const bucketKey = requestContext.bucketKey;
80
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
81
81
  return requestPrivate(credential, 'GET', endpoint, params, requestContext);
82
82
  };
83
83
  /**
@@ -91,9 +91,9 @@ export const getSpotAccountInfo = async (credential, params) => {
91
91
  const endpoint = 'https://api.binance.com/api/v3/account';
92
92
  const url = new URL(endpoint);
93
93
  const weight = 20;
94
- const requestContext = await createRequestContext();
95
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
96
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
94
+ const requestContext = await createRequestContext(url.host, weight);
95
+ const bucketKey = requestContext.bucketKey;
96
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
97
97
  return requestPrivate(credential, 'GET', endpoint, params, requestContext);
98
98
  };
99
99
  /**
@@ -107,8 +107,8 @@ export const getSpotOpenOrders = async (credential, params) => {
107
107
  const endpoint = 'https://api.binance.com/api/v3/openOrders';
108
108
  const url = new URL(endpoint);
109
109
  const weight = (params === null || params === void 0 ? void 0 : params.symbol) ? 6 : 80;
110
- const requestContext = await createRequestContext();
111
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
110
+ const requestContext = await createRequestContext(url.host, weight);
111
+ const bucketKey = requestContext.bucketKey;
112
112
  scopeError('BINANCE_API_RATE_LIMIT', {
113
113
  method: 'GET',
114
114
  endpoint,
@@ -117,7 +117,7 @@ export const getSpotOpenOrders = async (credential, params) => {
117
117
  bucketId: bucketKey,
118
118
  weight,
119
119
  hasSymbol: !!(params === null || params === void 0 ? void 0 : params.symbol),
120
- }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
120
+ }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
121
121
  return requestPrivate(credential, 'GET', endpoint, params, requestContext);
122
122
  };
123
123
  /**
@@ -131,9 +131,9 @@ export const postSpotOrder = async (credential, params) => {
131
131
  const endpoint = 'https://api.binance.com/api/v3/order';
132
132
  const url = new URL(endpoint);
133
133
  const weight = 1;
134
- const requestContext = await createRequestContext();
135
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
136
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'POST', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
134
+ const requestContext = await createRequestContext(url.host, weight);
135
+ const bucketKey = requestContext.bucketKey;
136
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'POST', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
137
137
  return requestPrivate(credential, 'POST', endpoint, params, requestContext);
138
138
  };
139
139
  /**
@@ -147,9 +147,9 @@ export const deleteSpotOrder = async (credential, params) => {
147
147
  const endpoint = 'https://api.binance.com/api/v3/order';
148
148
  const url = new URL(endpoint);
149
149
  const weight = 1;
150
- const requestContext = await createRequestContext();
151
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
152
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'DELETE', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
150
+ const requestContext = await createRequestContext(url.host, weight);
151
+ const bucketKey = requestContext.bucketKey;
152
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'DELETE', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
153
153
  return requestPrivate(credential, 'DELETE', endpoint, params, requestContext);
154
154
  };
155
155
  /**
@@ -167,9 +167,9 @@ export const postAssetTransfer = async (credential, params) => {
167
167
  const endpoint = 'https://api.binance.com/sapi/v1/asset/transfer';
168
168
  const url = new URL(endpoint);
169
169
  const weight = 900;
170
- const requestContext = await createRequestContext();
171
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
172
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'POST', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
170
+ const requestContext = await createRequestContext(url.host, weight);
171
+ const bucketKey = requestContext.bucketKey;
172
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'POST', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
173
173
  return requestPrivate(credential, 'POST', endpoint, params, requestContext);
174
174
  };
175
175
  /**
@@ -187,9 +187,9 @@ export const postUnifiedAccountAutoCollection = async (credential) => {
187
187
  const endpoint = 'https://papi.binance.com/papi/v1/auto-collection';
188
188
  const url = new URL(endpoint);
189
189
  const weight = 750;
190
- const requestContext = await createRequestContext();
191
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
192
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'POST', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
190
+ const requestContext = await createRequestContext(url.host, weight);
191
+ const bucketKey = requestContext.bucketKey;
192
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'POST', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
193
193
  return requestPrivate(credential, 'POST', endpoint, undefined, requestContext);
194
194
  };
195
195
  /**
@@ -205,9 +205,9 @@ export const getDepositAddress = async (credential, params) => {
205
205
  const endpoint = 'https://api.binance.com/sapi/v1/capital/deposit/address';
206
206
  const url = new URL(endpoint);
207
207
  const weight = 10;
208
- const requestContext = await createRequestContext();
209
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
210
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
208
+ const requestContext = await createRequestContext(url.host, weight);
209
+ const bucketKey = requestContext.bucketKey;
210
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
211
211
  return requestPrivate(credential, 'GET', endpoint, params, requestContext);
212
212
  };
213
213
  /**
@@ -221,9 +221,9 @@ export const getSubAccountList = async (credential, params) => {
221
221
  const endpoint = 'https://api.binance.com/sapi/v1/sub-account/list';
222
222
  const url = new URL(endpoint);
223
223
  const weight = 1;
224
- const requestContext = await createRequestContext();
225
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
226
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
224
+ const requestContext = await createRequestContext(url.host, weight);
225
+ const bucketKey = requestContext.bucketKey;
226
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
227
227
  return requestPrivate(credential, 'GET', endpoint, params, requestContext);
228
228
  };
229
229
  /**
@@ -237,9 +237,9 @@ export const postWithdraw = async (credential, params) => {
237
237
  const endpoint = 'https://api.binance.com/sapi/v1/capital/withdraw/apply';
238
238
  const url = new URL(endpoint);
239
239
  const weight = 600;
240
- const requestContext = await createRequestContext();
241
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
242
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'POST', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
240
+ const requestContext = await createRequestContext(url.host, weight);
241
+ const bucketKey = requestContext.bucketKey;
242
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'POST', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
243
243
  return requestPrivate(credential, 'POST', endpoint, params, requestContext);
244
244
  };
245
245
  /**
@@ -258,9 +258,9 @@ export const getWithdrawHistory = async (credential, params) => {
258
258
  const endpoint = 'https://api.binance.com/sapi/v1/capital/withdraw/history';
259
259
  const url = new URL(endpoint);
260
260
  const weight = 1;
261
- const requestContext = await createRequestContext();
262
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
263
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
261
+ const requestContext = await createRequestContext(url.host, weight);
262
+ const bucketKey = requestContext.bucketKey;
263
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
264
264
  return requestPrivate(credential, 'GET', endpoint, params, requestContext);
265
265
  };
266
266
  /**
@@ -274,9 +274,9 @@ export const getDepositHistory = async (credential, params) => {
274
274
  const endpoint = 'https://api.binance.com/sapi/v1/capital/deposit/hisrec';
275
275
  const url = new URL(endpoint);
276
276
  const weight = 1;
277
- const requestContext = await createRequestContext();
278
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
279
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
277
+ const requestContext = await createRequestContext(url.host, weight);
278
+ const bucketKey = requestContext.bucketKey;
279
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
280
280
  return requestPrivate(credential, 'GET', endpoint, params, requestContext);
281
281
  };
282
282
  /**
@@ -290,18 +290,18 @@ export const postUmOrder = async (credential, params) => {
290
290
  const endpoint = 'https://papi.binance.com/papi/v1/um/order';
291
291
  const url = new URL(endpoint);
292
292
  const weight = 1;
293
- const requestContext = await createRequestContext();
294
- const bucketKey = buildTokenBucketKey('order/unified/minute', requestContext.ip);
295
- scopeError('BINANCE_UNIFIED_ORDER_API_RATE_LIMIT', { method: 'POST', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
293
+ const requestContext = await createRequestContext('order/unified/minute', weight);
294
+ const bucketKey = requestContext.bucketKey;
295
+ scopeError('BINANCE_UNIFIED_ORDER_API_RATE_LIMIT', { method: 'POST', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
296
296
  return requestPrivate(credential, 'POST', endpoint, params, requestContext);
297
297
  };
298
298
  export const deleteUmOrder = async (credential, params) => {
299
299
  const endpoint = 'https://papi.binance.com/papi/v1/um/order';
300
300
  const url = new URL(endpoint);
301
301
  const weight = 1;
302
- const requestContext = await createRequestContext();
303
- const bucketKey = buildTokenBucketKey('order/unified/minute', requestContext.ip);
304
- scopeError('BINANCE_UNIFIED_ORDER_API_RATE_LIMIT', { method: 'DELETE', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
302
+ const requestContext = await createRequestContext('order/unified/minute', weight);
303
+ const bucketKey = requestContext.bucketKey;
304
+ scopeError('BINANCE_UNIFIED_ORDER_API_RATE_LIMIT', { method: 'DELETE', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
305
305
  return requestPrivate(credential, 'DELETE', endpoint, params, requestContext);
306
306
  };
307
307
  /**
@@ -315,9 +315,9 @@ export const getUMIncome = async (credential, params) => {
315
315
  const endpoint = 'https://papi.binance.com/papi/v1/um/income';
316
316
  const url = new URL(endpoint);
317
317
  const weight = 30;
318
- const requestContext = await createRequestContext();
319
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
320
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
318
+ const requestContext = await createRequestContext(url.host, weight);
319
+ const bucketKey = requestContext.bucketKey;
320
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
321
321
  return requestPrivate(credential, 'GET', endpoint, params, requestContext);
322
322
  };
323
323
  /**
@@ -331,9 +331,9 @@ export const getAccountIncome = async (credential, params) => {
331
331
  const endpoint = 'https://fapi.binance.com/fapi/v1/income';
332
332
  const url = new URL(endpoint);
333
333
  const weight = 30;
334
- const requestContext = await createRequestContext();
335
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
336
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
334
+ const requestContext = await createRequestContext(url.host, weight);
335
+ const bucketKey = requestContext.bucketKey;
336
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
337
337
  return requestPrivate(credential, 'GET', endpoint, params, requestContext);
338
338
  };
339
339
  /**
@@ -347,9 +347,9 @@ export const postSpotOrderCancelReplace = async (credential, params) => {
347
347
  const endpoint = 'https://api.binance.com/api/v3/order/cancelReplace';
348
348
  const url = new URL(endpoint);
349
349
  const weight = 1;
350
- const requestContext = await createRequestContext();
351
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
352
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'POST', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
350
+ const requestContext = await createRequestContext(url.host, weight);
351
+ const bucketKey = requestContext.bucketKey;
352
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'POST', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
353
353
  return requestPrivate(credential, 'POST', endpoint, params, requestContext);
354
354
  };
355
355
  /**
@@ -363,9 +363,9 @@ export const putUmOrder = async (credential, params) => {
363
363
  const endpoint = 'https://papi.binance.com/papi/v1/um/order';
364
364
  const url = new URL(endpoint);
365
365
  const weight = 1;
366
- const requestContext = await createRequestContext();
367
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
368
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'PUT', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
366
+ const requestContext = await createRequestContext(url.host, weight);
367
+ const bucketKey = requestContext.bucketKey;
368
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'PUT', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
369
369
  return requestPrivate(credential, 'PUT', endpoint, params, requestContext);
370
370
  };
371
371
  /**
@@ -380,9 +380,9 @@ export const getMarginAllPairs = async (params) => {
380
380
  const endpoint = 'https://api.binance.com/sapi/v1/margin/allPairs';
381
381
  const url = new URL(endpoint);
382
382
  const weight = 1;
383
- const requestContext = await createRequestContext();
384
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
385
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
383
+ const requestContext = await createRequestContext(url.host, weight);
384
+ const bucketKey = requestContext.bucketKey;
385
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
386
386
  return requestPrivate(credential, 'GET', endpoint, params, requestContext);
387
387
  };
388
388
  /**
@@ -395,9 +395,9 @@ export const getMarginNextHourlyInterestRate = async (params) => {
395
395
  const endpoint = 'https://api.binance.com/sapi/v1/margin/next-hourly-interest-rate';
396
396
  const url = new URL(endpoint);
397
397
  const weight = 1;
398
- const requestContext = await createRequestContext();
399
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
400
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
398
+ const requestContext = await createRequestContext(url.host, weight);
399
+ const bucketKey = requestContext.bucketKey;
400
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
401
401
  return requestPrivate(credential, 'GET', endpoint, params, requestContext);
402
402
  };
403
403
  /**
@@ -410,9 +410,9 @@ export const getMarginInterestRateHistory = async (params) => {
410
410
  const endpoint = 'https://api.binance.com/sapi/v1/margin/interestRateHistory';
411
411
  const url = new URL(endpoint);
412
412
  const weight = 1;
413
- const requestContext = await createRequestContext();
414
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
415
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
413
+ const requestContext = await createRequestContext(url.host, weight);
414
+ const bucketKey = requestContext.bucketKey;
415
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
416
416
  return requestPrivate(credential, 'GET', endpoint, params, requestContext);
417
417
  };
418
418
  /**
@@ -426,9 +426,9 @@ export const getUserAsset = async (credential, params) => {
426
426
  const endpoint = 'https://api.binance.com/sapi/v3/asset/getUserAsset';
427
427
  const url = new URL(endpoint);
428
428
  const weight = 1;
429
- const requestContext = await createRequestContext();
430
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
431
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'POST', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
429
+ const requestContext = await createRequestContext(url.host, weight);
430
+ const bucketKey = requestContext.bucketKey;
431
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'POST', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
432
432
  return requestPrivate(credential, 'POST', endpoint, params, requestContext);
433
433
  };
434
434
  /**
@@ -442,9 +442,9 @@ export const getFundingAsset = async (credential, params) => {
442
442
  const endpoint = 'https://api.binance.com/sapi/v1/asset/get-funding-asset';
443
443
  const url = new URL(endpoint);
444
444
  const weight = 1;
445
- const requestContext = await createRequestContext();
446
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
447
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'POST', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
445
+ const requestContext = await createRequestContext(url.host, weight);
446
+ const bucketKey = requestContext.bucketKey;
447
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'POST', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
448
448
  return requestPrivate(credential, 'POST', endpoint, params, requestContext);
449
449
  };
450
450
  /**
@@ -458,9 +458,9 @@ export const getUmAccountTradeList = async (credential, params) => {
458
458
  const endpoint = 'https://papi.binance.com/papi/v1/um/userTrades';
459
459
  const url = new URL(endpoint);
460
460
  const weight = 5;
461
- const requestContext = await createRequestContext();
462
- const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
463
- scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(weight));
461
+ const requestContext = await createRequestContext(url.host, weight);
462
+ const bucketKey = requestContext.bucketKey;
463
+ scopeError('BINANCE_API_RATE_LIMIT', { method: 'GET', endpoint, host: url.host, path: url.pathname, bucketId: bucketKey, weight }, () => tokenBucket(bucketKey, getTokenBucketOptions(url.host)).acquireSync(requestContext.acquireWeight));
464
464
  return requestPrivate(credential, 'GET', endpoint, params, requestContext);
465
465
  };
466
466
  //# sourceMappingURL=private-api.js.map