@yuants/vendor-coinex 0.1.36 → 0.2.0

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.
Files changed (49) hide show
  1. package/dist/api.js +119 -0
  2. package/dist/api.js.map +1 -0
  3. package/dist/cli.js +3 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/extension.js +90 -0
  6. package/dist/extension.js.map +1 -0
  7. package/dist/index.js +41 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/interest_rate.js +60 -0
  10. package/dist/interest_rate.js.map +1 -0
  11. package/dist/product.js +57 -0
  12. package/dist/product.js.map +1 -0
  13. package/dist/terminal.js +7 -0
  14. package/dist/terminal.js.map +1 -0
  15. package/dist/vendor-coinex.d.ts +1 -0
  16. package/lib/api.d.ts +142 -0
  17. package/lib/api.d.ts.map +1 -0
  18. package/lib/api.js +126 -0
  19. package/lib/api.js.map +1 -0
  20. package/lib/cli.d.ts +3 -0
  21. package/lib/cli.d.ts.map +1 -0
  22. package/lib/cli.js +5 -0
  23. package/lib/cli.js.map +1 -0
  24. package/lib/extension.d.ts +4 -0
  25. package/lib/extension.d.ts.map +1 -0
  26. package/lib/extension.js +92 -0
  27. package/lib/extension.js.map +1 -0
  28. package/lib/index.d.ts +2 -0
  29. package/lib/index.d.ts.map +1 -0
  30. package/lib/index.js +43 -0
  31. package/lib/index.js.map +1 -0
  32. package/lib/interest_rate.d.ts +2 -0
  33. package/lib/interest_rate.d.ts.map +1 -0
  34. package/lib/interest_rate.js +62 -0
  35. package/lib/interest_rate.js.map +1 -0
  36. package/lib/product.d.ts +14 -0
  37. package/lib/product.d.ts.map +1 -0
  38. package/lib/product.js +60 -0
  39. package/lib/product.js.map +1 -0
  40. package/lib/terminal.d.ts +3 -0
  41. package/lib/terminal.d.ts.map +1 -0
  42. package/lib/terminal.js +10 -0
  43. package/lib/terminal.js.map +1 -0
  44. package/lib/tsdoc-metadata.json +11 -0
  45. package/package.json +12 -7
  46. package/temp/image-tag +1 -0
  47. package/temp/package-deps.json +29 -0
  48. package/temp/vendor-coinex.api.json +177 -0
  49. package/temp/vendor-coinex.api.md +9 -0
package/dist/api.js ADDED
@@ -0,0 +1,119 @@
1
+ import { UUID, formatTime } from '@yuants/utils';
2
+ // @ts-ignore
3
+ import CryptoJS from 'crypto-js';
4
+ import { Subject, filter, firstValueFrom, mergeMap, of, shareReplay, throwError, timeout, timer } from 'rxjs';
5
+ /**
6
+ * API: https://www.bitget.com/zh-CN/api-doc/common/intro
7
+ */
8
+ export class CoinExClient {
9
+ constructor(config) {
10
+ this.config = config;
11
+ this.noAuth = true;
12
+ this.mapPathToRequestChannel = {};
13
+ /**
14
+ * 获取市场资金费率
15
+ *
16
+ * https://docs.coinex.com/api/v2/zh/futures/market/http/list-market-funding-rate
17
+ */
18
+ this.getFuturesFundingRate = async (params) => this.requestWithFlowControl('GET', '/v2/futures/funding-rate', { period: 1000, limit: 400 }, params);
19
+ /**
20
+ * 获取市场资金费率历史记录
21
+ *
22
+ * https://docs.coinex.com/api/v2/zh/futures/market/http/list-market-funding-rate-history
23
+ */
24
+ this.getFuturesFundingRateHistory = async (params) => this.requestWithFlowControl('GET', '/v2/futures/funding-rate-history', { period: 1000, limit: 400 }, params);
25
+ /**
26
+ * 获取市场状态
27
+ *
28
+ * https://docs.coinex.com/api/v2/zh/futures/market/http/list-market
29
+ */
30
+ this.getFuturesMarket = async (params) => this.request('GET', '/v2/futures/market', params);
31
+ /**
32
+ * 获取市场行情
33
+ *
34
+ * https://docs.coinex.com/api/v2/zh/futures/market/http/list-market-ticker
35
+ */
36
+ this.getFuturesTicker = async (params) => this.request('GET', '/v2/futures/ticker', params);
37
+ if (config.auth.access_key && config.auth.secret_key) {
38
+ this.noAuth = false;
39
+ }
40
+ }
41
+ async request(method, path, params) {
42
+ const url = new URL('https://api.coinex.com');
43
+ url.pathname = path;
44
+ if (method === 'GET' && params !== undefined) {
45
+ const sortedParams = Object.entries(params).sort(([a], [b]) => a.localeCompare(b));
46
+ for (const [k, v] of sortedParams) {
47
+ url.searchParams.set(k, '' + v);
48
+ }
49
+ }
50
+ if (this.noAuth) {
51
+ console.info(formatTime(Date.now()), method, url.href);
52
+ const res = await fetch(url.href, { method });
53
+ return res.json();
54
+ }
55
+ const timestamp = '' + Date.now();
56
+ const secret_key = this.config.auth.secret_key;
57
+ const body = method === 'GET' ? '' : JSON.stringify(params);
58
+ const signData = method + url.pathname + url.search + body + timestamp;
59
+ const str = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(signData, secret_key));
60
+ const headers = {
61
+ 'Content-Type': 'application/json',
62
+ 'X-COINEX-KEY': this.config.auth.access_key,
63
+ 'X-COINEX-SIGN': str,
64
+ 'X-COINEX-TIMESTAMP': timestamp,
65
+ };
66
+ console.info(formatTime(Date.now()), method, url.href, JSON.stringify(headers), body, signData);
67
+ const res = await fetch(url.href, {
68
+ method,
69
+ headers,
70
+ body: body || undefined,
71
+ });
72
+ return res.json();
73
+ }
74
+ setupChannel(path, period, limit) {
75
+ this.mapPathToRequestChannel[path] = {
76
+ requestQueue: [],
77
+ responseChannel: new Subject(),
78
+ };
79
+ const { requestQueue, responseChannel } = this.mapPathToRequestChannel[path];
80
+ timer(0, period)
81
+ .pipe(filter(() => requestQueue.length > 0), mergeMap(() => requestQueue.splice(0, limit)), mergeMap(async (request) => {
82
+ try {
83
+ const res = await this.request(request.method, request.path, request.params);
84
+ return { trace_id: request.trace_id, response: res };
85
+ }
86
+ catch (error) {
87
+ return { trace_id: request.trace_id, error };
88
+ }
89
+ }))
90
+ .subscribe(responseChannel);
91
+ }
92
+ /**
93
+ * @param method - GET, POST, PUT, DELETE
94
+ * @param path - api path
95
+ * @param flowControl - period in ms, limit in count
96
+ * @param params - request params/body
97
+ * @returns
98
+ */
99
+ async requestWithFlowControl(method, path, flowControl = { period: 10, limit: Infinity }, params) {
100
+ const { period, limit } = flowControl;
101
+ if (!this.mapPathToRequestChannel[path]) {
102
+ this.setupChannel(path, period, limit);
103
+ }
104
+ const uuid = UUID();
105
+ const { requestQueue, responseChannel } = this.mapPathToRequestChannel[path];
106
+ const res$ = responseChannel.pipe(
107
+ //
108
+ filter((response) => response.trace_id === uuid), mergeMap((response) => (response.error ? throwError(() => response.error) : of(response))), timeout(30000), shareReplay(1));
109
+ requestQueue.push({ trace_id: uuid, method, path, params });
110
+ return (await firstValueFrom(res$)).response;
111
+ }
112
+ }
113
+ export const client = new CoinExClient({
114
+ auth: {
115
+ access_key: process.env.ACCESS_KEY,
116
+ secret_key: process.env.SECRET_KEY,
117
+ },
118
+ });
119
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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","sourcesContent":["import { UUID, formatTime } from '@yuants/utils';\n// @ts-ignore\nimport CryptoJS from 'crypto-js';\nimport { Subject, filter, firstValueFrom, mergeMap, of, shareReplay, throwError, timeout, timer } from 'rxjs';\n\n/**\n * API: https://www.bitget.com/zh-CN/api-doc/common/intro\n */\nexport class CoinExClient {\n noAuth = true;\n constructor(\n public config: {\n auth: {\n access_key: string;\n secret_key: string;\n };\n },\n ) {\n if (config.auth.access_key && config.auth.secret_key) {\n this.noAuth = false;\n }\n }\n\n async request(method: string, path: string, params?: any) {\n const url = new URL('https://api.coinex.com');\n url.pathname = path;\n if (method === 'GET' && params !== undefined) {\n const sortedParams = Object.entries(params).sort(([a], [b]) => a.localeCompare(b));\n for (const [k, v] of sortedParams) {\n url.searchParams.set(k, '' + v);\n }\n }\n if (this.noAuth) {\n console.info(formatTime(Date.now()), method, url.href);\n const res = await fetch(url.href, { method });\n return res.json();\n }\n const timestamp = '' + Date.now();\n const secret_key = this.config.auth.secret_key;\n const body = method === 'GET' ? '' : JSON.stringify(params);\n const signData = method + url.pathname + url.search + body + timestamp;\n const str = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(signData, secret_key));\n\n const headers = {\n 'Content-Type': 'application/json',\n 'X-COINEX-KEY': this.config.auth.access_key!,\n 'X-COINEX-SIGN': str,\n 'X-COINEX-TIMESTAMP': timestamp,\n };\n\n console.info(formatTime(Date.now()), method, url.href, JSON.stringify(headers), body, signData);\n const res = await fetch(url.href, {\n method,\n headers,\n body: body || undefined,\n });\n\n return res.json();\n }\n\n mapPathToRequestChannel: Record<\n string,\n {\n requestQueue: Array<{\n trace_id: string;\n method: string;\n path: string;\n params?: any;\n }>;\n responseChannel: Subject<{ trace_id: string; response?: any; error?: Error }>;\n }\n > = {};\n\n setupChannel(path: string, period: number, limit: number) {\n this.mapPathToRequestChannel[path] = {\n requestQueue: [],\n responseChannel: new Subject(),\n };\n\n const { requestQueue, responseChannel } = this.mapPathToRequestChannel[path];\n timer(0, period)\n .pipe(\n filter(() => requestQueue.length > 0),\n mergeMap(() => requestQueue.splice(0, limit)),\n mergeMap(async (request) => {\n try {\n const res = await this.request(request.method, request.path, request.params);\n return { trace_id: request.trace_id, response: res };\n } catch (error) {\n return { trace_id: request.trace_id, error };\n }\n }),\n )\n .subscribe(responseChannel);\n }\n\n /**\n * @param method - GET, POST, PUT, DELETE\n * @param path - api path\n * @param flowControl - period in ms, limit in count\n * @param params - request params/body\n * @returns\n */\n async requestWithFlowControl(\n method: string,\n path: string,\n flowControl: { period: number; limit: number } = { period: 10, limit: Infinity },\n params?: any,\n ) {\n const { period, limit } = flowControl;\n if (!this.mapPathToRequestChannel[path]) {\n this.setupChannel(path, period, limit);\n }\n const uuid = UUID();\n\n const { requestQueue, responseChannel } = this.mapPathToRequestChannel[path];\n const res$ = responseChannel.pipe(\n //\n filter((response) => response.trace_id === uuid),\n mergeMap((response) => (response.error ? throwError(() => response.error) : of(response))),\n timeout(30_000),\n shareReplay(1),\n );\n requestQueue.push({ trace_id: uuid, method, path, params });\n return (await firstValueFrom(res$)).response;\n }\n\n /**\n * 获取市场资金费率\n *\n * https://docs.coinex.com/api/v2/zh/futures/market/http/list-market-funding-rate\n */\n getFuturesFundingRate = async (params?: {\n market?: string;\n }): Promise<{\n code: number;\n message: string;\n data: {\n market: string;\n mark_price: string;\n latest_funding_rate: string;\n next_funding_rate: string;\n max_funding_time: string;\n min_funding_time: string;\n latest_funding_time: number;\n next_funding_time: number;\n }[];\n }> => this.requestWithFlowControl('GET', '/v2/futures/funding-rate', { period: 1000, limit: 400 }, params);\n\n /**\n * 获取市场资金费率历史记录\n *\n * https://docs.coinex.com/api/v2/zh/futures/market/http/list-market-funding-rate-history\n */\n getFuturesFundingRateHistory = async (params: {\n market: string;\n start_time?: number;\n end_time?: number;\n page?: number;\n limit?: number;\n }): Promise<{\n code: number;\n message: string;\n pagination: {\n has_next: boolean;\n };\n data: {\n market: string;\n funding_time: number;\n theoretical_funding_rate: string;\n actual_funding_rate: string;\n }[];\n }> =>\n this.requestWithFlowControl(\n 'GET',\n '/v2/futures/funding-rate-history',\n { period: 1000, limit: 400 },\n params,\n );\n\n /**\n * 获取市场状态\n *\n * https://docs.coinex.com/api/v2/zh/futures/market/http/list-market\n */\n getFuturesMarket = async (params?: {\n market?: string;\n }): Promise<{\n code: number;\n message: string;\n data: {\n market: string;\n contract_type: string;\n maker_fee_rate: string;\n taker_fee_rate: string;\n min_amount: string;\n base_ccy: string;\n quote_ccy: string;\n base_ccy_precision: number;\n quote_ccy_precision: number;\n leverage: number[];\n open_interest_volume: string;\n }[];\n }> => this.request('GET', '/v2/futures/market', params);\n\n /**\n * 获取市场行情\n *\n * https://docs.coinex.com/api/v2/zh/futures/market/http/list-market-ticker\n */\n getFuturesTicker = async (params?: {\n market?: string;\n }): Promise<{\n code: number;\n message: string;\n data: {\n market: string;\n last: string;\n open: string;\n close: string;\n high: string;\n low: string;\n volume: string;\n value: string;\n volume_sell: string;\n volume_buy: string;\n index_price: string;\n mark_price: string;\n period: number;\n }[];\n }> => this.request('GET', '/v2/futures/ticker', params);\n}\n\nexport const client = new CoinExClient({\n auth: {\n access_key: process.env.ACCESS_KEY!,\n secret_key: process.env.SECRET_KEY!,\n },\n});\n"]}
package/dist/cli.js ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import './index';
3
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,SAAS,CAAC","sourcesContent":["#!/usr/bin/env node\nimport './index';\n"]}
@@ -0,0 +1,90 @@
1
+ import { makeDockerEnvs, makeK8sEnvs } from '@yuants/extension';
2
+ export default (context) => {
3
+ context.registerDeployProvider({
4
+ make_json_schema: () => ({
5
+ type: 'object',
6
+ properties: {
7
+ env: {
8
+ type: 'object',
9
+ required: ['HOST_URL'],
10
+ properties: {
11
+ //
12
+ HOST_URL: { type: 'string' },
13
+ TERMINAL_ID: { type: 'string' },
14
+ ACCESS_KEY: { type: 'string' },
15
+ SECRET_KEY: { type: 'string' },
16
+ PASSPHRASE: { type: 'string' },
17
+ },
18
+ },
19
+ },
20
+ }),
21
+ make_docker_compose_file: async (ctx, envCtx) => {
22
+ var _a;
23
+ return {
24
+ [`coinex-${ctx.env.ACCESS_KEY}`.replace(/\s/g, '')]: {
25
+ image: `ghcr.io/no-trade-no-life/vendor-coinex:${(_a = ctx.version) !== null && _a !== void 0 ? _a : envCtx.version}`,
26
+ restart: 'always',
27
+ environment: makeDockerEnvs(ctx.env),
28
+ },
29
+ };
30
+ },
31
+ make_k8s_resource_objects: async (ctx, envCtx) => {
32
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
33
+ return {
34
+ deployment: {
35
+ apiVersion: 'apps/v1',
36
+ kind: 'Deployment',
37
+ metadata: {
38
+ labels: {
39
+ 'y.ntnl.io/version': (_a = ctx.version) !== null && _a !== void 0 ? _a : envCtx.version,
40
+ 'y.ntnl.io/manifest_key': ctx.key,
41
+ 'y.ntnl.io/component': 'coinex',
42
+ },
43
+ name: `coinex-${ctx.key}`.replace(/\s/g, '').toLocaleLowerCase(),
44
+ namespace: 'yuan',
45
+ },
46
+ spec: {
47
+ replicas: 1,
48
+ selector: {
49
+ matchLabels: {
50
+ 'y.ntnl.io/component': 'coinex',
51
+ 'y.ntnl.io/manifest_key': ctx.key,
52
+ },
53
+ },
54
+ template: {
55
+ metadata: {
56
+ labels: {
57
+ 'y.ntnl.io/version': (_b = ctx.version) !== null && _b !== void 0 ? _b : envCtx.version,
58
+ 'y.ntnl.io/manifest_key': ctx.key,
59
+ 'y.ntnl.io/component': 'coinex',
60
+ },
61
+ },
62
+ spec: {
63
+ containers: [
64
+ {
65
+ env: makeK8sEnvs(ctx.env),
66
+ image: `ghcr.io/no-trade-no-life/vendor-coinex:${(_c = ctx.version) !== null && _c !== void 0 ? _c : envCtx.version}`,
67
+ imagePullPolicy: 'IfNotPresent',
68
+ name: 'coinex',
69
+ resources: {
70
+ limits: {
71
+ cpu: (_e = (_d = ctx.cpu) === null || _d === void 0 ? void 0 : _d.max) !== null && _e !== void 0 ? _e : '500m',
72
+ memory: (_g = (_f = ctx.memory) === null || _f === void 0 ? void 0 : _f.max) !== null && _g !== void 0 ? _g : '256Mi',
73
+ },
74
+ requests: {
75
+ cpu: (_j = (_h = ctx.cpu) === null || _h === void 0 ? void 0 : _h.min) !== null && _j !== void 0 ? _j : '100m',
76
+ memory: (_l = (_k = ctx.memory) === null || _k === void 0 ? void 0 : _k.min) !== null && _l !== void 0 ? _l : '128Mi',
77
+ },
78
+ },
79
+ },
80
+ ],
81
+ hostname: 'coinex',
82
+ },
83
+ },
84
+ },
85
+ },
86
+ };
87
+ },
88
+ });
89
+ };
90
+ //# sourceMappingURL=extension.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extension.js","sourceRoot":"","sources":["../src/extension.ts"],"names":[],"mappings":"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","sourcesContent":["import { IExtensionContext, makeDockerEnvs, makeK8sEnvs } from '@yuants/extension';\nexport default (context: IExtensionContext) => {\n context.registerDeployProvider({\n make_json_schema: () => ({\n type: 'object',\n properties: {\n env: {\n type: 'object',\n required: ['HOST_URL'],\n properties: {\n //\n HOST_URL: { type: 'string' },\n TERMINAL_ID: { type: 'string' },\n ACCESS_KEY: { type: 'string' },\n SECRET_KEY: { type: 'string' },\n PASSPHRASE: { type: 'string' },\n },\n },\n },\n }),\n make_docker_compose_file: async (ctx, envCtx) => {\n return {\n [`coinex-${ctx.env!.ACCESS_KEY}`.replace(/\\s/g, '')]: {\n image: `ghcr.io/no-trade-no-life/vendor-coinex:${ctx.version ?? envCtx.version}`,\n restart: 'always',\n\n environment: makeDockerEnvs(ctx.env),\n },\n };\n },\n make_k8s_resource_objects: async (ctx, envCtx) => {\n return {\n deployment: {\n apiVersion: 'apps/v1',\n kind: 'Deployment',\n metadata: {\n labels: {\n 'y.ntnl.io/version': ctx.version ?? envCtx.version,\n 'y.ntnl.io/manifest_key': ctx.key,\n 'y.ntnl.io/component': 'coinex',\n },\n name: `coinex-${ctx.key}`.replace(/\\s/g, '').toLocaleLowerCase(),\n namespace: 'yuan',\n },\n spec: {\n replicas: 1,\n selector: {\n matchLabels: {\n 'y.ntnl.io/component': 'coinex',\n 'y.ntnl.io/manifest_key': ctx.key,\n },\n },\n template: {\n metadata: {\n labels: {\n 'y.ntnl.io/version': ctx.version ?? envCtx.version,\n 'y.ntnl.io/manifest_key': ctx.key,\n 'y.ntnl.io/component': 'coinex',\n },\n },\n spec: {\n containers: [\n {\n env: makeK8sEnvs(ctx.env),\n image: `ghcr.io/no-trade-no-life/vendor-coinex:${ctx.version ?? envCtx.version}`,\n imagePullPolicy: 'IfNotPresent',\n name: 'coinex',\n resources: {\n limits: {\n cpu: ctx.cpu?.max ?? '500m',\n memory: ctx.memory?.max ?? '256Mi',\n },\n requests: {\n cpu: ctx.cpu?.min ?? '100m',\n memory: ctx.memory?.min ?? '128Mi',\n },\n },\n },\n ],\n hostname: 'coinex',\n },\n },\n },\n },\n };\n },\n });\n};\n"]}
package/dist/index.js ADDED
@@ -0,0 +1,41 @@
1
+ import { defer, from, map, mergeMap, repeat, retry, shareReplay, toArray } from 'rxjs';
2
+ import { client } from './api';
3
+ import './interest_rate';
4
+ const mapSymbolToFundingRate$ = defer(() => client.getFuturesFundingRate()).pipe(
5
+ //
6
+ map((v) => v.data), repeat({ delay: 1000 }), retry({ delay: 30000 }), mergeMap((x) => from(x).pipe(map((v) => [v.market, v]), toArray(), map((v) => new Map(v)))), shareReplay(1));
7
+ const mapSymbolToTicker$ = defer(() => client.getFuturesTicker()).pipe(
8
+ //
9
+ map((v) => v.data), repeat({ delay: 1000 }), retry({ delay: 30000 }), mergeMap((x) => from(x).pipe(map((v) => [v.market, v]), toArray(), map((v) => new Map(v)))), shareReplay(1));
10
+ // provideTicks(terminal, 'COINEX', (product_id) => {
11
+ // const [instType, instId] = decodePath(product_id);
12
+ // if (instType !== 'SWAP') return [];
13
+ // return combineLatest([mapSymbolToTicker$, mapSymbolToMarket$, mapSymbolToFundingRate$]).pipe(
14
+ // //
15
+ // map(([mapSymbolToTicker, mapSymbolToMarket, mapSymbolToFundingRate]): ITick => {
16
+ // const ticker = mapSymbolToTicker.get(instId);
17
+ // const market = mapSymbolToMarket.get(instId);
18
+ // const fundingRate = mapSymbolToFundingRate.get(instId);
19
+ // if (!ticker) {
20
+ // throw new Error(`ticker ${instId} not found`);
21
+ // }
22
+ // if (!market) {
23
+ // throw new Error(`market ${instId} not found`);
24
+ // }
25
+ // if (!fundingRate) {
26
+ // throw new Error(`fundingRate ${instId} not found`);
27
+ // }
28
+ // return {
29
+ // product_id,
30
+ // datasource_id: 'COINEX',
31
+ // updated_at: Date.now(),
32
+ // price: +ticker.last,
33
+ // interest_rate_for_long: -+fundingRate.latest_funding_rate,
34
+ // interest_rate_for_short: +fundingRate.latest_funding_rate,
35
+ // settlement_scheduled_at: +fundingRate.next_funding_time,
36
+ // open_interest: +market.open_interest_volume,
37
+ // };
38
+ // }),
39
+ // );
40
+ // });
41
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACvF,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAC/B,OAAO,iBAAiB,CAAC;AAEzB,MAAM,uBAAuB,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,qBAAqB,EAAE,CAAC,CAAC,IAAI;AAC9E,EAAE;AACF,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAClB,MAAM,CAAC,EAAE,KAAK,EAAE,IAAK,EAAE,CAAC,EACxB,KAAK,CAAC,EAAE,KAAK,EAAE,KAAM,EAAE,CAAC,EACxB,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CACb,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAU,CAAC,EAClC,OAAO,EAAE,EACT,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CACvB,CACF,EACD,WAAW,CAAC,CAAC,CAAC,CACf,CAAC;AAEF,MAAM,kBAAkB,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC,IAAI;AACpE,EAAE;AACF,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAClB,MAAM,CAAC,EAAE,KAAK,EAAE,IAAK,EAAE,CAAC,EACxB,KAAK,CAAC,EAAE,KAAK,EAAE,KAAM,EAAE,CAAC,EACxB,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CACb,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAU,CAAC,EAClC,OAAO,EAAE,EACT,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CACvB,CACF,EACD,WAAW,CAAC,CAAC,CAAC,CACf,CAAC;AAEF,qDAAqD;AACrD,uDAAuD;AACvD,wCAAwC;AACxC,kGAAkG;AAClG,SAAS;AACT,uFAAuF;AACvF,sDAAsD;AACtD,sDAAsD;AACtD,gEAAgE;AAChE,uBAAuB;AACvB,yDAAyD;AACzD,UAAU;AACV,uBAAuB;AACvB,yDAAyD;AACzD,UAAU;AACV,4BAA4B;AAC5B,8DAA8D;AAC9D,UAAU;AACV,iBAAiB;AACjB,sBAAsB;AACtB,mCAAmC;AACnC,kCAAkC;AAClC,+BAA+B;AAC/B,qEAAqE;AACrE,qEAAqE;AACrE,mEAAmE;AACnE,uDAAuD;AACvD,WAAW;AACX,UAAU;AACV,OAAO;AACP,MAAM","sourcesContent":["import { defer, from, map, mergeMap, repeat, retry, shareReplay, toArray } from 'rxjs';\nimport { client } from './api';\nimport './interest_rate';\n\nconst mapSymbolToFundingRate$ = defer(() => client.getFuturesFundingRate()).pipe(\n //\n map((v) => v.data),\n repeat({ delay: 1_000 }),\n retry({ delay: 30_000 }),\n mergeMap((x) =>\n from(x).pipe(\n map((v) => [v.market, v] as const),\n toArray(),\n map((v) => new Map(v)),\n ),\n ),\n shareReplay(1),\n);\n\nconst mapSymbolToTicker$ = defer(() => client.getFuturesTicker()).pipe(\n //\n map((v) => v.data),\n repeat({ delay: 1_000 }),\n retry({ delay: 30_000 }),\n mergeMap((x) =>\n from(x).pipe(\n map((v) => [v.market, v] as const),\n toArray(),\n map((v) => new Map(v)),\n ),\n ),\n shareReplay(1),\n);\n\n// provideTicks(terminal, 'COINEX', (product_id) => {\n// const [instType, instId] = decodePath(product_id);\n// if (instType !== 'SWAP') return [];\n// return combineLatest([mapSymbolToTicker$, mapSymbolToMarket$, mapSymbolToFundingRate$]).pipe(\n// //\n// map(([mapSymbolToTicker, mapSymbolToMarket, mapSymbolToFundingRate]): ITick => {\n// const ticker = mapSymbolToTicker.get(instId);\n// const market = mapSymbolToMarket.get(instId);\n// const fundingRate = mapSymbolToFundingRate.get(instId);\n// if (!ticker) {\n// throw new Error(`ticker ${instId} not found`);\n// }\n// if (!market) {\n// throw new Error(`market ${instId} not found`);\n// }\n// if (!fundingRate) {\n// throw new Error(`fundingRate ${instId} not found`);\n// }\n// return {\n// product_id,\n// datasource_id: 'COINEX',\n// updated_at: Date.now(),\n// price: +ticker.last,\n// interest_rate_for_long: -+fundingRate.latest_funding_rate,\n// interest_rate_for_short: +fundingRate.latest_funding_rate,\n// settlement_scheduled_at: +fundingRate.next_funding_time,\n// open_interest: +market.open_interest_volume,\n// };\n// }),\n// );\n// });\n"]}
@@ -0,0 +1,60 @@
1
+ var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
2
+ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
3
+ if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
4
+ var g = generator.apply(thisArg, _arguments || []), i, q = [];
5
+ return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
6
+ function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
7
+ function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
8
+ function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
9
+ function fulfill(value) { resume("next", value); }
10
+ function reject(value) { resume("throw", value); }
11
+ function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
12
+ };
13
+ import { createSeriesProvider } from '@yuants/data-series';
14
+ import { decodePath, formatTime } from '@yuants/utils';
15
+ import { firstValueFrom, timer } from 'rxjs';
16
+ import { client } from './api';
17
+ import { terminal } from './terminal';
18
+ createSeriesProvider(terminal, {
19
+ tableName: 'interest_rate',
20
+ series_id_prefix_parts: ['coinex'],
21
+ reversed: true,
22
+ serviceOptions: { concurrent: 1 },
23
+ queryFn: function ({ series_id, started_at, ended_at }) {
24
+ return __asyncGenerator(this, arguments, function* () {
25
+ const [datasource_id, product_id] = decodePath(series_id);
26
+ const [instType, instId] = decodePath(product_id);
27
+ let current_page = 0;
28
+ while (true) {
29
+ const res = yield __await(client.getFuturesFundingRateHistory({
30
+ market: instId,
31
+ start_time: started_at,
32
+ end_time: ended_at,
33
+ page: current_page,
34
+ limit: 100,
35
+ }));
36
+ if (res.code !== 0) {
37
+ throw `API failed: ${res.code} ${res.message}`;
38
+ }
39
+ if (res.data.length === 0)
40
+ break;
41
+ yield yield __await(res.data.map((v) => ({
42
+ series_id,
43
+ datasource_id,
44
+ product_id,
45
+ created_at: formatTime(+v.funding_time),
46
+ long_rate: `${-v.actual_funding_rate}`,
47
+ short_rate: `${v.actual_funding_rate}`,
48
+ settlement_price: '',
49
+ })));
50
+ if (!res.pagination.has_next)
51
+ break;
52
+ if (+res.data[res.data.length - 1].funding_time <= started_at)
53
+ break;
54
+ current_page++;
55
+ yield __await(firstValueFrom(timer(1000)));
56
+ }
57
+ });
58
+ },
59
+ });
60
+ //# sourceMappingURL=interest_rate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"interest_rate.js","sourceRoot":"","sources":["../src/interest_rate.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,oBAAoB,CAAgB,QAAQ,EAAE;IAC5C,SAAS,EAAE,eAAe;IAC1B,sBAAsB,EAAE,CAAC,QAAQ,CAAC;IAClC,QAAQ,EAAE,IAAI;IACd,cAAc,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE;IACjC,OAAO,EAAE,UAAiB,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE;;YAC3D,MAAM,CAAC,aAAa,EAAE,UAAU,CAAC,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;YAC1D,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;YAClD,IAAI,YAAY,GAAG,CAAC,CAAC;YAErB,OAAO,IAAI,EAAE;gBACX,MAAM,GAAG,GAAG,cAAM,MAAM,CAAC,4BAA4B,CAAC;oBACpD,MAAM,EAAE,MAAM;oBACd,UAAU,EAAE,UAAU;oBACtB,QAAQ,EAAE,QAAQ;oBAClB,IAAI,EAAE,YAAY;oBAClB,KAAK,EAAE,GAAG;iBACX,CAAC,CAAA,CAAC;gBACH,IAAI,GAAG,CAAC,IAAI,KAAK,CAAC,EAAE;oBAClB,MAAM,eAAe,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;iBAChD;gBACD,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;oBAAE,MAAM;gBAEjC,oBAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAChB,CAAC,CAAC,EAAiB,EAAE,CAAC,CAAC;oBACrB,SAAS;oBACT,aAAa;oBACb,UAAU;oBACV,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;oBACvC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,mBAAmB,EAAE;oBACtC,UAAU,EAAE,GAAG,CAAC,CAAC,mBAAmB,EAAE;oBACtC,gBAAgB,EAAE,EAAE;iBACrB,CAAC,CACH,CAAA,CAAC;gBACF,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ;oBAAE,MAAM;gBACpC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,YAAY,IAAI,UAAU;oBAAE,MAAM;gBACrE,YAAY,EAAE,CAAC;gBACf,cAAM,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA,CAAC;aACnC;QACH,CAAC;KAAA;CACF,CAAC,CAAC","sourcesContent":["import { IInterestRate } from '@yuants/data-interest-rate';\nimport { createSeriesProvider } from '@yuants/data-series';\nimport { decodePath, formatTime } from '@yuants/utils';\nimport { firstValueFrom, timer } from 'rxjs';\nimport { client } from './api';\nimport { terminal } from './terminal';\n\ncreateSeriesProvider<IInterestRate>(terminal, {\n tableName: 'interest_rate',\n series_id_prefix_parts: ['coinex'],\n reversed: true,\n serviceOptions: { concurrent: 1 },\n queryFn: async function* ({ series_id, started_at, ended_at }) {\n const [datasource_id, product_id] = decodePath(series_id);\n const [instType, instId] = decodePath(product_id);\n let current_page = 0;\n\n while (true) {\n const res = await client.getFuturesFundingRateHistory({\n market: instId,\n start_time: started_at,\n end_time: ended_at,\n page: current_page,\n limit: 100,\n });\n if (res.code !== 0) {\n throw `API failed: ${res.code} ${res.message}`;\n }\n if (res.data.length === 0) break;\n\n yield res.data.map(\n (v): IInterestRate => ({\n series_id,\n datasource_id,\n product_id,\n created_at: formatTime(+v.funding_time),\n long_rate: `${-v.actual_funding_rate}`,\n short_rate: `${v.actual_funding_rate}`,\n settlement_price: '',\n }),\n );\n if (!res.pagination.has_next) break;\n if (+res.data[res.data.length - 1].funding_time <= started_at) break;\n current_page++;\n await firstValueFrom(timer(1000));\n }\n },\n});\n"]}
@@ -0,0 +1,57 @@
1
+ import { createSQLWriter } from '@yuants/sql';
2
+ import { encodePath, formatTime } from '@yuants/utils';
3
+ import { defer, from, map, mergeMap, repeat, retry, shareReplay, Subject, tap, toArray } from 'rxjs';
4
+ import { client } from './api';
5
+ import { terminal } from './terminal';
6
+ const product$ = new Subject();
7
+ export const mapSymbolToMarket$ = defer(async () => {
8
+ const res = await client.getFuturesMarket();
9
+ if (res.code !== 0) {
10
+ throw new Error(res.message);
11
+ }
12
+ return res.data;
13
+ }).pipe(repeat({ delay: 1000 }), retry({ delay: 30000 }), mergeMap((x) => from(x).pipe(map((v) => [v.market, v]), toArray(), map((v) => new Map(v)))), shareReplay(1));
14
+ const futuresProducts$ = defer(async () => {
15
+ const res = await client.getFuturesMarket();
16
+ if (res.code !== 0) {
17
+ throw new Error(res.message);
18
+ }
19
+ const futures = res.data.map((item) => ({
20
+ datasource_id: 'COINEX',
21
+ product_id: encodePath('SWAP', item.market),
22
+ quote_currency: item.quote_ccy,
23
+ base_currency: item.base_ccy,
24
+ price_step: Number(item.quote_ccy_precision),
25
+ // FIXME: volume_step, value_scale
26
+ volume_step: 1,
27
+ value_scale: 1,
28
+ name: '',
29
+ value_scale_unit: '',
30
+ margin_rate: 0,
31
+ value_based_cost: 0,
32
+ volume_based_cost: 0,
33
+ max_position: 0,
34
+ max_volume: 0,
35
+ allow_long: true,
36
+ allow_short: true,
37
+ }));
38
+ return futures;
39
+ }).pipe(tap((list) => {
40
+ list.forEach((v) => product$.next(v));
41
+ }), tap({
42
+ error: (e) => {
43
+ console.error(formatTime(Date.now()), 'FuturesProducts', e);
44
+ },
45
+ }), retry({ delay: 5000 }), repeat({ delay: 86400000 }), shareReplay(1));
46
+ createSQLWriter(terminal, {
47
+ tableName: 'product',
48
+ data$: product$,
49
+ writeInterval: 1000,
50
+ keyFn: (x) => encodePath(x.datasource_id, x.product_id),
51
+ conflictKeys: ['datasource_id', 'product_id'],
52
+ });
53
+ futuresProducts$.subscribe();
54
+ const mapProductIdToFuturesProduct$ = futuresProducts$.pipe(
55
+ //
56
+ map((products) => new Map(products.map((v) => [v.product_id, v]))), shareReplay(1));
57
+ //# sourceMappingURL=product.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"product.js","sourceRoot":"","sources":["../src/product.ts"],"names":[],"mappings":"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","sourcesContent":["import { IProduct } from '@yuants/data-product';\nimport { createSQLWriter } from '@yuants/sql';\nimport { encodePath, formatTime } from '@yuants/utils';\nimport { defer, from, map, mergeMap, repeat, retry, shareReplay, Subject, tap, toArray } from 'rxjs';\nimport { client } from './api';\nimport { terminal } from './terminal';\n\nconst product$ = new Subject<IProduct>();\n\nexport const mapSymbolToMarket$ = defer(async () => {\n const res = await client.getFuturesMarket();\n if (res.code !== 0) {\n throw new Error(res.message);\n }\n return res.data;\n}).pipe(\n repeat({ delay: 1_000 }),\n retry({ delay: 30_000 }),\n mergeMap((x) =>\n from(x).pipe(\n map((v) => [v.market, v] as const),\n toArray(),\n map((v) => new Map(v)),\n ),\n ),\n shareReplay(1),\n);\n\nconst futuresProducts$ = defer(async () => {\n const res = await client.getFuturesMarket();\n if (res.code !== 0) {\n throw new Error(res.message);\n }\n\n const futures = res.data.map(\n (item): IProduct => ({\n datasource_id: 'COINEX',\n product_id: encodePath('SWAP', item.market),\n quote_currency: item.quote_ccy,\n base_currency: item.base_ccy,\n price_step: Number(item.quote_ccy_precision),\n // FIXME: volume_step, value_scale\n volume_step: 1,\n value_scale: 1,\n name: '',\n value_scale_unit: '',\n margin_rate: 0,\n value_based_cost: 0,\n volume_based_cost: 0,\n max_position: 0,\n max_volume: 0,\n allow_long: true,\n allow_short: true,\n }),\n );\n return futures;\n}).pipe(\n tap((list) => {\n list.forEach((v) => product$.next(v));\n }),\n tap({\n error: (e) => {\n console.error(formatTime(Date.now()), 'FuturesProducts', e);\n },\n }),\n retry({ delay: 5000 }),\n repeat({ delay: 86400_000 }),\n shareReplay(1),\n);\n\ncreateSQLWriter<IProduct>(terminal, {\n tableName: 'product',\n data$: product$,\n writeInterval: 1000,\n keyFn: (x) => encodePath(x.datasource_id, x.product_id),\n conflictKeys: ['datasource_id', 'product_id'],\n});\n\nfuturesProducts$.subscribe();\n\nconst mapProductIdToFuturesProduct$ = futuresProducts$.pipe(\n //\n map((products) => new Map(products.map((v) => [v.product_id, v]))),\n shareReplay(1),\n);\n"]}
@@ -0,0 +1,7 @@
1
+ import { Terminal } from '@yuants/protocol';
2
+ import { UUID } from '@yuants/utils';
3
+ export const terminal = new Terminal(process.env.HOST_URL, {
4
+ name: 'COINEX',
5
+ terminal_id: process.env.TERMINAL_ID || `COINEX/${UUID()}`,
6
+ });
7
+ //# sourceMappingURL=terminal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.js","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,MAAM,CAAC,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,QAAS,EAAE;IAC1D,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,UAAU,IAAI,EAAE,EAAE;CAC3D,CAAC,CAAC","sourcesContent":["import { Terminal } from '@yuants/protocol';\nimport { UUID } from '@yuants/utils';\n\nexport const terminal = new Terminal(process.env.HOST_URL!, {\n name: 'COINEX',\n terminal_id: process.env.TERMINAL_ID || `COINEX/${UUID()}`,\n});\n"]}
@@ -0,0 +1 @@
1
+ export { }
package/lib/api.d.ts ADDED
@@ -0,0 +1,142 @@
1
+ import { Subject } from 'rxjs';
2
+ /**
3
+ * API: https://www.bitget.com/zh-CN/api-doc/common/intro
4
+ */
5
+ export declare class CoinExClient {
6
+ config: {
7
+ auth: {
8
+ access_key: string;
9
+ secret_key: string;
10
+ };
11
+ };
12
+ noAuth: boolean;
13
+ constructor(config: {
14
+ auth: {
15
+ access_key: string;
16
+ secret_key: string;
17
+ };
18
+ });
19
+ request(method: string, path: string, params?: any): Promise<any>;
20
+ mapPathToRequestChannel: Record<string, {
21
+ requestQueue: Array<{
22
+ trace_id: string;
23
+ method: string;
24
+ path: string;
25
+ params?: any;
26
+ }>;
27
+ responseChannel: Subject<{
28
+ trace_id: string;
29
+ response?: any;
30
+ error?: Error;
31
+ }>;
32
+ }>;
33
+ setupChannel(path: string, period: number, limit: number): void;
34
+ /**
35
+ * @param method - GET, POST, PUT, DELETE
36
+ * @param path - api path
37
+ * @param flowControl - period in ms, limit in count
38
+ * @param params - request params/body
39
+ * @returns
40
+ */
41
+ requestWithFlowControl(method: string, path: string, flowControl?: {
42
+ period: number;
43
+ limit: number;
44
+ }, params?: any): Promise<any>;
45
+ /**
46
+ * 获取市场资金费率
47
+ *
48
+ * https://docs.coinex.com/api/v2/zh/futures/market/http/list-market-funding-rate
49
+ */
50
+ getFuturesFundingRate: (params?: {
51
+ market?: string;
52
+ }) => Promise<{
53
+ code: number;
54
+ message: string;
55
+ data: {
56
+ market: string;
57
+ mark_price: string;
58
+ latest_funding_rate: string;
59
+ next_funding_rate: string;
60
+ max_funding_time: string;
61
+ min_funding_time: string;
62
+ latest_funding_time: number;
63
+ next_funding_time: number;
64
+ }[];
65
+ }>;
66
+ /**
67
+ * 获取市场资金费率历史记录
68
+ *
69
+ * https://docs.coinex.com/api/v2/zh/futures/market/http/list-market-funding-rate-history
70
+ */
71
+ getFuturesFundingRateHistory: (params: {
72
+ market: string;
73
+ start_time?: number;
74
+ end_time?: number;
75
+ page?: number;
76
+ limit?: number;
77
+ }) => Promise<{
78
+ code: number;
79
+ message: string;
80
+ pagination: {
81
+ has_next: boolean;
82
+ };
83
+ data: {
84
+ market: string;
85
+ funding_time: number;
86
+ theoretical_funding_rate: string;
87
+ actual_funding_rate: string;
88
+ }[];
89
+ }>;
90
+ /**
91
+ * 获取市场状态
92
+ *
93
+ * https://docs.coinex.com/api/v2/zh/futures/market/http/list-market
94
+ */
95
+ getFuturesMarket: (params?: {
96
+ market?: string;
97
+ }) => Promise<{
98
+ code: number;
99
+ message: string;
100
+ data: {
101
+ market: string;
102
+ contract_type: string;
103
+ maker_fee_rate: string;
104
+ taker_fee_rate: string;
105
+ min_amount: string;
106
+ base_ccy: string;
107
+ quote_ccy: string;
108
+ base_ccy_precision: number;
109
+ quote_ccy_precision: number;
110
+ leverage: number[];
111
+ open_interest_volume: string;
112
+ }[];
113
+ }>;
114
+ /**
115
+ * 获取市场行情
116
+ *
117
+ * https://docs.coinex.com/api/v2/zh/futures/market/http/list-market-ticker
118
+ */
119
+ getFuturesTicker: (params?: {
120
+ market?: string;
121
+ }) => Promise<{
122
+ code: number;
123
+ message: string;
124
+ data: {
125
+ market: string;
126
+ last: string;
127
+ open: string;
128
+ close: string;
129
+ high: string;
130
+ low: string;
131
+ volume: string;
132
+ value: string;
133
+ volume_sell: string;
134
+ volume_buy: string;
135
+ index_price: string;
136
+ mark_price: string;
137
+ period: number;
138
+ }[];
139
+ }>;
140
+ }
141
+ export declare const client: CoinExClient;
142
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}