@yuants/vendor-okx 0.17.2 → 0.17.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/ohlc.js CHANGED
@@ -15,7 +15,7 @@ import { Terminal } from '@yuants/protocol';
15
15
  import { convertDurationToOffset, decodePath, encodePath, formatTime } from '@yuants/utils';
16
16
  import { firstValueFrom, Observable, timer } from 'rxjs';
17
17
  import { client } from './api';
18
- import { okxBusinessWsClient } from './websocket';
18
+ import { OKXWsClient } from './websocket';
19
19
  import { writeToSQL } from '@yuants/sql';
20
20
  // 时间粒度,默认值1m
21
21
  // 如 [1m/3m/5m/15m/30m/1H/2H/4H]
@@ -130,6 +130,7 @@ Terminal.fromNodeEnv().channel.publishChannel('ohlc', { pattern: `^OKX/` }, (ser
130
130
  console.info(formatTime(Date.now()), `subscribe`, series_id);
131
131
  return new Observable((subscriber) => {
132
132
  console.info(formatTime(Date.now()), `subscribe`, candleType, instId);
133
+ const okxBusinessWsClient = new OKXWsClient('wss://wspap.okx.com:8443/ws/v5/business');
133
134
  okxBusinessWsClient.subscribe(candleType, instId, async (data) => {
134
135
  const created_at = Number(data[0]);
135
136
  const closed_at = created_at + offset;
package/dist/ohlc.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ohlc.js","sourceRoot":"","sources":["../src/ohlc.ts"],"names":[],"mappings":";;;;;;;;;;;;AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,uBAAuB,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC5F,OAAO,EAAE,cAAc,EAAE,UAAU,EAAM,KAAK,EAAE,MAAM,MAAM,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAA2C,UAAU,EAAE,MAAM,aAAa,CAAC;AAElF,aAAa;AACb,gCAAgC;AAChC,8BAA8B;AAC9B,8CAA8C;AAE9C,MAAM,wBAAwB,GAA2B;IACvD,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,KAAK;IACZ,KAAK,EAAE,KAAK;IAEZ,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,KAAK;IAEZ,GAAG,EAAE,IAAI;IACT,GAAG,EAAE,IAAI;IACT,GAAG,EAAE,IAAI;CACV,CAAC;AAEF,MAAM,2BAA2B,GAA2B;IAC1D,IAAI,EAAE,qBAAqB;IAC3B,IAAI,EAAE,qBAAqB;IAC3B,IAAI,EAAE,qBAAqB;IAC3B,KAAK,EAAE,sBAAsB;IAC7B,KAAK,EAAE,sBAAsB;IAE7B,IAAI,EAAE,qBAAqB;IAC3B,IAAI,EAAE,qBAAqB;IAC3B,IAAI,EAAE,qBAAqB;IAC3B,IAAI,EAAE,qBAAqB;IAC3B,KAAK,EAAE,sBAAsB;IAE7B,GAAG,EAAE,qBAAqB;IAC1B,GAAG,EAAE,qBAAqB;IAC1B,GAAG,EAAE,qBAAqB;CAC3B,CAAC;AAEF,oBAAoB,CAAQ,QAAQ,CAAC,WAAW,EAAE,EAAE;IAClD,SAAS,EAAE,MAAM;IACjB,sBAAsB,EAAE,CAAC,KAAK,CAAC;IAC/B,QAAQ,EAAE,IAAI;IACd,cAAc,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE;IACjC,OAAO,EAAE,UAAiB,EAAE,SAAS,EAAE,QAAQ,EAAE;;YAC/C,MAAM,CAAC,aAAa,EAAE,UAAU,EAAE,QAAQ,CAAC,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;YACpE,MAAM,MAAM,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;YACjD,IAAI,CAAC,aAAa,EAAE;gBAClB,MAAM,2BAA2B,CAAC;aACnC;YACD,IAAI,CAAC,UAAU,EAAE;gBACf,MAAM,wBAAwB,CAAC;aAChC;YACD,IAAI,CAAC,MAAM,EAAE;gBACX,MAAM,qBAAqB,CAAC;aAC7B;YACD,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;YAClD,IAAI,CAAC,MAAM,EAAE;gBACX,MAAM,uBAAuB,UAAU,EAAE,CAAC;aAC3C;YAED,MAAM,GAAG,GAAG,wBAAwB,CAAC,QAAQ,CAAC,CAAC;YAC/C,IAAI,CAAC,GAAG,EAAE;gBACR,MAAM,yBAAyB,QAAQ,EAAE,CAAC;aAC3C;YAED,IAAI,gBAAgB,GAAG,QAAQ,CAAC;YAEhC,OAAO,IAAI,EAAE;gBACX,yBAAyB;gBACzB,MAAM,GAAG,GAAG,cAAM,MAAM,CAAC,iBAAiB,CAAC;oBACzC,MAAM;oBACN,GAAG;oBACH,KAAK,EAAE,GAAG,gBAAgB,EAAE;oBAC5B,KAAK,EAAE,KAAK;iBACb,CAAC,CAAA,CAAC;gBACH,IAAI,GAAG,CAAC,IAAI,KAAK,GAAG,EAAE;oBACpB,MAAM,eAAe,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC;iBAC5C;gBACD,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;oBAAE,MAAM;gBACjC,gBAAgB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACrD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CACvB,CAAC,CAAC,EAAS,EAAE,CAAC,CAAC;oBACb,SAAS;oBACT,aAAa;oBACb,UAAU;oBACV,QAAQ;oBACR,UAAU,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC7B,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;oBACrC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;oBACV,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;oBACV,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;oBACT,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;oBACX,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;oBACZ,aAAa,EAAE,GAAG;iBACnB,CAAC,CACH,CAAC;gBACF,oBAAM,IAAI,CAAA,CAAC;gBACX,cAAM,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAA,CAAC;aACnC;QACH,CAAC;KAAA;CACF,CAAC,CAAC;AAEH,QAAQ,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,SAAS,EAAE,EAAE;IACxF,8BAA8B;IAC9B,MAAM,CAAC,aAAa,EAAE,UAAU,EAAE,QAAQ,CAAC,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IACjD,IAAI,CAAC,aAAa,EAAE;QAClB,MAAM,2BAA2B,CAAC;KACnC;IACD,IAAI,CAAC,UAAU,EAAE;QACf,MAAM,wBAAwB,CAAC;KAChC;IACD,IAAI,CAAC,MAAM,EAAE;QACX,MAAM,qBAAqB,CAAC;KAC7B;IACD,MAAM,UAAU,GAAG,2BAA2B,CAAC,QAAQ,CAAC,CAAC;IACzD,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;IAC7D,OAAO,IAAI,UAAU,CAAQ,CAAC,UAAU,EAAE,EAAE;QAC1C,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;QACtE,mBAAmB,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,IAAc,EAAE,EAAE;YACzE,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACnC,MAAM,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;YACtC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACrB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACrB,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACpB,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACtB,IAAI,KAAK,CAAC,SAAS,CAAC,EAAE;gBACpB,OAAO;aACR;YACD,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC;YACzD,MAAM,UAAU,GAAU;gBACxB,SAAS,EAAE,UAAU,CAAC,SAAS,CAAC;gBAChC,UAAU,EAAE,UAAU,CAAC,UAAU,CAAC;gBAClC,IAAI;gBACJ,IAAI;gBACJ,GAAG;gBACH,KAAK;gBACL,SAAS;gBACT,aAAa;gBACb,QAAQ;gBACR,UAAU;gBACV,MAAM,EAAE,GAAG;gBACX,aAAa,EAAE,GAAG;aACnB,CAAC;YACF,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,EAAE;YACV,mBAAmB,CAAC,WAAW,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACtD,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC,IAAI,CACL,UAAU,CAAC;QACT,SAAS,EAAE,MAAM;QACjB,YAAY,EAAE,CAAC,YAAY,EAAE,WAAW,CAAC;QACzC,aAAa,EAAE,IAAI;QACnB,QAAQ,EAAE,QAAQ,CAAC,WAAW,EAAE;QAChC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,SAAS,CAAC;KACpD,CAAC,CACH,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["import { IOHLC } from '@yuants/data-ohlc';\nimport { createSeriesProvider } from '@yuants/data-series';\nimport { Terminal } from '@yuants/protocol';\nimport { convertDurationToOffset, decodePath, encodePath, formatTime } from '@yuants/utils';\nimport { firstValueFrom, Observable, of, timer } from 'rxjs';\nimport { client } from './api';\nimport { okxBusinessWsClient } from './websocket';\nimport { buildInsertManyIntoTableSQL, requestSQL, writeToSQL } from '@yuants/sql';\n\n// 时间粒度,默认值1m\n// 如 [1m/3m/5m/15m/30m/1H/2H/4H]\n// 香港时间开盘价k线:[6H/12H/1D/1W/1M]\n// UTC时间开盘价k线:[6Hutc/12Hutc/1Dutc/1Wutc/1Mutc]\n\nconst DURATION_TO_OKX_BAR_TYPE: Record<string, string> = {\n PT1M: '1m',\n PT3M: '3m',\n PT5M: '5m',\n PT15M: '15m',\n PT30M: '30m',\n\n PT1H: '1H',\n PT2H: '2H',\n PT4H: '4H',\n PT6H: '6H',\n PT12H: '12H',\n\n P1D: '1D',\n P1W: '1W',\n P1M: '1M',\n};\n\nconst DURATION_TO_OKX_CANDLE_TYPE: Record<string, string> = {\n PT1M: 'mark-price-candle1m',\n PT3M: 'mark-price-candle3m',\n PT5M: 'mark-price-candle5m',\n PT15M: 'mark-price-candle15m',\n PT30M: 'mark-price-candle30m',\n\n PT1H: 'mark-price-candle1H',\n PT2H: 'mark-price-candle2H',\n PT4H: 'mark-price-candle4H',\n PT6H: 'mark-price-candle6H',\n PT12H: 'mark-price-candle12H',\n\n P1D: 'mark-price-candle1D',\n P1W: 'mark-price-candle1W',\n P1M: 'mark-price-candle1M',\n};\n\ncreateSeriesProvider<IOHLC>(Terminal.fromNodeEnv(), {\n tableName: 'ohlc',\n series_id_prefix_parts: ['OKX'],\n reversed: true,\n serviceOptions: { concurrent: 1 },\n queryFn: async function* ({ series_id, ended_at }) {\n const [datasource_id, product_id, duration] = decodePath(series_id);\n const offset = convertDurationToOffset(duration);\n if (!datasource_id) {\n throw 'datasource_id is required';\n }\n if (!product_id) {\n throw 'product_id is required';\n }\n if (!offset) {\n throw 'duration is invalid';\n }\n const [instType, instId] = decodePath(product_id);\n if (!instId) {\n throw `invalid product_id: ${product_id}`;\n }\n\n const bar = DURATION_TO_OKX_BAR_TYPE[duration];\n if (!bar) {\n throw `unsupported duration: ${duration}`;\n }\n\n let currentStartTime = ended_at;\n\n while (true) {\n // 向前翻页,时间降序,不含 after 时间点\n const res = await client.getHistoryCandles({\n instId,\n bar,\n after: `${currentStartTime}`,\n limit: '100',\n });\n if (res.code !== '0') {\n throw `API failed: ${res.code} ${res.msg}`;\n }\n if (res.data.length === 0) break;\n currentStartTime = +res.data[res.data.length - 1][0];\n const data = res.data.map(\n (x): IOHLC => ({\n series_id,\n datasource_id,\n product_id,\n duration,\n created_at: formatTime(+x[0]),\n closed_at: formatTime(+x[0] + offset),\n open: x[1],\n high: x[2],\n low: x[3],\n close: x[4],\n volume: x[5],\n open_interest: '0',\n }),\n );\n yield data;\n await firstValueFrom(timer(1000));\n }\n },\n});\n\nTerminal.fromNodeEnv().channel.publishChannel('ohlc', { pattern: `^OKX/` }, (series_id) => {\n // const [] = decodePath(args)\n const [datasource_id, product_id, duration] = decodePath(series_id);\n const [, instId] = decodePath(product_id);\n const offset = convertDurationToOffset(duration);\n if (!datasource_id) {\n throw 'datasource_id is required';\n }\n if (!product_id) {\n throw 'product_id is required';\n }\n if (!offset) {\n throw 'duration is invalid';\n }\n const candleType = DURATION_TO_OKX_CANDLE_TYPE[duration];\n console.info(formatTime(Date.now()), `subscribe`, series_id);\n return new Observable<IOHLC>((subscriber) => {\n console.info(formatTime(Date.now()), `subscribe`, candleType, instId);\n okxBusinessWsClient.subscribe(candleType, instId, async (data: string[]) => {\n const created_at = Number(data[0]);\n const closed_at = created_at + offset;\n const open = data[1];\n const high = data[2];\n const low = data[3];\n const close = data[4];\n if (isNaN(closed_at)) {\n return;\n }\n console.info(formatTime(Date.now()), `insertData`, data);\n const cancelData: IOHLC = {\n closed_at: formatTime(closed_at),\n created_at: formatTime(created_at),\n open,\n high,\n low,\n close,\n series_id,\n datasource_id,\n duration,\n product_id,\n volume: '0',\n open_interest: '0',\n };\n subscriber.next(cancelData);\n });\n return () => {\n okxBusinessWsClient.unsubscribe(candleType, instId);\n };\n }).pipe(\n writeToSQL({\n tableName: 'ohlc',\n conflictKeys: ['created_at', 'series_id'],\n writeInterval: 1000,\n terminal: Terminal.fromNodeEnv(),\n keyFn: (x) => encodePath(x.created_at, x.series_id),\n }),\n );\n});\n"]}
1
+ {"version":3,"file":"ohlc.js","sourceRoot":"","sources":["../src/ohlc.ts"],"names":[],"mappings":"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","sourcesContent":["import { IOHLC } from '@yuants/data-ohlc';\nimport { createSeriesProvider } from '@yuants/data-series';\nimport { Terminal } from '@yuants/protocol';\nimport { convertDurationToOffset, decodePath, encodePath, formatTime } from '@yuants/utils';\nimport { firstValueFrom, Observable, of, timer } from 'rxjs';\nimport { client } from './api';\nimport { OKXWsClient } from './websocket';\nimport { writeToSQL } from '@yuants/sql';\n\n// 时间粒度,默认值1m\n// 如 [1m/3m/5m/15m/30m/1H/2H/4H]\n// 香港时间开盘价k线:[6H/12H/1D/1W/1M]\n// UTC时间开盘价k线:[6Hutc/12Hutc/1Dutc/1Wutc/1Mutc]\n\nconst DURATION_TO_OKX_BAR_TYPE: Record<string, string> = {\n PT1M: '1m',\n PT3M: '3m',\n PT5M: '5m',\n PT15M: '15m',\n PT30M: '30m',\n\n PT1H: '1H',\n PT2H: '2H',\n PT4H: '4H',\n PT6H: '6H',\n PT12H: '12H',\n\n P1D: '1D',\n P1W: '1W',\n P1M: '1M',\n};\n\nconst DURATION_TO_OKX_CANDLE_TYPE: Record<string, string> = {\n PT1M: 'mark-price-candle1m',\n PT3M: 'mark-price-candle3m',\n PT5M: 'mark-price-candle5m',\n PT15M: 'mark-price-candle15m',\n PT30M: 'mark-price-candle30m',\n\n PT1H: 'mark-price-candle1H',\n PT2H: 'mark-price-candle2H',\n PT4H: 'mark-price-candle4H',\n PT6H: 'mark-price-candle6H',\n PT12H: 'mark-price-candle12H',\n\n P1D: 'mark-price-candle1D',\n P1W: 'mark-price-candle1W',\n P1M: 'mark-price-candle1M',\n};\n\ncreateSeriesProvider<IOHLC>(Terminal.fromNodeEnv(), {\n tableName: 'ohlc',\n series_id_prefix_parts: ['OKX'],\n reversed: true,\n serviceOptions: { concurrent: 1 },\n queryFn: async function* ({ series_id, ended_at }) {\n const [datasource_id, product_id, duration] = decodePath(series_id);\n const offset = convertDurationToOffset(duration);\n if (!datasource_id) {\n throw 'datasource_id is required';\n }\n if (!product_id) {\n throw 'product_id is required';\n }\n if (!offset) {\n throw 'duration is invalid';\n }\n const [instType, instId] = decodePath(product_id);\n if (!instId) {\n throw `invalid product_id: ${product_id}`;\n }\n\n const bar = DURATION_TO_OKX_BAR_TYPE[duration];\n if (!bar) {\n throw `unsupported duration: ${duration}`;\n }\n\n let currentStartTime = ended_at;\n\n while (true) {\n // 向前翻页,时间降序,不含 after 时间点\n const res = await client.getHistoryCandles({\n instId,\n bar,\n after: `${currentStartTime}`,\n limit: '100',\n });\n if (res.code !== '0') {\n throw `API failed: ${res.code} ${res.msg}`;\n }\n if (res.data.length === 0) break;\n currentStartTime = +res.data[res.data.length - 1][0];\n const data = res.data.map(\n (x): IOHLC => ({\n series_id,\n datasource_id,\n product_id,\n duration,\n created_at: formatTime(+x[0]),\n closed_at: formatTime(+x[0] + offset),\n open: x[1],\n high: x[2],\n low: x[3],\n close: x[4],\n volume: x[5],\n open_interest: '0',\n }),\n );\n yield data;\n await firstValueFrom(timer(1000));\n }\n },\n});\n\nTerminal.fromNodeEnv().channel.publishChannel('ohlc', { pattern: `^OKX/` }, (series_id) => {\n // const [] = decodePath(args)\n const [datasource_id, product_id, duration] = decodePath(series_id);\n const [, instId] = decodePath(product_id);\n const offset = convertDurationToOffset(duration);\n if (!datasource_id) {\n throw 'datasource_id is required';\n }\n if (!product_id) {\n throw 'product_id is required';\n }\n if (!offset) {\n throw 'duration is invalid';\n }\n const candleType = DURATION_TO_OKX_CANDLE_TYPE[duration];\n console.info(formatTime(Date.now()), `subscribe`, series_id);\n return new Observable<IOHLC>((subscriber) => {\n console.info(formatTime(Date.now()), `subscribe`, candleType, instId);\n const okxBusinessWsClient = new OKXWsClient('wss://wspap.okx.com:8443/ws/v5/business');\n okxBusinessWsClient.subscribe(candleType, instId, async (data: string[]) => {\n const created_at = Number(data[0]);\n const closed_at = created_at + offset;\n const open = data[1];\n const high = data[2];\n const low = data[3];\n const close = data[4];\n if (isNaN(closed_at)) {\n return;\n }\n console.info(formatTime(Date.now()), `insertData`, data);\n const cancelData: IOHLC = {\n closed_at: formatTime(closed_at),\n created_at: formatTime(created_at),\n open,\n high,\n low,\n close,\n series_id,\n datasource_id,\n duration,\n product_id,\n volume: '0',\n open_interest: '0',\n };\n subscriber.next(cancelData);\n });\n return () => {\n okxBusinessWsClient.unsubscribe(candleType, instId);\n };\n }).pipe(\n writeToSQL({\n tableName: 'ohlc',\n conflictKeys: ['created_at', 'series_id'],\n writeInterval: 1000,\n terminal: Terminal.fromNodeEnv(),\n keyFn: (x) => encodePath(x.created_at, x.series_id),\n }),\n );\n});\n"]}
package/dist/websocket.js CHANGED
@@ -1,11 +1,19 @@
1
1
  import { encodePath, formatTime } from '@yuants/utils';
2
+ import { interval, tap } from 'rxjs';
2
3
  // import WebSocket from 'ws';
3
- class OKXWsClient {
4
+ export class OKXWsClient {
4
5
  constructor(url) {
5
6
  this.connected = false;
6
7
  // this.instId = instId;
7
8
  this.ws = new WebSocket(url);
8
9
  this.pendingSub = [];
10
+ this.keepAlive = interval(25000)
11
+ .pipe(tap(() => {
12
+ if (this.connected) {
13
+ this.ws.send('ping');
14
+ }
15
+ }))
16
+ .subscribe();
9
17
  // this.ws.
10
18
  this.ws.addEventListener('open', () => {
11
19
  this.connected = true;
@@ -25,6 +33,9 @@ class OKXWsClient {
25
33
  // 处理消息
26
34
  handleMessage(raw) {
27
35
  var _a, _b;
36
+ if (raw.data === 'pong') {
37
+ return;
38
+ }
28
39
  const msg = JSON.parse(raw.data);
29
40
  if ((_a = msg.arg) === null || _a === void 0 ? void 0 : _a.channel) {
30
41
  const channelId = encodePath(msg.arg.channel, msg.arg.instId);
@@ -72,9 +83,11 @@ class OKXWsClient {
72
83
  };
73
84
  this.ws.send(JSON.stringify(unSubMsg));
74
85
  this.subscriptions.delete(channelId);
86
+ if (this.subscriptions.size === 0) {
87
+ this.keepAlive.unsubscribe();
88
+ }
75
89
  delete this.handlers[channelId];
76
90
  console.info(`📩 Sent unsubscribe for ${channelId}`);
77
91
  }
78
92
  }
79
- export const okxBusinessWsClient = new OKXWsClient('wss://wspap.okx.com:8443/ws/v5/business');
80
93
  //# sourceMappingURL=websocket.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"websocket.js","sourceRoot":"","sources":["../src/websocket.ts"],"names":[],"mappings":"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","sourcesContent":["import { encodePath, formatTime } from '@yuants/utils';\n// import WebSocket from 'ws';\n\nclass OKXWsClient {\n ws: WebSocket;\n connected: boolean = false;\n subscriptions: Set<string>;\n handlers: Record<string, Function>;\n pendingSub: string[];\n constructor(url: string) {\n // this.instId = instId;\n this.ws = new WebSocket(url);\n this.pendingSub = [];\n // this.ws.\n this.ws.addEventListener('open', () => {\n this.connected = true;\n console.info(formatTime(Date.now()), '✅ WS connected');\n while (this.pendingSub.length > 0) {\n const msg = this.pendingSub.shift();\n if (msg) {\n this.ws.send(msg);\n console.info(formatTime(Date.now()), `📩 Sent subscribe for ${msg}`);\n }\n }\n });\n this.ws.addEventListener('message', (raw) => this.handleMessage(raw));\n this.subscriptions = new Set();\n this.handlers = {}; // key: channel, value: callback\n }\n\n // 处理消息\n handleMessage(raw: any) {\n const msg = JSON.parse(raw.data);\n if (msg.arg?.channel) {\n const channelId = encodePath(msg.arg.channel, msg.arg.instId);\n const data = msg.data?.[0];\n if (data && this.handlers[channelId]) {\n this.handlers[channelId](data, msg.arg);\n }\n } else if (msg.event) {\n console.info('Event:', msg);\n }\n }\n\n // 调用订阅\n subscribe(channel: string, instId?: string, handler?: Function) {\n const channelId = encodePath(channel, instId);\n if (this.subscriptions.has(channelId)) {\n console.info(formatTime(Date.now()), `⚠️ Already subscribed: ${channelId}`);\n return;\n }\n\n const subMsg = {\n op: 'subscribe',\n args: [{ channel, instId }],\n };\n\n if (this.connected) {\n this.ws.send(JSON.stringify(subMsg));\n console.info(formatTime(Date.now()), `📩 Sent subscribe for ${channelId}`);\n } else {\n this.pendingSub.push(JSON.stringify(subMsg));\n console.info(formatTime(Date.now()), `📩 add subscribe for ${channelId} to pending list`);\n }\n this.subscriptions.add(channelId);\n if (handler) {\n this.handlers[channelId] = handler;\n }\n }\n\n // 取消订阅\n unsubscribe(channel: string, instId?: string) {\n const channelId = encodePath(channel, instId);\n if (!this.subscriptions.has(channelId)) return;\n\n const unSubMsg = {\n op: 'unsubscribe',\n args: [{ channel, instId }],\n };\n\n this.ws.send(JSON.stringify(unSubMsg));\n this.subscriptions.delete(channelId);\n delete this.handlers[channelId];\n console.info(`📩 Sent unsubscribe for ${channelId}`);\n }\n}\n\nexport const okxBusinessWsClient = new OKXWsClient('wss://wspap.okx.com:8443/ws/v5/business');\n"]}
1
+ {"version":3,"file":"websocket.js","sourceRoot":"","sources":["../src/websocket.ts"],"names":[],"mappings":"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","sourcesContent":["import { encodePath, formatTime } from '@yuants/utils';\nimport { interval, Subscription, tap } from 'rxjs';\n// import WebSocket from 'ws';\n\nexport class OKXWsClient {\n ws: WebSocket;\n connected: boolean = false;\n subscriptions: Set<string>;\n handlers: Record<string, Function>;\n pendingSub: string[];\n keepAlive: Subscription;\n constructor(url: string) {\n // this.instId = instId;\n this.ws = new WebSocket(url);\n this.pendingSub = [];\n this.keepAlive = interval(25000)\n .pipe(\n tap(() => {\n if (this.connected) {\n this.ws.send('ping');\n }\n }),\n )\n .subscribe();\n // this.ws.\n this.ws.addEventListener('open', () => {\n this.connected = true;\n console.info(formatTime(Date.now()), '✅ WS connected');\n while (this.pendingSub.length > 0) {\n const msg = this.pendingSub.shift();\n if (msg) {\n this.ws.send(msg);\n console.info(formatTime(Date.now()), `📩 Sent subscribe for ${msg}`);\n }\n }\n });\n\n this.ws.addEventListener('message', (raw) => this.handleMessage(raw));\n this.subscriptions = new Set();\n this.handlers = {}; // key: channel, value: callback\n }\n\n // 处理消息\n handleMessage(raw: any) {\n if (raw.data === 'pong') {\n return;\n }\n const msg = JSON.parse(raw.data);\n if (msg.arg?.channel) {\n const channelId = encodePath(msg.arg.channel, msg.arg.instId);\n const data = msg.data?.[0];\n if (data && this.handlers[channelId]) {\n this.handlers[channelId](data, msg.arg);\n }\n } else if (msg.event) {\n console.info('Event:', msg);\n }\n }\n\n // 调用订阅\n subscribe(channel: string, instId?: string, handler?: Function) {\n const channelId = encodePath(channel, instId);\n if (this.subscriptions.has(channelId)) {\n console.info(formatTime(Date.now()), `⚠️ Already subscribed: ${channelId}`);\n return;\n }\n\n const subMsg = {\n op: 'subscribe',\n args: [{ channel, instId }],\n };\n\n if (this.connected) {\n this.ws.send(JSON.stringify(subMsg));\n console.info(formatTime(Date.now()), `📩 Sent subscribe for ${channelId}`);\n } else {\n this.pendingSub.push(JSON.stringify(subMsg));\n console.info(formatTime(Date.now()), `📩 add subscribe for ${channelId} to pending list`);\n }\n this.subscriptions.add(channelId);\n if (handler) {\n this.handlers[channelId] = handler;\n }\n }\n\n // 取消订阅\n unsubscribe(channel: string, instId?: string) {\n const channelId = encodePath(channel, instId);\n if (!this.subscriptions.has(channelId)) return;\n\n const unSubMsg = {\n op: 'unsubscribe',\n args: [{ channel, instId }],\n };\n\n this.ws.send(JSON.stringify(unSubMsg));\n this.subscriptions.delete(channelId);\n if (this.subscriptions.size === 0) {\n this.keepAlive.unsubscribe();\n }\n delete this.handlers[channelId];\n console.info(`📩 Sent unsubscribe for ${channelId}`);\n }\n}\n"]}
package/lib/ohlc.js CHANGED
@@ -132,7 +132,8 @@ protocol_1.Terminal.fromNodeEnv().channel.publishChannel('ohlc', { pattern: `^OK
132
132
  console.info((0, utils_1.formatTime)(Date.now()), `subscribe`, series_id);
133
133
  return new rxjs_1.Observable((subscriber) => {
134
134
  console.info((0, utils_1.formatTime)(Date.now()), `subscribe`, candleType, instId);
135
- websocket_1.okxBusinessWsClient.subscribe(candleType, instId, async (data) => {
135
+ const okxBusinessWsClient = new websocket_1.OKXWsClient('wss://wspap.okx.com:8443/ws/v5/business');
136
+ okxBusinessWsClient.subscribe(candleType, instId, async (data) => {
136
137
  const created_at = Number(data[0]);
137
138
  const closed_at = created_at + offset;
138
139
  const open = data[1];
@@ -160,7 +161,7 @@ protocol_1.Terminal.fromNodeEnv().channel.publishChannel('ohlc', { pattern: `^OK
160
161
  subscriber.next(cancelData);
161
162
  });
162
163
  return () => {
163
- websocket_1.okxBusinessWsClient.unsubscribe(candleType, instId);
164
+ okxBusinessWsClient.unsubscribe(candleType, instId);
164
165
  };
165
166
  }).pipe((0, sql_1.writeToSQL)({
166
167
  tableName: 'ohlc',
package/lib/ohlc.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ohlc.js","sourceRoot":"","sources":["../src/ohlc.ts"],"names":[],"mappings":"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","sourcesContent":["import { IOHLC } from '@yuants/data-ohlc';\nimport { createSeriesProvider } from '@yuants/data-series';\nimport { Terminal } from '@yuants/protocol';\nimport { convertDurationToOffset, decodePath, encodePath, formatTime } from '@yuants/utils';\nimport { firstValueFrom, Observable, of, timer } from 'rxjs';\nimport { client } from './api';\nimport { okxBusinessWsClient } from './websocket';\nimport { buildInsertManyIntoTableSQL, requestSQL, writeToSQL } from '@yuants/sql';\n\n// 时间粒度,默认值1m\n// 如 [1m/3m/5m/15m/30m/1H/2H/4H]\n// 香港时间开盘价k线:[6H/12H/1D/1W/1M]\n// UTC时间开盘价k线:[6Hutc/12Hutc/1Dutc/1Wutc/1Mutc]\n\nconst DURATION_TO_OKX_BAR_TYPE: Record<string, string> = {\n PT1M: '1m',\n PT3M: '3m',\n PT5M: '5m',\n PT15M: '15m',\n PT30M: '30m',\n\n PT1H: '1H',\n PT2H: '2H',\n PT4H: '4H',\n PT6H: '6H',\n PT12H: '12H',\n\n P1D: '1D',\n P1W: '1W',\n P1M: '1M',\n};\n\nconst DURATION_TO_OKX_CANDLE_TYPE: Record<string, string> = {\n PT1M: 'mark-price-candle1m',\n PT3M: 'mark-price-candle3m',\n PT5M: 'mark-price-candle5m',\n PT15M: 'mark-price-candle15m',\n PT30M: 'mark-price-candle30m',\n\n PT1H: 'mark-price-candle1H',\n PT2H: 'mark-price-candle2H',\n PT4H: 'mark-price-candle4H',\n PT6H: 'mark-price-candle6H',\n PT12H: 'mark-price-candle12H',\n\n P1D: 'mark-price-candle1D',\n P1W: 'mark-price-candle1W',\n P1M: 'mark-price-candle1M',\n};\n\ncreateSeriesProvider<IOHLC>(Terminal.fromNodeEnv(), {\n tableName: 'ohlc',\n series_id_prefix_parts: ['OKX'],\n reversed: true,\n serviceOptions: { concurrent: 1 },\n queryFn: async function* ({ series_id, ended_at }) {\n const [datasource_id, product_id, duration] = decodePath(series_id);\n const offset = convertDurationToOffset(duration);\n if (!datasource_id) {\n throw 'datasource_id is required';\n }\n if (!product_id) {\n throw 'product_id is required';\n }\n if (!offset) {\n throw 'duration is invalid';\n }\n const [instType, instId] = decodePath(product_id);\n if (!instId) {\n throw `invalid product_id: ${product_id}`;\n }\n\n const bar = DURATION_TO_OKX_BAR_TYPE[duration];\n if (!bar) {\n throw `unsupported duration: ${duration}`;\n }\n\n let currentStartTime = ended_at;\n\n while (true) {\n // 向前翻页,时间降序,不含 after 时间点\n const res = await client.getHistoryCandles({\n instId,\n bar,\n after: `${currentStartTime}`,\n limit: '100',\n });\n if (res.code !== '0') {\n throw `API failed: ${res.code} ${res.msg}`;\n }\n if (res.data.length === 0) break;\n currentStartTime = +res.data[res.data.length - 1][0];\n const data = res.data.map(\n (x): IOHLC => ({\n series_id,\n datasource_id,\n product_id,\n duration,\n created_at: formatTime(+x[0]),\n closed_at: formatTime(+x[0] + offset),\n open: x[1],\n high: x[2],\n low: x[3],\n close: x[4],\n volume: x[5],\n open_interest: '0',\n }),\n );\n yield data;\n await firstValueFrom(timer(1000));\n }\n },\n});\n\nTerminal.fromNodeEnv().channel.publishChannel('ohlc', { pattern: `^OKX/` }, (series_id) => {\n // const [] = decodePath(args)\n const [datasource_id, product_id, duration] = decodePath(series_id);\n const [, instId] = decodePath(product_id);\n const offset = convertDurationToOffset(duration);\n if (!datasource_id) {\n throw 'datasource_id is required';\n }\n if (!product_id) {\n throw 'product_id is required';\n }\n if (!offset) {\n throw 'duration is invalid';\n }\n const candleType = DURATION_TO_OKX_CANDLE_TYPE[duration];\n console.info(formatTime(Date.now()), `subscribe`, series_id);\n return new Observable<IOHLC>((subscriber) => {\n console.info(formatTime(Date.now()), `subscribe`, candleType, instId);\n okxBusinessWsClient.subscribe(candleType, instId, async (data: string[]) => {\n const created_at = Number(data[0]);\n const closed_at = created_at + offset;\n const open = data[1];\n const high = data[2];\n const low = data[3];\n const close = data[4];\n if (isNaN(closed_at)) {\n return;\n }\n console.info(formatTime(Date.now()), `insertData`, data);\n const cancelData: IOHLC = {\n closed_at: formatTime(closed_at),\n created_at: formatTime(created_at),\n open,\n high,\n low,\n close,\n series_id,\n datasource_id,\n duration,\n product_id,\n volume: '0',\n open_interest: '0',\n };\n subscriber.next(cancelData);\n });\n return () => {\n okxBusinessWsClient.unsubscribe(candleType, instId);\n };\n }).pipe(\n writeToSQL({\n tableName: 'ohlc',\n conflictKeys: ['created_at', 'series_id'],\n writeInterval: 1000,\n terminal: Terminal.fromNodeEnv(),\n keyFn: (x) => encodePath(x.created_at, x.series_id),\n }),\n );\n});\n"]}
1
+ {"version":3,"file":"ohlc.js","sourceRoot":"","sources":["../src/ohlc.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AACA,qDAA2D;AAC3D,+CAA4C;AAC5C,yCAA4F;AAC5F,+BAA6D;AAC7D,+BAA+B;AAC/B,2CAA0C;AAC1C,qCAAyC;AAEzC,aAAa;AACb,gCAAgC;AAChC,8BAA8B;AAC9B,8CAA8C;AAE9C,MAAM,wBAAwB,GAA2B;IACvD,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,KAAK;IACZ,KAAK,EAAE,KAAK;IAEZ,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;IACV,IAAI,EAAE,IAAI;IACV,KAAK,EAAE,KAAK;IAEZ,GAAG,EAAE,IAAI;IACT,GAAG,EAAE,IAAI;IACT,GAAG,EAAE,IAAI;CACV,CAAC;AAEF,MAAM,2BAA2B,GAA2B;IAC1D,IAAI,EAAE,qBAAqB;IAC3B,IAAI,EAAE,qBAAqB;IAC3B,IAAI,EAAE,qBAAqB;IAC3B,KAAK,EAAE,sBAAsB;IAC7B,KAAK,EAAE,sBAAsB;IAE7B,IAAI,EAAE,qBAAqB;IAC3B,IAAI,EAAE,qBAAqB;IAC3B,IAAI,EAAE,qBAAqB;IAC3B,IAAI,EAAE,qBAAqB;IAC3B,KAAK,EAAE,sBAAsB;IAE7B,GAAG,EAAE,qBAAqB;IAC1B,GAAG,EAAE,qBAAqB;IAC1B,GAAG,EAAE,qBAAqB;CAC3B,CAAC;AAEF,IAAA,kCAAoB,EAAQ,mBAAQ,CAAC,WAAW,EAAE,EAAE;IAClD,SAAS,EAAE,MAAM;IACjB,sBAAsB,EAAE,CAAC,KAAK,CAAC;IAC/B,QAAQ,EAAE,IAAI;IACd,cAAc,EAAE,EAAE,UAAU,EAAE,CAAC,EAAE;IACjC,OAAO,EAAE,UAAiB,EAAE,SAAS,EAAE,QAAQ,EAAE;;YAC/C,MAAM,CAAC,aAAa,EAAE,UAAU,EAAE,QAAQ,CAAC,GAAG,IAAA,kBAAU,EAAC,SAAS,CAAC,CAAC;YACpE,MAAM,MAAM,GAAG,IAAA,+BAAuB,EAAC,QAAQ,CAAC,CAAC;YACjD,IAAI,CAAC,aAAa,EAAE;gBAClB,MAAM,2BAA2B,CAAC;aACnC;YACD,IAAI,CAAC,UAAU,EAAE;gBACf,MAAM,wBAAwB,CAAC;aAChC;YACD,IAAI,CAAC,MAAM,EAAE;gBACX,MAAM,qBAAqB,CAAC;aAC7B;YACD,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,IAAA,kBAAU,EAAC,UAAU,CAAC,CAAC;YAClD,IAAI,CAAC,MAAM,EAAE;gBACX,MAAM,uBAAuB,UAAU,EAAE,CAAC;aAC3C;YAED,MAAM,GAAG,GAAG,wBAAwB,CAAC,QAAQ,CAAC,CAAC;YAC/C,IAAI,CAAC,GAAG,EAAE;gBACR,MAAM,yBAAyB,QAAQ,EAAE,CAAC;aAC3C;YAED,IAAI,gBAAgB,GAAG,QAAQ,CAAC;YAEhC,OAAO,IAAI,EAAE;gBACX,yBAAyB;gBACzB,MAAM,GAAG,GAAG,cAAM,YAAM,CAAC,iBAAiB,CAAC;oBACzC,MAAM;oBACN,GAAG;oBACH,KAAK,EAAE,GAAG,gBAAgB,EAAE;oBAC5B,KAAK,EAAE,KAAK;iBACb,CAAC,CAAA,CAAC;gBACH,IAAI,GAAG,CAAC,IAAI,KAAK,GAAG,EAAE;oBACpB,MAAM,eAAe,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC;iBAC5C;gBACD,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;oBAAE,MAAM;gBACjC,gBAAgB,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACrD,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CACvB,CAAC,CAAC,EAAS,EAAE,CAAC,CAAC;oBACb,SAAS;oBACT,aAAa;oBACb,UAAU;oBACV,QAAQ;oBACR,UAAU,EAAE,IAAA,kBAAU,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBAC7B,SAAS,EAAE,IAAA,kBAAU,EAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC;oBACrC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;oBACV,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;oBACV,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;oBACT,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;oBACX,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;oBACZ,aAAa,EAAE,GAAG;iBACnB,CAAC,CACH,CAAC;gBACF,oBAAM,IAAI,CAAA,CAAC;gBACX,cAAM,IAAA,qBAAc,EAAC,IAAA,YAAK,EAAC,IAAI,CAAC,CAAC,CAAA,CAAC;aACnC;QACH,CAAC;KAAA;CACF,CAAC,CAAC;AAEH,mBAAQ,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,SAAS,EAAE,EAAE;IACxF,8BAA8B;IAC9B,MAAM,CAAC,aAAa,EAAE,UAAU,EAAE,QAAQ,CAAC,GAAG,IAAA,kBAAU,EAAC,SAAS,CAAC,CAAC;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC,GAAG,IAAA,kBAAU,EAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAA,+BAAuB,EAAC,QAAQ,CAAC,CAAC;IACjD,IAAI,CAAC,aAAa,EAAE;QAClB,MAAM,2BAA2B,CAAC;KACnC;IACD,IAAI,CAAC,UAAU,EAAE;QACf,MAAM,wBAAwB,CAAC;KAChC;IACD,IAAI,CAAC,MAAM,EAAE;QACX,MAAM,qBAAqB,CAAC;KAC7B;IACD,MAAM,UAAU,GAAG,2BAA2B,CAAC,QAAQ,CAAC,CAAC;IACzD,OAAO,CAAC,IAAI,CAAC,IAAA,kBAAU,EAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;IAC7D,OAAO,IAAI,iBAAU,CAAQ,CAAC,UAAU,EAAE,EAAE;QAC1C,OAAO,CAAC,IAAI,CAAC,IAAA,kBAAU,EAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;QACtE,MAAM,mBAAmB,GAAG,IAAI,uBAAW,CAAC,yCAAyC,CAAC,CAAC;QACvF,mBAAmB,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,IAAc,EAAE,EAAE;YACzE,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACnC,MAAM,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;YACtC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACrB,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACrB,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACpB,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACtB,IAAI,KAAK,CAAC,SAAS,CAAC,EAAE;gBACpB,OAAO;aACR;YACD,OAAO,CAAC,IAAI,CAAC,IAAA,kBAAU,EAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,YAAY,EAAE,IAAI,CAAC,CAAC;YACzD,MAAM,UAAU,GAAU;gBACxB,SAAS,EAAE,IAAA,kBAAU,EAAC,SAAS,CAAC;gBAChC,UAAU,EAAE,IAAA,kBAAU,EAAC,UAAU,CAAC;gBAClC,IAAI;gBACJ,IAAI;gBACJ,GAAG;gBACH,KAAK;gBACL,SAAS;gBACT,aAAa;gBACb,QAAQ;gBACR,UAAU;gBACV,MAAM,EAAE,GAAG;gBACX,aAAa,EAAE,GAAG;aACnB,CAAC;YACF,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,EAAE;YACV,mBAAmB,CAAC,WAAW,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACtD,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC,IAAI,CACL,IAAA,gBAAU,EAAC;QACT,SAAS,EAAE,MAAM;QACjB,YAAY,EAAE,CAAC,YAAY,EAAE,WAAW,CAAC;QACzC,aAAa,EAAE,IAAI;QACnB,QAAQ,EAAE,mBAAQ,CAAC,WAAW,EAAE;QAChC,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAA,kBAAU,EAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,SAAS,CAAC;KACpD,CAAC,CACH,CAAC;AACJ,CAAC,CAAC,CAAC","sourcesContent":["import { IOHLC } from '@yuants/data-ohlc';\nimport { createSeriesProvider } from '@yuants/data-series';\nimport { Terminal } from '@yuants/protocol';\nimport { convertDurationToOffset, decodePath, encodePath, formatTime } from '@yuants/utils';\nimport { firstValueFrom, Observable, of, timer } from 'rxjs';\nimport { client } from './api';\nimport { OKXWsClient } from './websocket';\nimport { writeToSQL } from '@yuants/sql';\n\n// 时间粒度,默认值1m\n// 如 [1m/3m/5m/15m/30m/1H/2H/4H]\n// 香港时间开盘价k线:[6H/12H/1D/1W/1M]\n// UTC时间开盘价k线:[6Hutc/12Hutc/1Dutc/1Wutc/1Mutc]\n\nconst DURATION_TO_OKX_BAR_TYPE: Record<string, string> = {\n PT1M: '1m',\n PT3M: '3m',\n PT5M: '5m',\n PT15M: '15m',\n PT30M: '30m',\n\n PT1H: '1H',\n PT2H: '2H',\n PT4H: '4H',\n PT6H: '6H',\n PT12H: '12H',\n\n P1D: '1D',\n P1W: '1W',\n P1M: '1M',\n};\n\nconst DURATION_TO_OKX_CANDLE_TYPE: Record<string, string> = {\n PT1M: 'mark-price-candle1m',\n PT3M: 'mark-price-candle3m',\n PT5M: 'mark-price-candle5m',\n PT15M: 'mark-price-candle15m',\n PT30M: 'mark-price-candle30m',\n\n PT1H: 'mark-price-candle1H',\n PT2H: 'mark-price-candle2H',\n PT4H: 'mark-price-candle4H',\n PT6H: 'mark-price-candle6H',\n PT12H: 'mark-price-candle12H',\n\n P1D: 'mark-price-candle1D',\n P1W: 'mark-price-candle1W',\n P1M: 'mark-price-candle1M',\n};\n\ncreateSeriesProvider<IOHLC>(Terminal.fromNodeEnv(), {\n tableName: 'ohlc',\n series_id_prefix_parts: ['OKX'],\n reversed: true,\n serviceOptions: { concurrent: 1 },\n queryFn: async function* ({ series_id, ended_at }) {\n const [datasource_id, product_id, duration] = decodePath(series_id);\n const offset = convertDurationToOffset(duration);\n if (!datasource_id) {\n throw 'datasource_id is required';\n }\n if (!product_id) {\n throw 'product_id is required';\n }\n if (!offset) {\n throw 'duration is invalid';\n }\n const [instType, instId] = decodePath(product_id);\n if (!instId) {\n throw `invalid product_id: ${product_id}`;\n }\n\n const bar = DURATION_TO_OKX_BAR_TYPE[duration];\n if (!bar) {\n throw `unsupported duration: ${duration}`;\n }\n\n let currentStartTime = ended_at;\n\n while (true) {\n // 向前翻页,时间降序,不含 after 时间点\n const res = await client.getHistoryCandles({\n instId,\n bar,\n after: `${currentStartTime}`,\n limit: '100',\n });\n if (res.code !== '0') {\n throw `API failed: ${res.code} ${res.msg}`;\n }\n if (res.data.length === 0) break;\n currentStartTime = +res.data[res.data.length - 1][0];\n const data = res.data.map(\n (x): IOHLC => ({\n series_id,\n datasource_id,\n product_id,\n duration,\n created_at: formatTime(+x[0]),\n closed_at: formatTime(+x[0] + offset),\n open: x[1],\n high: x[2],\n low: x[3],\n close: x[4],\n volume: x[5],\n open_interest: '0',\n }),\n );\n yield data;\n await firstValueFrom(timer(1000));\n }\n },\n});\n\nTerminal.fromNodeEnv().channel.publishChannel('ohlc', { pattern: `^OKX/` }, (series_id) => {\n // const [] = decodePath(args)\n const [datasource_id, product_id, duration] = decodePath(series_id);\n const [, instId] = decodePath(product_id);\n const offset = convertDurationToOffset(duration);\n if (!datasource_id) {\n throw 'datasource_id is required';\n }\n if (!product_id) {\n throw 'product_id is required';\n }\n if (!offset) {\n throw 'duration is invalid';\n }\n const candleType = DURATION_TO_OKX_CANDLE_TYPE[duration];\n console.info(formatTime(Date.now()), `subscribe`, series_id);\n return new Observable<IOHLC>((subscriber) => {\n console.info(formatTime(Date.now()), `subscribe`, candleType, instId);\n const okxBusinessWsClient = new OKXWsClient('wss://wspap.okx.com:8443/ws/v5/business');\n okxBusinessWsClient.subscribe(candleType, instId, async (data: string[]) => {\n const created_at = Number(data[0]);\n const closed_at = created_at + offset;\n const open = data[1];\n const high = data[2];\n const low = data[3];\n const close = data[4];\n if (isNaN(closed_at)) {\n return;\n }\n console.info(formatTime(Date.now()), `insertData`, data);\n const cancelData: IOHLC = {\n closed_at: formatTime(closed_at),\n created_at: formatTime(created_at),\n open,\n high,\n low,\n close,\n series_id,\n datasource_id,\n duration,\n product_id,\n volume: '0',\n open_interest: '0',\n };\n subscriber.next(cancelData);\n });\n return () => {\n okxBusinessWsClient.unsubscribe(candleType, instId);\n };\n }).pipe(\n writeToSQL({\n tableName: 'ohlc',\n conflictKeys: ['created_at', 'series_id'],\n writeInterval: 1000,\n terminal: Terminal.fromNodeEnv(),\n keyFn: (x) => encodePath(x.created_at, x.series_id),\n }),\n );\n});\n"]}
@@ -1,14 +1,14 @@
1
- declare class OKXWsClient {
1
+ import { Subscription } from 'rxjs';
2
+ export declare class OKXWsClient {
2
3
  ws: WebSocket;
3
4
  connected: boolean;
4
5
  subscriptions: Set<string>;
5
6
  handlers: Record<string, Function>;
6
7
  pendingSub: string[];
8
+ keepAlive: Subscription;
7
9
  constructor(url: string);
8
10
  handleMessage(raw: any): void;
9
11
  subscribe(channel: string, instId?: string, handler?: Function): void;
10
12
  unsubscribe(channel: string, instId?: string): void;
11
13
  }
12
- export declare const okxBusinessWsClient: OKXWsClient;
13
- export {};
14
14
  //# sourceMappingURL=websocket.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../src/websocket.ts"],"names":[],"mappings":"AAGA,cAAM,WAAW;IACf,EAAE,EAAE,SAAS,CAAC;IACd,SAAS,EAAE,OAAO,CAAS;IAC3B,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnC,UAAU,EAAE,MAAM,EAAE,CAAC;gBACT,GAAG,EAAE,MAAM;IAsBvB,aAAa,CAAC,GAAG,EAAE,GAAG;IActB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ;IA0B9D,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;CAc7C;AAED,eAAO,MAAM,mBAAmB,aAA6D,CAAC"}
1
+ {"version":3,"file":"websocket.d.ts","sourceRoot":"","sources":["../src/websocket.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,YAAY,EAAO,MAAM,MAAM,CAAC;AAGnD,qBAAa,WAAW;IACtB,EAAE,EAAE,SAAS,CAAC;IACd,SAAS,EAAE,OAAO,CAAS;IAC3B,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACnC,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,YAAY,CAAC;gBACZ,GAAG,EAAE,MAAM;IAgCvB,aAAa,CAAC,GAAG,EAAE,GAAG;IAiBtB,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ;IA0B9D,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;CAiB7C"}
package/lib/websocket.js CHANGED
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.okxBusinessWsClient = void 0;
3
+ exports.OKXWsClient = void 0;
4
4
  const utils_1 = require("@yuants/utils");
5
+ const rxjs_1 = require("rxjs");
5
6
  // import WebSocket from 'ws';
6
7
  class OKXWsClient {
7
8
  constructor(url) {
@@ -9,6 +10,13 @@ class OKXWsClient {
9
10
  // this.instId = instId;
10
11
  this.ws = new WebSocket(url);
11
12
  this.pendingSub = [];
13
+ this.keepAlive = (0, rxjs_1.interval)(25000)
14
+ .pipe((0, rxjs_1.tap)(() => {
15
+ if (this.connected) {
16
+ this.ws.send('ping');
17
+ }
18
+ }))
19
+ .subscribe();
12
20
  // this.ws.
13
21
  this.ws.addEventListener('open', () => {
14
22
  this.connected = true;
@@ -28,6 +36,9 @@ class OKXWsClient {
28
36
  // 处理消息
29
37
  handleMessage(raw) {
30
38
  var _a, _b;
39
+ if (raw.data === 'pong') {
40
+ return;
41
+ }
31
42
  const msg = JSON.parse(raw.data);
32
43
  if ((_a = msg.arg) === null || _a === void 0 ? void 0 : _a.channel) {
33
44
  const channelId = (0, utils_1.encodePath)(msg.arg.channel, msg.arg.instId);
@@ -75,9 +86,12 @@ class OKXWsClient {
75
86
  };
76
87
  this.ws.send(JSON.stringify(unSubMsg));
77
88
  this.subscriptions.delete(channelId);
89
+ if (this.subscriptions.size === 0) {
90
+ this.keepAlive.unsubscribe();
91
+ }
78
92
  delete this.handlers[channelId];
79
93
  console.info(`📩 Sent unsubscribe for ${channelId}`);
80
94
  }
81
95
  }
82
- exports.okxBusinessWsClient = new OKXWsClient('wss://wspap.okx.com:8443/ws/v5/business');
96
+ exports.OKXWsClient = OKXWsClient;
83
97
  //# sourceMappingURL=websocket.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"websocket.js","sourceRoot":"","sources":["../src/websocket.ts"],"names":[],"mappings":"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","sourcesContent":["import { encodePath, formatTime } from '@yuants/utils';\n// import WebSocket from 'ws';\n\nclass OKXWsClient {\n ws: WebSocket;\n connected: boolean = false;\n subscriptions: Set<string>;\n handlers: Record<string, Function>;\n pendingSub: string[];\n constructor(url: string) {\n // this.instId = instId;\n this.ws = new WebSocket(url);\n this.pendingSub = [];\n // this.ws.\n this.ws.addEventListener('open', () => {\n this.connected = true;\n console.info(formatTime(Date.now()), '✅ WS connected');\n while (this.pendingSub.length > 0) {\n const msg = this.pendingSub.shift();\n if (msg) {\n this.ws.send(msg);\n console.info(formatTime(Date.now()), `📩 Sent subscribe for ${msg}`);\n }\n }\n });\n this.ws.addEventListener('message', (raw) => this.handleMessage(raw));\n this.subscriptions = new Set();\n this.handlers = {}; // key: channel, value: callback\n }\n\n // 处理消息\n handleMessage(raw: any) {\n const msg = JSON.parse(raw.data);\n if (msg.arg?.channel) {\n const channelId = encodePath(msg.arg.channel, msg.arg.instId);\n const data = msg.data?.[0];\n if (data && this.handlers[channelId]) {\n this.handlers[channelId](data, msg.arg);\n }\n } else if (msg.event) {\n console.info('Event:', msg);\n }\n }\n\n // 调用订阅\n subscribe(channel: string, instId?: string, handler?: Function) {\n const channelId = encodePath(channel, instId);\n if (this.subscriptions.has(channelId)) {\n console.info(formatTime(Date.now()), `⚠️ Already subscribed: ${channelId}`);\n return;\n }\n\n const subMsg = {\n op: 'subscribe',\n args: [{ channel, instId }],\n };\n\n if (this.connected) {\n this.ws.send(JSON.stringify(subMsg));\n console.info(formatTime(Date.now()), `📩 Sent subscribe for ${channelId}`);\n } else {\n this.pendingSub.push(JSON.stringify(subMsg));\n console.info(formatTime(Date.now()), `📩 add subscribe for ${channelId} to pending list`);\n }\n this.subscriptions.add(channelId);\n if (handler) {\n this.handlers[channelId] = handler;\n }\n }\n\n // 取消订阅\n unsubscribe(channel: string, instId?: string) {\n const channelId = encodePath(channel, instId);\n if (!this.subscriptions.has(channelId)) return;\n\n const unSubMsg = {\n op: 'unsubscribe',\n args: [{ channel, instId }],\n };\n\n this.ws.send(JSON.stringify(unSubMsg));\n this.subscriptions.delete(channelId);\n delete this.handlers[channelId];\n console.info(`📩 Sent unsubscribe for ${channelId}`);\n }\n}\n\nexport const okxBusinessWsClient = new OKXWsClient('wss://wspap.okx.com:8443/ws/v5/business');\n"]}
1
+ {"version":3,"file":"websocket.js","sourceRoot":"","sources":["../src/websocket.ts"],"names":[],"mappings":"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","sourcesContent":["import { encodePath, formatTime } from '@yuants/utils';\nimport { interval, Subscription, tap } from 'rxjs';\n// import WebSocket from 'ws';\n\nexport class OKXWsClient {\n ws: WebSocket;\n connected: boolean = false;\n subscriptions: Set<string>;\n handlers: Record<string, Function>;\n pendingSub: string[];\n keepAlive: Subscription;\n constructor(url: string) {\n // this.instId = instId;\n this.ws = new WebSocket(url);\n this.pendingSub = [];\n this.keepAlive = interval(25000)\n .pipe(\n tap(() => {\n if (this.connected) {\n this.ws.send('ping');\n }\n }),\n )\n .subscribe();\n // this.ws.\n this.ws.addEventListener('open', () => {\n this.connected = true;\n console.info(formatTime(Date.now()), '✅ WS connected');\n while (this.pendingSub.length > 0) {\n const msg = this.pendingSub.shift();\n if (msg) {\n this.ws.send(msg);\n console.info(formatTime(Date.now()), `📩 Sent subscribe for ${msg}`);\n }\n }\n });\n\n this.ws.addEventListener('message', (raw) => this.handleMessage(raw));\n this.subscriptions = new Set();\n this.handlers = {}; // key: channel, value: callback\n }\n\n // 处理消息\n handleMessage(raw: any) {\n if (raw.data === 'pong') {\n return;\n }\n const msg = JSON.parse(raw.data);\n if (msg.arg?.channel) {\n const channelId = encodePath(msg.arg.channel, msg.arg.instId);\n const data = msg.data?.[0];\n if (data && this.handlers[channelId]) {\n this.handlers[channelId](data, msg.arg);\n }\n } else if (msg.event) {\n console.info('Event:', msg);\n }\n }\n\n // 调用订阅\n subscribe(channel: string, instId?: string, handler?: Function) {\n const channelId = encodePath(channel, instId);\n if (this.subscriptions.has(channelId)) {\n console.info(formatTime(Date.now()), `⚠️ Already subscribed: ${channelId}`);\n return;\n }\n\n const subMsg = {\n op: 'subscribe',\n args: [{ channel, instId }],\n };\n\n if (this.connected) {\n this.ws.send(JSON.stringify(subMsg));\n console.info(formatTime(Date.now()), `📩 Sent subscribe for ${channelId}`);\n } else {\n this.pendingSub.push(JSON.stringify(subMsg));\n console.info(formatTime(Date.now()), `📩 add subscribe for ${channelId} to pending list`);\n }\n this.subscriptions.add(channelId);\n if (handler) {\n this.handlers[channelId] = handler;\n }\n }\n\n // 取消订阅\n unsubscribe(channel: string, instId?: string) {\n const channelId = encodePath(channel, instId);\n if (!this.subscriptions.has(channelId)) return;\n\n const unSubMsg = {\n op: 'unsubscribe',\n args: [{ channel, instId }],\n };\n\n this.ws.send(JSON.stringify(unSubMsg));\n this.subscriptions.delete(channelId);\n if (this.subscriptions.size === 0) {\n this.keepAlive.unsubscribe();\n }\n delete this.handlers[channelId];\n console.info(`📩 Sent unsubscribe for ${channelId}`);\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuants/vendor-okx",
3
- "version": "0.17.2",
3
+ "version": "0.17.4",
4
4
  "bin": "lib/cli.js",
5
5
  "files": [
6
6
  "dist",
@@ -8,18 +8,18 @@
8
8
  "temp"
9
9
  ],
10
10
  "dependencies": {
11
- "@yuants/protocol": "0.37.2",
12
- "@yuants/transfer": "0.2.4",
13
- "@yuants/data-account": "0.3.4",
14
- "@yuants/data-order": "0.2.1",
15
- "@yuants/utils": "0.5.0",
16
- "@yuants/sql": "0.8.3",
17
- "@yuants/data-series": "0.3.16",
18
- "@yuants/data-product": "0.2.5",
19
- "@yuants/data-ohlc": "0.3.12",
20
- "@yuants/data-interest-rate": "0.1.13",
21
- "@yuants/data-quote": "0.2.8",
22
- "@yuants/secret": "0.1.8",
11
+ "@yuants/protocol": "0.37.3",
12
+ "@yuants/transfer": "0.2.5",
13
+ "@yuants/data-account": "0.3.5",
14
+ "@yuants/data-order": "0.2.2",
15
+ "@yuants/utils": "0.6.0",
16
+ "@yuants/sql": "0.8.4",
17
+ "@yuants/data-series": "0.3.17",
18
+ "@yuants/data-product": "0.2.6",
19
+ "@yuants/data-ohlc": "0.3.13",
20
+ "@yuants/data-interest-rate": "0.1.14",
21
+ "@yuants/data-quote": "0.2.9",
22
+ "@yuants/secret": "0.1.9",
23
23
  "rxjs": "~7.5.6",
24
24
  "crypto-js": "^4.2.0",
25
25
  "ws": "~8.8.1"
@@ -31,7 +31,7 @@
31
31
  "@rushstack/heft-node-rig": "~1.10.7",
32
32
  "@types/heft-jest": "1.0.3",
33
33
  "@types/node": "22",
34
- "@yuants/extension": "0.2.20",
34
+ "@yuants/extension": "0.2.21",
35
35
  "@yuants/tool-kit": "0.1.10",
36
36
  "typescript": "~4.7.4",
37
37
  "ts-node": "~10.9.2",
package/temp/image-tag CHANGED
@@ -1 +1 @@
1
- sha-228c9502ea76194e265da7d2fac1dcb84e0d7ba1
1
+ sha-cf8e1e68a882ee8c6bcae8d0bc0c53234fa1f004
@@ -1,6 +1,6 @@
1
1
  {
2
- "apps/vendor-okx/CHANGELOG.json": "e9e9f3ddafe30e5b667b2d328dcc6c667bfa698a",
3
- "apps/vendor-okx/CHANGELOG.md": "b72c199aac0887db83707bd58ea43847304afbd2",
2
+ "apps/vendor-okx/CHANGELOG.json": "297215540209b99df2436c4623e0fbd73916a490",
3
+ "apps/vendor-okx/CHANGELOG.md": "3e72e87148c8338116c0423f8e6dd8e4e5b73cbb",
4
4
  "apps/vendor-okx/README.md": "ac3d1f6c4c8d73066664699b0bb1b01db02e67a2",
5
5
  "apps/vendor-okx/api-extractor.json": "62f4fd324425b9a235f0c117975967aab09ced0c",
6
6
  "apps/vendor-okx/build/Dockerfile": "e625b9593e496c343297c9ce133d6cc4be9617a7",
@@ -8,7 +8,7 @@
8
8
  "apps/vendor-okx/config/rig.json": "f6c7b5537dc77a3170ba9f008bae3b6c3ee11956",
9
9
  "apps/vendor-okx/config/typescript.json": "854907e8a821f2050f6533368db160c649c25348",
10
10
  "apps/vendor-okx/etc/vendor-okx.api.md": "92c54ccd547d2ad81ca6088158ca193e85c208df",
11
- "apps/vendor-okx/package.json": "bc9c23f69c35eca3a4923f35b050135aec0dd676",
11
+ "apps/vendor-okx/package.json": "78e739d1a3d0956b73c753f7ed08d531b1cdaae9",
12
12
  "apps/vendor-okx/src/account.ts": "7e8bb44845269a401a850aff2e5bf170b0811bd8",
13
13
  "apps/vendor-okx/src/api.ts": "0433a359ec1fb84c866c1875b630cbb861696533",
14
14
  "apps/vendor-okx/src/cli.ts": "9bf6b5559a6c6f33da20e74cc6c5d702c60ec891",
@@ -18,25 +18,25 @@
18
18
  "apps/vendor-okx/src/interest_rate.ts": "da173624ffed4cb083d797328174fe717809769c",
19
19
  "apps/vendor-okx/src/legacy_index.ts": "19f9e4af4b6b8ae846e0800b1bd52d5eeaa8a2ce",
20
20
  "apps/vendor-okx/src/logger.ts": "d25d427e74f46819a601e0cb17d5358b22c8db7b",
21
- "apps/vendor-okx/src/ohlc.ts": "ffbe2feadd43befb925984fdc704d00527717e92",
21
+ "apps/vendor-okx/src/ohlc.ts": "0b8c9b32238a4e26954dbd5360e129b3850df1ae",
22
22
  "apps/vendor-okx/src/order.ts": "09509ae5af4b212cc1c99c55c436b3b0ce8bda33",
23
23
  "apps/vendor-okx/src/product.ts": "a2e7feb86bc01fe3b1af6dcb9a9ebfba6be91434",
24
24
  "apps/vendor-okx/src/quote.ts": "b8dd019e6cceb50e486a9d41e54385bda4e21ab0",
25
- "apps/vendor-okx/src/websocket.ts": "7a22838b75247cdc3da90c8601100b6e8b34a350",
25
+ "apps/vendor-okx/src/websocket.ts": "59791907faef7adf2d1d4b6876cc6a476b5f7e3e",
26
26
  "apps/vendor-okx/tsconfig.json": "81da8f78196974b5d15da0edb6b2d9f48641063c",
27
27
  "apps/vendor-okx/.rush/temp/shrinkwrap-deps.json": "87df045a10e829fd62d50013da30fd929442d54c",
28
- "libraries/protocol/temp/package-deps.json": "d326f24867d9ae3fef16ff84ba537eabb7c8adf0",
29
- "libraries/transfer/temp/package-deps.json": "cb2786055e5e79cd7d9d0f5787e300ca1c0bf002",
30
- "libraries/data-account/temp/package-deps.json": "0e5bd33f40288d3bc2a3b32cf51188a346a8dd34",
31
- "libraries/data-order/temp/package-deps.json": "58c4daa9bd7c6420bbf92efd003aa311ade858ae",
32
- "libraries/utils/temp/package-deps.json": "c747617da1c0a40843603c62a7477da641ff0aef",
33
- "libraries/sql/temp/package-deps.json": "1cb2248873d01ed732e8473f7b242a41f987fdd7",
34
- "libraries/data-series/temp/package-deps.json": "3ba9330800ae3952ed7ba430526596a24d1e8eb7",
35
- "libraries/data-product/temp/package-deps.json": "634e636d948295079b02dbeffb84f6d52872fda8",
36
- "libraries/data-ohlc/temp/package-deps.json": "f05db3bced2139edafc9a3d2c647d0987f974ce7",
37
- "libraries/data-interest-rate/temp/package-deps.json": "420702140b635d7fbbd0524108a827b12efde639",
38
- "libraries/data-quote/temp/package-deps.json": "477aa425b15f7308c292c4d5d4d44e42e69765a3",
39
- "libraries/secret/temp/package-deps.json": "892d858510fdede82540567f298604c7495d5793",
40
- "libraries/extension/temp/package-deps.json": "96816518ae9dc050cafe0b8fbce95cbb59d06ee6",
28
+ "libraries/protocol/temp/package-deps.json": "43291b31649f44821b64235587e30fe4663fc305",
29
+ "libraries/transfer/temp/package-deps.json": "a662579703128c1770f30f8ffaab3f5a233f9d48",
30
+ "libraries/data-account/temp/package-deps.json": "8cd059657ea073e638ba6dacf3444b7e9bd363e7",
31
+ "libraries/data-order/temp/package-deps.json": "0ec7bb60f94eb437a05ee53e46841ca0ed718635",
32
+ "libraries/utils/temp/package-deps.json": "ecdd5e56cb2b6db83ee9caf8784ad342484f1699",
33
+ "libraries/sql/temp/package-deps.json": "ccd7161a4384bf97c6a29bff21030ed3bea5336f",
34
+ "libraries/data-series/temp/package-deps.json": "4024c0f6e805fecc48dbdc2045d3d3c0c5c609db",
35
+ "libraries/data-product/temp/package-deps.json": "08342cfa222eca4cd64d23f753ae9a2cd5254343",
36
+ "libraries/data-ohlc/temp/package-deps.json": "d8812a8cdf4b60e7d3a66ff723f6d9ec82f27259",
37
+ "libraries/data-interest-rate/temp/package-deps.json": "27c147717413bf219a8aef339c14411290cd7d93",
38
+ "libraries/data-quote/temp/package-deps.json": "06ec122f1a8d33627668e30ea2a7ecbe7c04e12f",
39
+ "libraries/secret/temp/package-deps.json": "9ab6e32f718f74f5358a3950ca4bf1fdb04642ca",
40
+ "libraries/extension/temp/package-deps.json": "f22ec5c30214f7aeeda63f46bd920290be555f57",
41
41
  "tools/toolkit/temp/package-deps.json": "eb0447c467da3a90db0913ed01e42ec0de840234"
42
42
  }