@yuants/vendor-binance 0.14.3 → 0.14.4
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/api/client.js +46 -9
- package/dist/api/client.js.map +1 -1
- package/dist/api/private-api.js +111 -57
- package/dist/api/private-api.js.map +1 -1
- package/dist/api/public-api.js +40 -22
- package/dist/api/public-api.js.map +1 -1
- package/lib/api/client.d.ts +7 -2
- package/lib/api/client.d.ts.map +1 -1
- package/lib/api/client.js +47 -8
- package/lib/api/client.js.map +1 -1
- package/lib/api/private-api.d.ts.map +1 -1
- package/lib/api/private-api.js +110 -56
- package/lib/api/private-api.js.map +1 -1
- package/lib/api/public-api.d.ts.map +1 -1
- package/lib/api/public-api.js +39 -21
- package/lib/api/public-api.js.map +1 -1
- package/package.json +6 -6
- package/temp/build/typescript/ts_tQj2bmGB.json +1 -1
- package/temp/package-deps.json +8 -8
- package/temp/test/jest/haste-map-f37bc94525b36254e573de220443d250-dc922b21f2d35e7315abf4c3159e25a5-63b40dbcff306581344a73f9073894a1 +0 -0
package/dist/api/client.js
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
var _a;
|
|
2
|
-
import { fetch } from '@yuants/http-services';
|
|
2
|
+
import { fetch, selectHTTPProxyIpRoundRobin } from '@yuants/http-services';
|
|
3
3
|
import { GlobalPrometheusRegistry, Terminal } from '@yuants/protocol';
|
|
4
|
-
import { encodeHex, formatTime, HmacSHA256, newError, tokenBucket } from '@yuants/utils';
|
|
4
|
+
import { encodeHex, encodePath, formatTime, HmacSHA256, newError, tokenBucket } from '@yuants/utils';
|
|
5
5
|
const MetricBinanceApiUsedWeight = GlobalPrometheusRegistry.gauge('binance_api_used_weight', '');
|
|
6
6
|
const MetricBinanceApiCounter = GlobalPrometheusRegistry.counter('binance_api_request_total', '');
|
|
7
7
|
const terminal = Terminal.fromNodeEnv();
|
|
8
8
|
const shouldUseHttpProxy = process.env.USE_HTTP_PROXY === 'true';
|
|
9
9
|
const fetchImpl = shouldUseHttpProxy ? fetch : (_a = globalThis.fetch) !== null && _a !== void 0 ? _a : fetch;
|
|
10
|
+
const MISSING_PUBLIC_IP_LOG_INTERVAL = 3600000;
|
|
11
|
+
const missingPublicIpLogAtByTerminalId = new Map();
|
|
10
12
|
if (shouldUseHttpProxy) {
|
|
11
13
|
globalThis.fetch = fetch;
|
|
12
14
|
}
|
|
@@ -30,6 +32,27 @@ export const unifiedOrderAPIBucket = tokenBucket('order/unified/minute', {
|
|
|
30
32
|
refillInterval: 60000,
|
|
31
33
|
refillAmount: 1200,
|
|
32
34
|
});
|
|
35
|
+
export const buildTokenBucketKey = (baseKey, ip) => encodePath([baseKey, ip]);
|
|
36
|
+
const resolveLocalPublicIp = () => {
|
|
37
|
+
var _a, _b, _c;
|
|
38
|
+
const ip = (_b = (_a = terminal.terminalInfo.tags) === null || _a === void 0 ? void 0 : _a.public_ip) === null || _b === void 0 ? void 0 : _b.trim();
|
|
39
|
+
if (ip)
|
|
40
|
+
return ip;
|
|
41
|
+
const now = Date.now();
|
|
42
|
+
const lastLoggedAt = (_c = missingPublicIpLogAtByTerminalId.get(terminal.terminal_id)) !== null && _c !== void 0 ? _c : 0;
|
|
43
|
+
if (now - lastLoggedAt > MISSING_PUBLIC_IP_LOG_INTERVAL) {
|
|
44
|
+
missingPublicIpLogAtByTerminalId.set(terminal.terminal_id, now);
|
|
45
|
+
console.info(formatTime(Date.now()), 'missing terminal public_ip tag, fallback to public-ip-unknown');
|
|
46
|
+
}
|
|
47
|
+
return 'public-ip-unknown';
|
|
48
|
+
};
|
|
49
|
+
export const createRequestContext = () => {
|
|
50
|
+
if (shouldUseHttpProxy) {
|
|
51
|
+
const ip = selectHTTPProxyIpRoundRobin(terminal);
|
|
52
|
+
return { ip };
|
|
53
|
+
}
|
|
54
|
+
return { ip: resolveLocalPublicIp() };
|
|
55
|
+
};
|
|
33
56
|
// 每个接口单独进行主动限流控制
|
|
34
57
|
const mapPathToRetryAfterUntil = {};
|
|
35
58
|
export const isApiError = (value) => typeof (value === null || value === void 0 ? void 0 : value.code) === 'number' && typeof (value === null || value === void 0 ? void 0 : value.msg) === 'string';
|
|
@@ -48,7 +71,11 @@ const appendParams = (url, params) => {
|
|
|
48
71
|
url.searchParams.set(timestampEntry[0], String(timestampEntry[1]));
|
|
49
72
|
}
|
|
50
73
|
};
|
|
51
|
-
const callApi = async (method, endpoint, params, credential) => {
|
|
74
|
+
const callApi = async (method, endpoint, params, credential, requestContext) => {
|
|
75
|
+
var _a;
|
|
76
|
+
if (shouldUseHttpProxy && !requestContext) {
|
|
77
|
+
throw newError('E_PROXY_TARGET_NOT_FOUND', { reason: 'Missing request context' });
|
|
78
|
+
}
|
|
52
79
|
const url = new URL(endpoint);
|
|
53
80
|
const normalizedParams = Object.assign({}, params);
|
|
54
81
|
if (credential) {
|
|
@@ -88,10 +115,20 @@ const callApi = async (method, endpoint, params, credential) => {
|
|
|
88
115
|
delete mapPathToRetryAfterUntil[endpoint];
|
|
89
116
|
}
|
|
90
117
|
MetricBinanceApiCounter.labels({ path: url.pathname, terminal_id: terminal.terminal_id }).inc();
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
118
|
+
const proxyIp = shouldUseHttpProxy
|
|
119
|
+
? (_a = requestContext === null || requestContext === void 0 ? void 0 : requestContext.ip) !== null && _a !== void 0 ? _a : selectHTTPProxyIpRoundRobin(terminal)
|
|
120
|
+
: undefined;
|
|
121
|
+
const res = await fetchImpl(url.href, shouldUseHttpProxy
|
|
122
|
+
? {
|
|
123
|
+
method,
|
|
124
|
+
headers,
|
|
125
|
+
labels: proxyIp ? { ip: proxyIp } : undefined,
|
|
126
|
+
terminal,
|
|
127
|
+
}
|
|
128
|
+
: {
|
|
129
|
+
method,
|
|
130
|
+
headers,
|
|
131
|
+
});
|
|
95
132
|
const usedWeight1M = res.headers.get('x-mbx-used-weight-1m');
|
|
96
133
|
const retryAfter = res.headers.get('Retry-After');
|
|
97
134
|
if (retryAfter) {
|
|
@@ -103,8 +140,8 @@ const callApi = async (method, endpoint, params, credential) => {
|
|
|
103
140
|
}
|
|
104
141
|
return res.json();
|
|
105
142
|
};
|
|
106
|
-
export const requestPublic = (method, endpoint, params) => callApi(method, endpoint, params);
|
|
107
|
-
export const requestPrivate = (credential, method, endpoint, params) => callApi(method, endpoint, params, credential);
|
|
143
|
+
export const requestPublic = (method, endpoint, params, requestContext) => callApi(method, endpoint, params, undefined, requestContext);
|
|
144
|
+
export const requestPrivate = (credential, method, endpoint, params, requestContext) => callApi(method, endpoint, params, credential, requestContext);
|
|
108
145
|
export const getDefaultCredential = () => {
|
|
109
146
|
const access_key = process.env.ACCESS_KEY;
|
|
110
147
|
const secret_key = process.env.SECRET_KEY;
|
package/dist/api/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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","sourcesContent":["import { fetch } from '@yuants/http-services';\nimport { GlobalPrometheusRegistry, Terminal } from '@yuants/protocol';\nimport { encodeHex, formatTime, HmacSHA256, newError, tokenBucket } 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;\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 ICredential {\n access_key: string;\n secret_key: string;\n}\n\nexport interface IApiError {\n code: number;\n msg: string;\n}\n\nexport const spotAPIBucket = tokenBucket('api.binance.com', {\n capacity: 6000,\n refillInterval: 60_000,\n refillAmount: 6000,\n});\n\nexport const futureAPIBucket = tokenBucket('fapi.binance.com', {\n capacity: 2400,\n refillInterval: 60_000,\n refillAmount: 2400,\n});\n\nexport const unifiedAPIBucket = tokenBucket('papi.binance.com', {\n capacity: 6000,\n refillInterval: 60_000,\n refillAmount: 6000,\n});\n\nexport const unifiedOrderAPIBucket = tokenBucket('order/unified/minute', {\n capacity: 1200,\n refillInterval: 60_000,\n refillAmount: 1200,\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): Promise<T> => {\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 res = await fetchImpl(url.href, {\n method,\n headers,\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>(method: HttpMethod, endpoint: string, params?: RequestParams) =>\n callApi<T>(method, endpoint, params);\n\nexport const requestPrivate = <T>(\n credential: ICredential,\n method: HttpMethod,\n endpoint: string,\n params?: RequestParams,\n) => callApi<T>(method, endpoint, params, credential);\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 { fetch, selectHTTPProxyIpRoundRobin } from '@yuants/http-services';\nimport { GlobalPrometheusRegistry, Terminal } from '@yuants/protocol';\nimport { encodeHex, encodePath, formatTime, HmacSHA256, newError, tokenBucket } 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 spotAPIBucket = tokenBucket('api.binance.com', {\n capacity: 6000,\n refillInterval: 60_000,\n refillAmount: 6000,\n});\n\nexport const futureAPIBucket = tokenBucket('fapi.binance.com', {\n capacity: 2400,\n refillInterval: 60_000,\n refillAmount: 2400,\n});\n\nexport const unifiedAPIBucket = tokenBucket('papi.binance.com', {\n capacity: 6000,\n refillInterval: 60_000,\n refillAmount: 6000,\n});\n\nexport const unifiedOrderAPIBucket = tokenBucket('order/unified/minute', {\n capacity: 1200,\n refillInterval: 60_000,\n refillAmount: 1200,\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 = (): IRequestContext => {\n if (shouldUseHttpProxy) {\n const ip = selectHTTPProxyIpRoundRobin(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\n ? requestContext?.ip ?? selectHTTPProxyIpRoundRobin(terminal)\n : 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"]}
|
package/dist/api/private-api.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { scopeError, tokenBucket } from '@yuants/utils';
|
|
2
|
-
import { getDefaultCredential, requestPrivate } from './client';
|
|
2
|
+
import { buildTokenBucketKey, createRequestContext, getDefaultCredential, requestPrivate, } from './client';
|
|
3
3
|
/**
|
|
4
4
|
* 查询账户信息(USER_DATA)
|
|
5
5
|
*
|
|
@@ -13,8 +13,10 @@ export const getUnifiedAccountInfo = (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
|
-
|
|
17
|
-
|
|
16
|
+
const requestContext = 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).acquireSync(weight));
|
|
19
|
+
return requestPrivate(credential, 'GET', endpoint, undefined, requestContext);
|
|
18
20
|
};
|
|
19
21
|
/**
|
|
20
22
|
* 获取UM账户信息
|
|
@@ -29,8 +31,10 @@ export const getUnifiedUmAccount = (credential) => {
|
|
|
29
31
|
const endpoint = 'https://papi.binance.com/papi/v1/um/account';
|
|
30
32
|
const url = new URL(endpoint);
|
|
31
33
|
const weight = 5;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
const requestContext = 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).acquireSync(weight));
|
|
37
|
+
return requestPrivate(credential, 'GET', endpoint, undefined, requestContext);
|
|
34
38
|
};
|
|
35
39
|
/**
|
|
36
40
|
* 查看当前全部UM挂单(USER_DATA)
|
|
@@ -45,16 +49,18 @@ export const getUnifiedUmOpenOrders = (credential, params) => {
|
|
|
45
49
|
const endpoint = 'https://papi.binance.com/papi/v1/um/openOrders';
|
|
46
50
|
const url = new URL(endpoint);
|
|
47
51
|
const weight = (params === null || params === void 0 ? void 0 : params.symbol) ? 1 : 40;
|
|
52
|
+
const requestContext = createRequestContext();
|
|
53
|
+
const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
|
|
48
54
|
scopeError('BINANCE_API_RATE_LIMIT', {
|
|
49
55
|
method: 'GET',
|
|
50
56
|
endpoint,
|
|
51
57
|
host: url.host,
|
|
52
58
|
path: url.pathname,
|
|
53
|
-
bucketId:
|
|
59
|
+
bucketId: bucketKey,
|
|
54
60
|
weight,
|
|
55
61
|
hasSymbol: !!(params === null || params === void 0 ? void 0 : params.symbol),
|
|
56
|
-
}, () => tokenBucket(
|
|
57
|
-
return requestPrivate(credential, 'GET', endpoint, params);
|
|
62
|
+
}, () => tokenBucket(bucketKey).acquireSync(weight));
|
|
63
|
+
return requestPrivate(credential, 'GET', endpoint, params, requestContext);
|
|
58
64
|
};
|
|
59
65
|
/**
|
|
60
66
|
* 查询账户余额(USER_DATA)
|
|
@@ -69,8 +75,10 @@ export const getUnifiedAccountBalance = (credential, params) => {
|
|
|
69
75
|
const endpoint = 'https://papi.binance.com/papi/v1/balance';
|
|
70
76
|
const url = new URL(endpoint);
|
|
71
77
|
const weight = 20;
|
|
72
|
-
|
|
73
|
-
|
|
78
|
+
const requestContext = 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).acquireSync(weight));
|
|
81
|
+
return requestPrivate(credential, 'GET', endpoint, params, requestContext);
|
|
74
82
|
};
|
|
75
83
|
/**
|
|
76
84
|
* 账户信息 (USER_DATA)
|
|
@@ -83,8 +91,10 @@ export const getSpotAccountInfo = (credential, params) => {
|
|
|
83
91
|
const endpoint = 'https://api.binance.com/api/v3/account';
|
|
84
92
|
const url = new URL(endpoint);
|
|
85
93
|
const weight = 20;
|
|
86
|
-
|
|
87
|
-
|
|
94
|
+
const requestContext = 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).acquireSync(weight));
|
|
97
|
+
return requestPrivate(credential, 'GET', endpoint, params, requestContext);
|
|
88
98
|
};
|
|
89
99
|
/**
|
|
90
100
|
* Current open orders (USER_DATA)
|
|
@@ -97,16 +107,18 @@ export const getSpotOpenOrders = (credential, params) => {
|
|
|
97
107
|
const endpoint = 'https://api.binance.com/api/v3/openOrders';
|
|
98
108
|
const url = new URL(endpoint);
|
|
99
109
|
const weight = (params === null || params === void 0 ? void 0 : params.symbol) ? 6 : 80;
|
|
110
|
+
const requestContext = createRequestContext();
|
|
111
|
+
const bucketKey = buildTokenBucketKey(url.host, requestContext.ip);
|
|
100
112
|
scopeError('BINANCE_API_RATE_LIMIT', {
|
|
101
113
|
method: 'GET',
|
|
102
114
|
endpoint,
|
|
103
115
|
host: url.host,
|
|
104
116
|
path: url.pathname,
|
|
105
|
-
bucketId:
|
|
117
|
+
bucketId: bucketKey,
|
|
106
118
|
weight,
|
|
107
119
|
hasSymbol: !!(params === null || params === void 0 ? void 0 : params.symbol),
|
|
108
|
-
}, () => tokenBucket(
|
|
109
|
-
return requestPrivate(credential, 'GET', endpoint, params);
|
|
120
|
+
}, () => tokenBucket(bucketKey).acquireSync(weight));
|
|
121
|
+
return requestPrivate(credential, 'GET', endpoint, params, requestContext);
|
|
110
122
|
};
|
|
111
123
|
/**
|
|
112
124
|
* New order (TRADE)
|
|
@@ -119,8 +131,10 @@ export const postSpotOrder = (credential, params) => {
|
|
|
119
131
|
const endpoint = 'https://api.binance.com/api/v3/order';
|
|
120
132
|
const url = new URL(endpoint);
|
|
121
133
|
const weight = 1;
|
|
122
|
-
|
|
123
|
-
|
|
134
|
+
const requestContext = 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).acquireSync(weight));
|
|
137
|
+
return requestPrivate(credential, 'POST', endpoint, params, requestContext);
|
|
124
138
|
};
|
|
125
139
|
/**
|
|
126
140
|
* Cancel order (TRADE)
|
|
@@ -133,8 +147,10 @@ export const deleteSpotOrder = (credential, params) => {
|
|
|
133
147
|
const endpoint = 'https://api.binance.com/api/v3/order';
|
|
134
148
|
const url = new URL(endpoint);
|
|
135
149
|
const weight = 1;
|
|
136
|
-
|
|
137
|
-
|
|
150
|
+
const requestContext = 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).acquireSync(weight));
|
|
153
|
+
return requestPrivate(credential, 'DELETE', endpoint, params, requestContext);
|
|
138
154
|
};
|
|
139
155
|
/**
|
|
140
156
|
* 用户万向划转(USER_DATA)
|
|
@@ -151,8 +167,10 @@ export const postAssetTransfer = (credential, params) => {
|
|
|
151
167
|
const endpoint = 'https://api.binance.com/sapi/v1/asset/transfer';
|
|
152
168
|
const url = new URL(endpoint);
|
|
153
169
|
const weight = 900;
|
|
154
|
-
|
|
155
|
-
|
|
170
|
+
const requestContext = 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).acquireSync(weight));
|
|
173
|
+
return requestPrivate(credential, 'POST', endpoint, params, requestContext);
|
|
156
174
|
};
|
|
157
175
|
/**
|
|
158
176
|
* 统一账户资金归集(TRADE)
|
|
@@ -169,8 +187,10 @@ export const postUnifiedAccountAutoCollection = (credential) => {
|
|
|
169
187
|
const endpoint = 'https://papi.binance.com/papi/v1/auto-collection';
|
|
170
188
|
const url = new URL(endpoint);
|
|
171
189
|
const weight = 750;
|
|
172
|
-
|
|
173
|
-
|
|
190
|
+
const requestContext = 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).acquireSync(weight));
|
|
193
|
+
return requestPrivate(credential, 'POST', endpoint, undefined, requestContext);
|
|
174
194
|
};
|
|
175
195
|
/**
|
|
176
196
|
* 获取充值地址(支持多网络)(USER_DATA)
|
|
@@ -185,8 +205,10 @@ export const getDepositAddress = (credential, params) => {
|
|
|
185
205
|
const endpoint = 'https://api.binance.com/sapi/v1/capital/deposit/address';
|
|
186
206
|
const url = new URL(endpoint);
|
|
187
207
|
const weight = 10;
|
|
188
|
-
|
|
189
|
-
|
|
208
|
+
const requestContext = 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).acquireSync(weight));
|
|
211
|
+
return requestPrivate(credential, 'GET', endpoint, params, requestContext);
|
|
190
212
|
};
|
|
191
213
|
/**
|
|
192
214
|
* 查询子账户列表(适用主账户)
|
|
@@ -199,8 +221,10 @@ export const getSubAccountList = (credential, params) => {
|
|
|
199
221
|
const endpoint = 'https://api.binance.com/sapi/v1/sub-account/list';
|
|
200
222
|
const url = new URL(endpoint);
|
|
201
223
|
const weight = 1;
|
|
202
|
-
|
|
203
|
-
|
|
224
|
+
const requestContext = 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).acquireSync(weight));
|
|
227
|
+
return requestPrivate(credential, 'GET', endpoint, params, requestContext);
|
|
204
228
|
};
|
|
205
229
|
/**
|
|
206
230
|
* 提币(USER_DATA)
|
|
@@ -213,8 +237,10 @@ export const postWithdraw = (credential, params) => {
|
|
|
213
237
|
const endpoint = 'https://api.binance.com/sapi/v1/capital/withdraw/apply';
|
|
214
238
|
const url = new URL(endpoint);
|
|
215
239
|
const weight = 600;
|
|
216
|
-
|
|
217
|
-
|
|
240
|
+
const requestContext = 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).acquireSync(weight));
|
|
243
|
+
return requestPrivate(credential, 'POST', endpoint, params, requestContext);
|
|
218
244
|
};
|
|
219
245
|
/**
|
|
220
246
|
* 获取提币历史(支持多网络)(USER_DATA)
|
|
@@ -232,8 +258,10 @@ export const getWithdrawHistory = (credential, params) => {
|
|
|
232
258
|
const endpoint = 'https://api.binance.com/sapi/v1/capital/withdraw/history';
|
|
233
259
|
const url = new URL(endpoint);
|
|
234
260
|
const weight = 1;
|
|
235
|
-
|
|
236
|
-
|
|
261
|
+
const requestContext = 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).acquireSync(weight));
|
|
264
|
+
return requestPrivate(credential, 'GET', endpoint, params, requestContext);
|
|
237
265
|
};
|
|
238
266
|
/**
|
|
239
267
|
* 获取充值历史(支持多网络)
|
|
@@ -246,8 +274,10 @@ export const getDepositHistory = (credential, params) => {
|
|
|
246
274
|
const endpoint = 'https://api.binance.com/sapi/v1/capital/deposit/hisrec';
|
|
247
275
|
const url = new URL(endpoint);
|
|
248
276
|
const weight = 1;
|
|
249
|
-
|
|
250
|
-
|
|
277
|
+
const requestContext = 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).acquireSync(weight));
|
|
280
|
+
return requestPrivate(credential, 'GET', endpoint, params, requestContext);
|
|
251
281
|
};
|
|
252
282
|
/**
|
|
253
283
|
* UM下单(TRADE)
|
|
@@ -260,15 +290,19 @@ export const postUmOrder = (credential, params) => {
|
|
|
260
290
|
const endpoint = 'https://papi.binance.com/papi/v1/um/order';
|
|
261
291
|
const url = new URL(endpoint);
|
|
262
292
|
const weight = 1;
|
|
263
|
-
|
|
264
|
-
|
|
293
|
+
const requestContext = 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).acquireSync(weight));
|
|
296
|
+
return requestPrivate(credential, 'POST', endpoint, params, requestContext);
|
|
265
297
|
};
|
|
266
298
|
export const deleteUmOrder = (credential, params) => {
|
|
267
299
|
const endpoint = 'https://papi.binance.com/papi/v1/um/order';
|
|
268
300
|
const url = new URL(endpoint);
|
|
269
301
|
const weight = 1;
|
|
270
|
-
|
|
271
|
-
|
|
302
|
+
const requestContext = 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).acquireSync(weight));
|
|
305
|
+
return requestPrivate(credential, 'DELETE', endpoint, params, requestContext);
|
|
272
306
|
};
|
|
273
307
|
/**
|
|
274
308
|
* 获取UM损益资金流水(USER_DATA)
|
|
@@ -281,8 +315,10 @@ export const getUMIncome = (credential, params) => {
|
|
|
281
315
|
const endpoint = 'https://papi.binance.com/papi/v1/um/income';
|
|
282
316
|
const url = new URL(endpoint);
|
|
283
317
|
const weight = 30;
|
|
284
|
-
|
|
285
|
-
|
|
318
|
+
const requestContext = 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).acquireSync(weight));
|
|
321
|
+
return requestPrivate(credential, 'GET', endpoint, params, requestContext);
|
|
286
322
|
};
|
|
287
323
|
/**
|
|
288
324
|
* 获取账户损益资金流水(USER_DATA)
|
|
@@ -295,8 +331,10 @@ export const getAccountIncome = (credential, params) => {
|
|
|
295
331
|
const endpoint = 'https://fapi.binance.com/fapi/v1/income';
|
|
296
332
|
const url = new URL(endpoint);
|
|
297
333
|
const weight = 30;
|
|
298
|
-
|
|
299
|
-
|
|
334
|
+
const requestContext = 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).acquireSync(weight));
|
|
337
|
+
return requestPrivate(credential, 'GET', endpoint, params, requestContext);
|
|
300
338
|
};
|
|
301
339
|
/**
|
|
302
340
|
* Cancel an Existing Order and Send a New Order (TRADE)
|
|
@@ -309,8 +347,10 @@ export const postSpotOrderCancelReplace = (credential, params) => {
|
|
|
309
347
|
const endpoint = 'https://api.binance.com/api/v3/order/cancelReplace';
|
|
310
348
|
const url = new URL(endpoint);
|
|
311
349
|
const weight = 1;
|
|
312
|
-
|
|
313
|
-
|
|
350
|
+
const requestContext = 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).acquireSync(weight));
|
|
353
|
+
return requestPrivate(credential, 'POST', endpoint, params, requestContext);
|
|
314
354
|
};
|
|
315
355
|
/**
|
|
316
356
|
* Modify Order (TRADE)
|
|
@@ -323,8 +363,10 @@ export const putUmOrder = (credential, params) => {
|
|
|
323
363
|
const endpoint = 'https://papi.binance.com/papi/v1/um/order';
|
|
324
364
|
const url = new URL(endpoint);
|
|
325
365
|
const weight = 1;
|
|
326
|
-
|
|
327
|
-
|
|
366
|
+
const requestContext = 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).acquireSync(weight));
|
|
369
|
+
return requestPrivate(credential, 'PUT', endpoint, params, requestContext);
|
|
328
370
|
};
|
|
329
371
|
/**
|
|
330
372
|
* 获取所有全仓杠杆交易对(MARKET_DATA)
|
|
@@ -338,8 +380,10 @@ export const getMarginAllPairs = (params) => {
|
|
|
338
380
|
const endpoint = 'https://api.binance.com/sapi/v1/margin/allPairs';
|
|
339
381
|
const url = new URL(endpoint);
|
|
340
382
|
const weight = 1;
|
|
341
|
-
|
|
342
|
-
|
|
383
|
+
const requestContext = 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).acquireSync(weight));
|
|
386
|
+
return requestPrivate(credential, 'GET', endpoint, params, requestContext);
|
|
343
387
|
};
|
|
344
388
|
/**
|
|
345
389
|
* Get a future hourly interest rate
|
|
@@ -351,8 +395,10 @@ export const getMarginNextHourlyInterestRate = (params) => {
|
|
|
351
395
|
const endpoint = 'https://api.binance.com/sapi/v1/margin/next-hourly-interest-rate';
|
|
352
396
|
const url = new URL(endpoint);
|
|
353
397
|
const weight = 1;
|
|
354
|
-
|
|
355
|
-
|
|
398
|
+
const requestContext = 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).acquireSync(weight));
|
|
401
|
+
return requestPrivate(credential, 'GET', endpoint, params, requestContext);
|
|
356
402
|
};
|
|
357
403
|
/**
|
|
358
404
|
* Query Margin Interest Rate History
|
|
@@ -364,8 +410,10 @@ export const getMarginInterestRateHistory = (params) => {
|
|
|
364
410
|
const endpoint = 'https://api.binance.com/sapi/v1/margin/interestRateHistory';
|
|
365
411
|
const url = new URL(endpoint);
|
|
366
412
|
const weight = 1;
|
|
367
|
-
|
|
368
|
-
|
|
413
|
+
const requestContext = 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).acquireSync(weight));
|
|
416
|
+
return requestPrivate(credential, 'GET', endpoint, params, requestContext);
|
|
369
417
|
};
|
|
370
418
|
/**
|
|
371
419
|
*获取用户持仓
|
|
@@ -378,8 +426,10 @@ export const getUserAsset = (credential, params) => {
|
|
|
378
426
|
const endpoint = 'https://api.binance.com/sapi/v3/asset/getUserAsset';
|
|
379
427
|
const url = new URL(endpoint);
|
|
380
428
|
const weight = 1;
|
|
381
|
-
|
|
382
|
-
|
|
429
|
+
const requestContext = 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).acquireSync(weight));
|
|
432
|
+
return requestPrivate(credential, 'POST', endpoint, params, requestContext);
|
|
383
433
|
};
|
|
384
434
|
/**
|
|
385
435
|
* 查询资金账户
|
|
@@ -392,8 +442,10 @@ export const getFundingAsset = (credential, params) => {
|
|
|
392
442
|
const endpoint = 'https://api.binance.com/sapi/v1/asset/get-funding-asset';
|
|
393
443
|
const url = new URL(endpoint);
|
|
394
444
|
const weight = 1;
|
|
395
|
-
|
|
396
|
-
|
|
445
|
+
const requestContext = 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).acquireSync(weight));
|
|
448
|
+
return requestPrivate(credential, 'POST', endpoint, params, requestContext);
|
|
397
449
|
};
|
|
398
450
|
/**
|
|
399
451
|
* UM账户成交历史 (USER_DATA)
|
|
@@ -406,7 +458,9 @@ export const getUmAccountTradeList = (credential, params) => {
|
|
|
406
458
|
const endpoint = 'https://papi.binance.com/papi/v1/um/userTrades';
|
|
407
459
|
const url = new URL(endpoint);
|
|
408
460
|
const weight = 5;
|
|
409
|
-
|
|
410
|
-
|
|
461
|
+
const requestContext = 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).acquireSync(weight));
|
|
464
|
+
return requestPrivate(credential, 'GET', endpoint, params, requestContext);
|
|
411
465
|
};
|
|
412
466
|
//# sourceMappingURL=private-api.js.map
|