@yuants/vendor-binance 0.14.8 → 0.14.9
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 +3 -8
- package/dist/api/client.js.map +1 -1
- package/lib/api/client.d.ts +0 -1
- package/lib/api/client.d.ts.map +1 -1
- package/lib/api/client.js +3 -8
- package/lib/api/client.js.map +1 -1
- package/package.json +8 -8
- package/temp/build/typescript/ts_tQj2bmGB.json +1 -1
- package/temp/package-deps.json +5 -5
- package/temp/test/jest/haste-map-f37bc94525b36254e573de220443d250-dc922b21f2d35e7315abf4c3159e25a5-63b40dbcff306581344a73f9073894a1 +0 -0
package/dist/api/client.js
CHANGED
|
@@ -60,7 +60,7 @@ const resolveLocalPublicIp = () => {
|
|
|
60
60
|
};
|
|
61
61
|
export const createRequestContext = async (baseKey, weight) => {
|
|
62
62
|
if (shouldUseHttpProxy) {
|
|
63
|
-
const { ip,
|
|
63
|
+
const { ip, bucketKey } = acquireProxyBucket({
|
|
64
64
|
baseKey,
|
|
65
65
|
weight,
|
|
66
66
|
terminal,
|
|
@@ -76,7 +76,7 @@ export const createRequestContext = async (baseKey, weight) => {
|
|
|
76
76
|
return options;
|
|
77
77
|
},
|
|
78
78
|
});
|
|
79
|
-
return { ip,
|
|
79
|
+
return { ip, bucketKey, acquireWeight: 0 };
|
|
80
80
|
}
|
|
81
81
|
const ip = resolveLocalPublicIp();
|
|
82
82
|
return {
|
|
@@ -147,16 +147,11 @@ const callApi = async (method, endpoint, params, credential, requestContext) =>
|
|
|
147
147
|
}
|
|
148
148
|
MetricBinanceApiCounter.labels({ path: url.pathname, terminal_id: terminal.terminal_id }).inc();
|
|
149
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;
|
|
151
150
|
const res = await fetchImpl(url.href, shouldUseHttpProxy
|
|
152
151
|
? {
|
|
153
152
|
method,
|
|
154
153
|
headers,
|
|
155
|
-
labels: proxyIp
|
|
156
|
-
? { ip: proxyIp, terminal_id: proxyTerminalId }
|
|
157
|
-
: proxyIp
|
|
158
|
-
? { ip: proxyIp }
|
|
159
|
-
: undefined,
|
|
154
|
+
labels: proxyIp ? { ip: proxyIp } : undefined,
|
|
160
155
|
terminal,
|
|
161
156
|
}
|
|
162
157
|
: {
|
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 { 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
|
+
{"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 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, 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, 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 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/lib/api/client.d.ts
CHANGED
package/lib/api/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAOL,KAAK,kBAAkB,EACxB,MAAM,eAAe,CAAC;AAcvB,KAAK,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEpD,KAAK,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;AAE3E,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"AAEA,OAAO,EAOL,KAAK,kBAAkB,EACxB,MAAM,eAAe,CAAC;AAcvB,KAAK,UAAU,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEpD,KAAK,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC,CAAC;AAE3E,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb;AAED,eAAO,MAAM,kCAAkC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CA0BjF,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,SAAS,MAAM,KAAG,kBAAkB,GAAG,SAChC,CAAC;AAE9C,eAAO,MAAM,aAAa,sCAGzB,CAAC;AAEF,eAAO,MAAM,eAAe,sCAG3B,CAAC;AAEF,eAAO,MAAM,gBAAgB,sCAG5B,CAAC;AAEF,eAAO,MAAM,qBAAqB,sCAGjC,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,SAAS,MAAM,EAAE,IAAI,MAAM,KAAG,MAAmC,CAAC;AActG,eAAO,MAAM,oBAAoB,GAAU,SAAS,MAAM,EAAE,QAAQ,MAAM,KAAG,OAAO,CAAC,eAAe,CA0BnG,CAAC;AAKF,eAAO,MAAM,UAAU,GAAI,CAAC,EAAE,OAAO,CAAC,GAAG,SAAS,KAAG,KAAK,IAAI,SACmC,CAAC;AA+GlG,eAAO,MAAM,aAAa,GAAI,CAAC,EAC7B,QAAQ,UAAU,EAClB,UAAU,MAAM,EAChB,SAAS,aAAa,EACtB,iBAAiB,eAAe,eACkC,CAAC;AAErE,eAAO,MAAM,cAAc,GAAI,CAAC,EAC9B,YAAY,WAAW,EACvB,QAAQ,UAAU,EAClB,UAAU,MAAM,EAChB,SAAS,aAAa,EACtB,iBAAiB,eAAe,eACmC,CAAC;AAEtE,eAAO,MAAM,oBAAoB,QAAO,WAOvC,CAAC"}
|
package/lib/api/client.js
CHANGED
|
@@ -65,7 +65,7 @@ const resolveLocalPublicIp = () => {
|
|
|
65
65
|
};
|
|
66
66
|
const createRequestContext = async (baseKey, weight) => {
|
|
67
67
|
if (shouldUseHttpProxy) {
|
|
68
|
-
const { ip,
|
|
68
|
+
const { ip, bucketKey } = (0, http_services_1.acquireProxyBucket)({
|
|
69
69
|
baseKey,
|
|
70
70
|
weight,
|
|
71
71
|
terminal,
|
|
@@ -81,7 +81,7 @@ const createRequestContext = async (baseKey, weight) => {
|
|
|
81
81
|
return options;
|
|
82
82
|
},
|
|
83
83
|
});
|
|
84
|
-
return { ip,
|
|
84
|
+
return { ip, bucketKey, acquireWeight: 0 };
|
|
85
85
|
}
|
|
86
86
|
const ip = resolveLocalPublicIp();
|
|
87
87
|
return {
|
|
@@ -154,16 +154,11 @@ const callApi = async (method, endpoint, params, credential, requestContext) =>
|
|
|
154
154
|
}
|
|
155
155
|
MetricBinanceApiCounter.labels({ path: url.pathname, terminal_id: terminal.terminal_id }).inc();
|
|
156
156
|
const proxyIp = shouldUseHttpProxy ? requestContext === null || requestContext === void 0 ? void 0 : requestContext.ip : undefined;
|
|
157
|
-
const proxyTerminalId = shouldUseHttpProxy ? requestContext === null || requestContext === void 0 ? void 0 : requestContext.terminalId : undefined;
|
|
158
157
|
const res = await fetchImpl(url.href, shouldUseHttpProxy
|
|
159
158
|
? {
|
|
160
159
|
method,
|
|
161
160
|
headers,
|
|
162
|
-
labels: proxyIp
|
|
163
|
-
? { ip: proxyIp, terminal_id: proxyTerminalId }
|
|
164
|
-
: proxyIp
|
|
165
|
-
? { ip: proxyIp }
|
|
166
|
-
: undefined,
|
|
161
|
+
labels: proxyIp ? { ip: proxyIp } : undefined,
|
|
167
162
|
terminal,
|
|
168
163
|
}
|
|
169
164
|
: {
|
package/lib/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 { 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
|
+
{"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 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, 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, 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 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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yuants/vendor-binance",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.9",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -10,20 +10,20 @@
|
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"rxjs": "~7.5.6",
|
|
12
12
|
"@yuants/protocol": "0.55.0",
|
|
13
|
+
"@yuants/cache": "0.3.15",
|
|
13
14
|
"@yuants/data-account": "0.11.12",
|
|
14
15
|
"@yuants/data-quote": "0.4.12",
|
|
15
|
-
"@yuants/cache": "0.3.15",
|
|
16
16
|
"@yuants/utils": "0.19.7",
|
|
17
|
-
"@yuants/data-ohlc": "0.6.8",
|
|
18
|
-
"@yuants/data-order": "0.7.13",
|
|
19
|
-
"@yuants/sql": "0.9.43",
|
|
20
17
|
"@yuants/data-series": "0.3.65",
|
|
18
|
+
"@yuants/sql": "0.9.43",
|
|
21
19
|
"@yuants/data-product": "0.5.13",
|
|
20
|
+
"@yuants/data-ohlc": "0.6.8",
|
|
22
21
|
"@yuants/data-interest-rate": "0.2.13",
|
|
23
|
-
"@yuants/transfer": "0.2.52",
|
|
24
22
|
"@yuants/exchange": "0.8.23",
|
|
25
|
-
"@yuants/data-
|
|
26
|
-
"@yuants/
|
|
23
|
+
"@yuants/data-order": "0.7.13",
|
|
24
|
+
"@yuants/transfer": "0.2.52",
|
|
25
|
+
"@yuants/http-services": "0.5.3",
|
|
26
|
+
"@yuants/data-trade": "0.1.38"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@microsoft/api-extractor": "~7.55.2",
|