@tigeropenapi/tigeropen 0.1.0 → 0.3.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 (129) hide show
  1. package/README.md +475 -104
  2. package/dist/cjs/client/api-request.js +16 -10
  3. package/dist/cjs/client/api-response.js +23 -3
  4. package/dist/cjs/client/case-convert.js +35 -0
  5. package/dist/cjs/client/http-client.js +46 -20
  6. package/dist/cjs/client/index.js +6 -2
  7. package/dist/cjs/config/client-config.js +130 -49
  8. package/dist/cjs/config/domain.js +21 -2
  9. package/dist/cjs/config/index.js +3 -1
  10. package/dist/cjs/index.js +1 -1
  11. package/dist/cjs/model/contract.js +1 -2
  12. package/dist/cjs/model/order-helpers.js +9 -9
  13. package/dist/cjs/model/order.js +5 -2
  14. package/dist/cjs/model/position.js +1 -2
  15. package/dist/cjs/model/quote.js +7 -0
  16. package/dist/cjs/model/trade.js +2 -0
  17. package/dist/cjs/push/index.js +6 -3
  18. package/dist/cjs/push/pb/AssetData.js +208 -0
  19. package/dist/cjs/push/pb/KlineData.js +184 -0
  20. package/dist/cjs/push/pb/OptionTopData.js +427 -0
  21. package/dist/cjs/push/pb/OrderStatusData.js +568 -0
  22. package/dist/cjs/push/pb/OrderTransactionData.js +256 -0
  23. package/dist/cjs/push/pb/PositionData.js +316 -0
  24. package/dist/cjs/push/pb/PushData.js +219 -0
  25. package/dist/cjs/push/pb/QuoteBBOData.js +160 -0
  26. package/dist/cjs/push/pb/QuoteBasicData.js +329 -0
  27. package/dist/cjs/push/pb/QuoteData.js +507 -0
  28. package/dist/cjs/push/pb/QuoteDepthData.js +220 -0
  29. package/dist/cjs/push/pb/Request.js +278 -0
  30. package/dist/cjs/push/pb/Response.js +97 -0
  31. package/dist/cjs/push/pb/SocketCommon.js +86 -0
  32. package/dist/cjs/push/pb/StockTopData.js +199 -0
  33. package/dist/cjs/push/pb/TickData.js +202 -0
  34. package/dist/cjs/push/pb/TradeTickData.js +308 -0
  35. package/dist/cjs/push/pb/index.js +49 -0
  36. package/dist/cjs/push/proto-message.js +129 -0
  37. package/dist/cjs/push/push-client.js +292 -164
  38. package/dist/cjs/push/push-message.js +4 -60
  39. package/dist/cjs/push/varint.js +76 -0
  40. package/dist/cjs/quote/index.js +3 -2
  41. package/dist/cjs/quote/quote-client.js +128 -94
  42. package/dist/cjs/signer/signer.js +10 -10
  43. package/dist/cjs/trade/trade-client.js +56 -62
  44. package/dist/esm/client/api-request.js +14 -8
  45. package/dist/esm/client/api-response.js +22 -3
  46. package/dist/esm/client/case-convert.js +31 -0
  47. package/dist/esm/client/http-client.js +47 -21
  48. package/dist/esm/client/index.js +3 -2
  49. package/dist/esm/config/client-config.js +131 -51
  50. package/dist/esm/config/domain.js +20 -2
  51. package/dist/esm/config/index.js +2 -2
  52. package/dist/esm/index.js +1 -1
  53. package/dist/esm/model/contract.js +1 -2
  54. package/dist/esm/model/order-helpers.js +9 -9
  55. package/dist/esm/model/order.js +5 -2
  56. package/dist/esm/model/position.js +1 -2
  57. package/dist/esm/model/quote.js +6 -0
  58. package/dist/esm/model/trade.js +1 -0
  59. package/dist/esm/push/index.js +4 -2
  60. package/dist/esm/push/pb/AssetData.js +205 -0
  61. package/dist/esm/push/pb/KlineData.js +181 -0
  62. package/dist/esm/push/pb/OptionTopData.js +424 -0
  63. package/dist/esm/push/pb/OrderStatusData.js +565 -0
  64. package/dist/esm/push/pb/OrderTransactionData.js +253 -0
  65. package/dist/esm/push/pb/PositionData.js +313 -0
  66. package/dist/esm/push/pb/PushData.js +216 -0
  67. package/dist/esm/push/pb/QuoteBBOData.js +157 -0
  68. package/dist/esm/push/pb/QuoteBasicData.js +326 -0
  69. package/dist/esm/push/pb/QuoteData.js +504 -0
  70. package/dist/esm/push/pb/QuoteDepthData.js +217 -0
  71. package/dist/esm/push/pb/Request.js +275 -0
  72. package/dist/esm/push/pb/Response.js +94 -0
  73. package/dist/esm/push/pb/SocketCommon.js +83 -0
  74. package/dist/esm/push/pb/StockTopData.js +196 -0
  75. package/dist/esm/push/pb/TickData.js +199 -0
  76. package/dist/esm/push/pb/TradeTickData.js +305 -0
  77. package/dist/esm/push/pb/index.js +25 -0
  78. package/dist/esm/push/proto-message.js +121 -0
  79. package/dist/esm/push/push-client.js +260 -165
  80. package/dist/esm/push/push-message.js +3 -56
  81. package/dist/esm/push/varint.js +72 -0
  82. package/dist/esm/quote/index.js +2 -2
  83. package/dist/esm/quote/quote-client.js +127 -94
  84. package/dist/esm/signer/signer.js +10 -10
  85. package/dist/esm/trade/trade-client.js +56 -62
  86. package/dist/types/client/api-request.d.ts +12 -11
  87. package/dist/types/client/api-response.d.ts +15 -7
  88. package/dist/types/client/case-convert.d.ts +16 -0
  89. package/dist/types/client/http-client.d.ts +26 -14
  90. package/dist/types/client/index.d.ts +3 -2
  91. package/dist/types/config/client-config.d.ts +29 -13
  92. package/dist/types/config/domain.d.ts +9 -0
  93. package/dist/types/config/index.d.ts +2 -2
  94. package/dist/types/index.d.ts +1 -1
  95. package/dist/types/model/contract.d.ts +13 -29
  96. package/dist/types/model/order-helpers.d.ts +21 -20
  97. package/dist/types/model/order.d.ts +101 -55
  98. package/dist/types/model/position.d.ts +26 -24
  99. package/dist/types/model/quote.d.ts +311 -0
  100. package/dist/types/model/trade.d.ts +113 -0
  101. package/dist/types/push/callbacks.d.ts +32 -51
  102. package/dist/types/push/index.d.ts +5 -3
  103. package/dist/types/push/pb/AssetData.d.ts +47 -0
  104. package/dist/types/push/pb/KlineData.d.ts +43 -0
  105. package/dist/types/push/pb/OptionTopData.d.ts +76 -0
  106. package/dist/types/push/pb/OrderStatusData.d.ts +96 -0
  107. package/dist/types/push/pb/OrderTransactionData.d.ts +51 -0
  108. package/dist/types/push/pb/PositionData.d.ts +63 -0
  109. package/dist/types/push/pb/PushData.d.ts +46 -0
  110. package/dist/types/push/pb/QuoteBBOData.d.ts +35 -0
  111. package/dist/types/push/pb/QuoteBasicData.d.ts +66 -0
  112. package/dist/types/push/pb/QuoteData.d.ts +94 -0
  113. package/dist/types/push/pb/QuoteDepthData.d.ts +37 -0
  114. package/dist/types/push/pb/Request.d.ts +44 -0
  115. package/dist/types/push/pb/Response.d.ts +30 -0
  116. package/dist/types/push/pb/SocketCommon.d.ts +64 -0
  117. package/dist/types/push/pb/StockTopData.d.ts +37 -0
  118. package/dist/types/push/pb/TickData.d.ts +44 -0
  119. package/dist/types/push/pb/TradeTickData.d.ts +53 -0
  120. package/dist/types/push/pb/index.d.ts +39 -0
  121. package/dist/types/push/proto-message.d.ts +33 -0
  122. package/dist/types/push/push-client.d.ts +69 -68
  123. package/dist/types/push/push-message.d.ts +3 -147
  124. package/dist/types/push/varint.d.ts +23 -0
  125. package/dist/types/quote/index.d.ts +2 -2
  126. package/dist/types/quote/quote-client.d.ts +41 -47
  127. package/dist/types/signer/signer.d.ts +6 -6
  128. package/dist/types/trade/trade-client.d.ts +34 -38
  129. package/package.json +11 -6
@@ -1,19 +1,78 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.PushClient = exports.ConnectionState = void 0;
37
+ /**
38
+ * PushClient - TCP + TLS push client (Protobuf protocol)
39
+ *
40
+ * Connects to the push server via raw TCP + TLS to receive real-time
41
+ * market data and account push notifications.
42
+ * Uses varint32 length-prefixed + Protobuf binary frame format,
43
+ * aligned with the Java SDK's Netty + Protobuf implementation.
44
+ * Supports connection authentication, subscribe/unsubscribe, callbacks,
45
+ * heartbeat keep-alive, and automatic reconnection.
46
+ */
47
+ const tls = __importStar(require("tls"));
4
48
  const signer_1 = require("../signer/signer");
5
49
  const push_message_1 = require("./push-message");
6
- /** 默认推送服务器地址 */
7
- const DEFAULT_PUSH_URL = 'wss://openapi-push.tigerfintech.com';
8
- /** 默认心跳间隔(毫秒) */
50
+ const Request_1 = require("./pb/Request");
51
+ const Response_1 = require("./pb/Response");
52
+ const SocketCommon_1 = require("./pb/SocketCommon");
53
+ const varint_1 = require("./varint");
54
+ const proto_message_1 = require("./proto-message");
55
+ /** Default push server host */
56
+ const DEFAULT_PUSH_HOST = 'openapi.tigerfintech.com';
57
+ /** Default push server port */
58
+ const DEFAULT_PUSH_PORT = 9883;
59
+ /** Default heartbeat interval (ms) */
9
60
  const DEFAULT_HEARTBEAT_INTERVAL = 10000;
10
- /** 默认重连间隔(毫秒) */
61
+ /** Default reconnect interval (ms) */
11
62
  const DEFAULT_RECONNECT_INTERVAL = 5000;
12
- /** 最大重连间隔(毫秒) */
63
+ /** Max reconnect interval (ms) */
13
64
  const MAX_RECONNECT_INTERVAL = 60000;
14
- /** 默认连接超时(毫秒) */
65
+ /** Default connect timeout (ms) */
15
66
  const DEFAULT_CONNECT_TIMEOUT = 30000;
16
- /** 连接状态 */
67
+ /** SDK version identifier */
68
+ const SDK_VERSION = 'typescript/0.1.0';
69
+ /** Protocol version */
70
+ const ACCEPT_VERSION = '1.0';
71
+ /** Default send heartbeat interval (ms) */
72
+ const DEFAULT_SEND_INTERVAL = 10000;
73
+ /** Default receive heartbeat interval (ms) */
74
+ const DEFAULT_RECEIVE_INTERVAL = 10000;
75
+ /** Connection state */
17
76
  var ConnectionState;
18
77
  (function (ConnectionState) {
19
78
  ConnectionState[ConnectionState["Disconnected"] = 0] = "Disconnected";
@@ -21,151 +80,220 @@ var ConnectionState;
21
80
  ConnectionState[ConnectionState["Connected"] = 2] = "Connected";
22
81
  })(ConnectionState || (exports.ConnectionState = ConnectionState = {}));
23
82
  /**
24
- * PushClient WebSocket 推送客户端
83
+ * PushClient - TCP + TLS push client (Protobuf protocol)
25
84
  */
26
85
  class PushClient {
27
86
  constructor(config, options) {
28
- this.ws = null;
87
+ this.socket = null;
29
88
  this._state = ConnectionState.Disconnected;
30
89
  this.callbacks = {};
31
- /** 订阅状态管理:subject -> Set<symbol> */
90
+ /** Subscription state: subject -> Set<symbol> */
32
91
  this.subscriptions = new Map();
33
- /** 账户级别订阅 */
92
+ /** Account-level subscriptions */
34
93
  this.accountSubs = new Set();
35
94
  this.heartbeatTimer = null;
36
95
  this.reconnectTimer = null;
37
96
  this.stopped = false;
38
- /** 可注入的 WebSocket 工厂(用于测试) */
39
- this.wsFactory = null;
97
+ /** TCP stream receive buffer */
98
+ this.recvBuffer = Buffer.alloc(0);
99
+ /** Injectable TLS socket factory (for testing) */
100
+ this.socketFactory = null;
40
101
  this.config = config;
41
- this.pushUrl = options?.pushUrl ?? DEFAULT_PUSH_URL;
102
+ this.pushHost = options?.pushHost ?? DEFAULT_PUSH_HOST;
103
+ this.pushPort = options?.pushPort ?? DEFAULT_PUSH_PORT;
42
104
  this.heartbeatInterval = options?.heartbeatInterval ?? DEFAULT_HEARTBEAT_INTERVAL;
43
105
  this.reconnectInterval = options?.reconnectInterval ?? DEFAULT_RECONNECT_INTERVAL;
44
106
  this.autoReconnect = options?.autoReconnect ?? true;
45
107
  this.connectTimeout = options?.connectTimeout ?? DEFAULT_CONNECT_TIMEOUT;
108
+ this.useFullTick = options?.useFullTick ?? false;
46
109
  }
47
- /** 获取当前连接状态 */
110
+ /** Get current connection state */
48
111
  get state() {
49
112
  return this._state;
50
113
  }
51
- /** 设置回调函数集合 */
114
+ /** Set callback functions */
52
115
  setCallbacks(cb) {
53
116
  this.callbacks = cb;
54
117
  }
55
- /** 连接到推送服务器并进行认证 */
118
+ /** Connect to the push server and authenticate */
56
119
  connect() {
57
120
  return new Promise((resolve, reject) => {
58
121
  if (this._state !== ConnectionState.Disconnected) {
59
- reject(new Error('客户端已连接或正在连接中'));
122
+ reject(new Error('Client is already connected or connecting'));
60
123
  return;
61
124
  }
62
125
  this._state = ConnectionState.Connecting;
63
126
  this.stopped = false;
64
- const ws = this.createWebSocket(this.pushUrl);
65
- this.ws = ws;
127
+ this.recvBuffer = Buffer.alloc(0);
128
+ const socket = this.createSocket(this.pushHost, this.pushPort);
129
+ this.socket = socket;
130
+ let settled = false;
66
131
  const timeout = setTimeout(() => {
67
- ws.close();
68
- this._state = ConnectionState.Disconnected;
69
- this.ws = null;
70
- reject(new Error('连接超时'));
132
+ if (!settled) {
133
+ settled = true;
134
+ socket.destroy();
135
+ this._state = ConnectionState.Disconnected;
136
+ this.socket = null;
137
+ reject(new Error('Connect timeout'));
138
+ }
71
139
  }, this.connectTimeout);
72
- ws.onopen = () => {
73
- clearTimeout(timeout);
74
- // 发送认证消息
75
- try {
76
- this.authenticate();
140
+ // Resolve once we receive CONNECTED response from server
141
+ const onConnected = () => {
142
+ if (!settled) {
143
+ settled = true;
144
+ clearTimeout(timeout);
77
145
  this._state = ConnectionState.Connected;
78
146
  this.startHeartbeat();
79
147
  this.callbacks.onConnect?.();
80
148
  resolve();
81
149
  }
150
+ };
151
+ socket.on('connect', () => {
152
+ // TLS handshake complete, send authentication message
153
+ try {
154
+ this.authenticate();
155
+ }
82
156
  catch (err) {
83
- ws.close();
84
- this._state = ConnectionState.Disconnected;
85
- this.ws = null;
86
- reject(err);
157
+ if (!settled) {
158
+ settled = true;
159
+ clearTimeout(timeout);
160
+ socket.destroy();
161
+ this._state = ConnectionState.Disconnected;
162
+ this.socket = null;
163
+ reject(err);
164
+ }
87
165
  }
88
- };
89
- ws.onmessage = (ev) => {
90
- this.handleMessage(String(ev.data));
91
- };
92
- ws.onclose = () => {
166
+ });
167
+ socket.on('data', (chunk) => {
168
+ this.handleData(chunk, onConnected);
169
+ });
170
+ socket.on('close', () => {
93
171
  if (this.stopped)
94
172
  return;
95
173
  this.stopHeartbeat();
96
174
  const wasConnected = this._state === ConnectionState.Connected;
97
175
  this._state = ConnectionState.Disconnected;
98
- this.ws = null;
176
+ this.socket = null;
99
177
  if (wasConnected && this.autoReconnect && !this.stopped) {
100
178
  this.scheduleReconnect();
101
179
  }
102
- };
103
- ws.onerror = (ev) => {
104
- if (this._state === ConnectionState.Connecting) {
180
+ });
181
+ socket.on('error', (err) => {
182
+ if (!settled) {
183
+ settled = true;
105
184
  clearTimeout(timeout);
106
185
  this._state = ConnectionState.Disconnected;
107
- this.ws = null;
108
- reject(new Error('WebSocket 连接失败'));
186
+ this.socket = null;
187
+ reject(new Error(`TLS connection failed: ${err.message}`));
109
188
  }
110
189
  else {
111
- this.callbacks.onError?.(new Error('WebSocket 错误'));
190
+ this.callbacks.onError?.(new Error(`TLS error: ${err.message}`));
112
191
  }
113
- };
192
+ });
114
193
  });
115
194
  }
116
- /** 断开连接 */
195
+ /** Disconnect from the push server */
117
196
  disconnect() {
118
197
  this.stopped = true;
119
198
  this.stopHeartbeat();
120
199
  this.clearReconnectTimer();
121
- if (this.ws) {
122
- this.ws.onclose = null;
123
- this.ws.onerror = null;
124
- this.ws.onmessage = null;
125
- this.ws.close();
126
- this.ws = null;
200
+ if (this.socket) {
201
+ // Send DISCONNECT message before closing
202
+ try {
203
+ const req = (0, proto_message_1.buildDisconnectMessage)();
204
+ this.sendMessage(req);
205
+ }
206
+ catch {
207
+ // Ignore send failure, continue closing
208
+ }
209
+ this.socket.destroy();
210
+ this.socket = null;
127
211
  }
128
212
  this._state = ConnectionState.Disconnected;
213
+ this.recvBuffer = Buffer.alloc(0);
129
214
  this.callbacks.onDisconnect?.();
130
215
  }
131
- /** 发送认证消息 */
216
+ /** Send authentication message */
132
217
  authenticate() {
133
- const ts = new Date().toISOString().replace('T', ' ').substring(0, 19);
218
+ // Sign content is the tigerId string itself (aligned with Java SDK)
134
219
  const sign = (0, signer_1.signWithRSA)(this.config.privateKey, this.config.tigerId);
135
- const req = {
136
- tigerId: this.config.tigerId,
137
- sign,
138
- timestamp: ts,
139
- version: '2.0',
140
- };
141
- const msg = (0, push_message_1.createPushMessage)(push_message_1.MessageType.Connect, undefined, req);
142
- this.sendMessage(msg);
220
+ const req = (0, proto_message_1.buildConnectMessage)(this.config.tigerId, sign, SDK_VERSION, ACCEPT_VERSION, DEFAULT_SEND_INTERVAL, DEFAULT_RECEIVE_INTERVAL, this.useFullTick);
221
+ this.sendMessage(req);
143
222
  }
144
- /** 发送消息 */
223
+ /** Send a Protobuf Request message (varint32 length prefix + binary) */
145
224
  sendMessage(msg) {
146
- if (!this.ws)
147
- throw new Error('WebSocket 连接未建立');
148
- this.ws.send((0, push_message_1.serializeMessage)(msg));
149
- }
150
- /** 创建 WebSocket 实例 */
151
- createWebSocket(url) {
152
- if (this.wsFactory)
153
- return this.wsFactory(url);
154
- // 动态导入 ws 库(Node.js 环境)
155
- // eslint-disable-next-line @typescript-eslint/no-require-imports
156
- const WS = require('ws');
157
- return new WS(url);
158
- }
159
- /** 心跳保活 */
225
+ if (!this.socket)
226
+ throw new Error('TLS connection not established');
227
+ const encoded = Request_1.Request.encode(msg).finish();
228
+ const framed = (0, varint_1.encodeVarint32)(encoded);
229
+ this.socket.write(framed);
230
+ }
231
+ /** Create a TLS socket instance */
232
+ createSocket(host, port) {
233
+ if (this.socketFactory)
234
+ return this.socketFactory(host, port);
235
+ return tls.connect({ host, port, rejectUnauthorized: false });
236
+ }
237
+ /** Handle incoming TCP data: buffer + decode varint32 frames */
238
+ handleData(chunk, onConnected) {
239
+ this.recvBuffer = Buffer.concat([this.recvBuffer, chunk]);
240
+ while (this.recvBuffer.length > 0) {
241
+ const frame = (0, varint_1.decodeVarint32)(new Uint8Array(this.recvBuffer));
242
+ if (!frame)
243
+ break; // Incomplete frame, wait for more data
244
+ this.recvBuffer = Buffer.from(frame.remaining);
245
+ // Deserialize Protobuf Response
246
+ let response;
247
+ try {
248
+ response = Response_1.Response.decode(frame.message);
249
+ }
250
+ catch {
251
+ this.callbacks.onError?.(new Error('Protobuf deserialization failed'));
252
+ continue;
253
+ }
254
+ this.handleResponse(response, onConnected);
255
+ }
256
+ }
257
+ /** Handle a decoded Response message */
258
+ handleResponse(response, onConnected) {
259
+ const cb = this.callbacks;
260
+ switch (response.command) {
261
+ case SocketCommon_1.SocketCommon_Command.CONNECTED:
262
+ // Server confirmed authentication
263
+ onConnected?.();
264
+ break;
265
+ case SocketCommon_1.SocketCommon_Command.HEARTBEAT:
266
+ // Heartbeat response, ignore
267
+ break;
268
+ case SocketCommon_1.SocketCommon_Command.MESSAGE:
269
+ if (response.body) {
270
+ this.dispatchPushData(response.body);
271
+ }
272
+ break;
273
+ case SocketCommon_1.SocketCommon_Command.ERROR:
274
+ cb.onError?.(new Error(`Server error: ${response.msg ?? 'unknown error'}`));
275
+ // Check for kickout
276
+ if (response.msg && response.msg.toLowerCase().includes('kickout')) {
277
+ cb.onKickout?.(response.msg);
278
+ }
279
+ break;
280
+ case SocketCommon_1.SocketCommon_Command.DISCONNECT:
281
+ cb.onDisconnect?.();
282
+ break;
283
+ default:
284
+ break;
285
+ }
286
+ }
287
+ /** Heartbeat keep-alive */
160
288
  startHeartbeat() {
161
289
  this.stopHeartbeat();
162
290
  this.heartbeatTimer = setInterval(() => {
163
291
  try {
164
- const msg = (0, push_message_1.createPushMessage)(push_message_1.MessageType.Heartbeat);
165
- this.sendMessage(msg);
292
+ const req = (0, proto_message_1.buildHeartBeatMessage)();
293
+ this.sendMessage(req);
166
294
  }
167
295
  catch {
168
- // 心跳发送失败,连接可能已断开
296
+ // Heartbeat send failed, connection may be broken
169
297
  }
170
298
  }, this.heartbeatInterval);
171
299
  }
@@ -175,7 +303,7 @@ class PushClient {
175
303
  this.heartbeatTimer = null;
176
304
  }
177
305
  }
178
- /** 自动重连 */
306
+ /** Auto reconnect with exponential backoff */
179
307
  scheduleReconnect() {
180
308
  let interval = this.reconnectInterval;
181
309
  const attempt = () => {
@@ -198,7 +326,7 @@ class PushClient {
198
326
  this.reconnectTimer = null;
199
327
  }
200
328
  }
201
- /** 重连后恢复订阅 */
329
+ /** Resubscribe after reconnection */
202
330
  resubscribe() {
203
331
  for (const [subject, symbols] of this.subscriptions) {
204
332
  this.doSubscribe(subject, Array.from(symbols));
@@ -207,81 +335,81 @@ class PushClient {
207
335
  this.doSubscribe(subject, undefined, this.config.account);
208
336
  }
209
337
  }
210
- /** 处理收到的消息 */
211
- handleMessage(raw) {
212
- let msg;
213
- try {
214
- msg = (0, push_message_1.deserializeMessage)(raw);
215
- }
216
- catch {
217
- this.callbacks.onError?.(new Error('反序列化消息失败'));
218
- return;
219
- }
338
+ /** Dispatch push data to the appropriate callback based on dataType */
339
+ dispatchPushData(pushData) {
220
340
  const cb = this.callbacks;
221
- switch (msg.type) {
222
- case push_message_1.MessageType.Kickout:
223
- cb.onKickout?.(msg.data);
224
- break;
225
- case push_message_1.MessageType.Error:
226
- cb.onError?.(new Error(`服务端错误: ${msg.data}`));
227
- break;
228
- case push_message_1.MessageType.Quote:
229
- cb.onQuote?.(msg.data);
230
- break;
231
- case push_message_1.MessageType.Tick:
232
- cb.onTick?.(msg.data);
341
+ switch (pushData.dataType) {
342
+ case SocketCommon_1.SocketCommon_DataType.Quote:
343
+ if (pushData.quoteData)
344
+ cb.onQuote?.(pushData.quoteData);
233
345
  break;
234
- case push_message_1.MessageType.Depth:
235
- cb.onDepth?.(msg.data);
346
+ case SocketCommon_1.SocketCommon_DataType.Option:
347
+ if (pushData.quoteData)
348
+ cb.onOption?.(pushData.quoteData);
236
349
  break;
237
- case push_message_1.MessageType.Option:
238
- cb.onOption?.(msg.data);
350
+ case SocketCommon_1.SocketCommon_DataType.Future:
351
+ if (pushData.quoteData)
352
+ cb.onFuture?.(pushData.quoteData);
239
353
  break;
240
- case push_message_1.MessageType.Future:
241
- cb.onFuture?.(msg.data);
354
+ case SocketCommon_1.SocketCommon_DataType.QuoteDepth:
355
+ if (pushData.quoteDepthData)
356
+ cb.onDepth?.(pushData.quoteDepthData);
242
357
  break;
243
- case push_message_1.MessageType.Kline:
244
- cb.onKline?.(msg.data);
358
+ case SocketCommon_1.SocketCommon_DataType.TradeTick:
359
+ if (pushData.tradeTickData)
360
+ cb.onTick?.(pushData.tradeTickData);
245
361
  break;
246
- case push_message_1.MessageType.Asset:
247
- cb.onAsset?.(msg.data);
362
+ case SocketCommon_1.SocketCommon_DataType.Asset:
363
+ if (pushData.assetData)
364
+ cb.onAsset?.(pushData.assetData);
248
365
  break;
249
- case push_message_1.MessageType.Position:
250
- cb.onPosition?.(msg.data);
366
+ case SocketCommon_1.SocketCommon_DataType.Position:
367
+ if (pushData.positionData)
368
+ cb.onPosition?.(pushData.positionData);
251
369
  break;
252
- case push_message_1.MessageType.Order:
253
- cb.onOrder?.(msg.data);
370
+ case SocketCommon_1.SocketCommon_DataType.OrderStatus:
371
+ if (pushData.orderStatusData)
372
+ cb.onOrder?.(pushData.orderStatusData);
254
373
  break;
255
- case push_message_1.MessageType.Transaction:
256
- cb.onTransaction?.(msg.data);
374
+ case SocketCommon_1.SocketCommon_DataType.OrderTransaction:
375
+ if (pushData.orderTransactionData)
376
+ cb.onTransaction?.(pushData.orderTransactionData);
257
377
  break;
258
- case push_message_1.MessageType.StockTop:
259
- cb.onStockTop?.(msg.data);
378
+ case SocketCommon_1.SocketCommon_DataType.StockTop:
379
+ if (pushData.stockTopData)
380
+ cb.onStockTop?.(pushData.stockTopData);
260
381
  break;
261
- case push_message_1.MessageType.OptionTop:
262
- cb.onOptionTop?.(msg.data);
382
+ case SocketCommon_1.SocketCommon_DataType.OptionTop:
383
+ if (pushData.optionTopData)
384
+ cb.onOptionTop?.(pushData.optionTopData);
263
385
  break;
264
- case push_message_1.MessageType.FullTick:
265
- cb.onFullTick?.(msg.data);
386
+ case SocketCommon_1.SocketCommon_DataType.Kline:
387
+ if (pushData.klineData)
388
+ cb.onKline?.(pushData.klineData);
266
389
  break;
267
- case push_message_1.MessageType.QuoteBBO:
268
- cb.onQuoteBBO?.(msg.data);
390
+ default:
391
+ // FullTick and QuoteBBO use TradeTick/Quote dataType
392
+ // TickData (fullTick) via tickData field
393
+ if (pushData.tickData)
394
+ cb.onFullTick?.(pushData.tickData);
269
395
  break;
270
396
  }
271
397
  }
272
- /** 内部订阅方法 */
398
+ /** Internal subscribe method */
273
399
  doSubscribe(subject, symbols, account, market) {
274
- const req = { subject, symbols, account, market };
275
- const msg = (0, push_message_1.createPushMessage)(push_message_1.MessageType.Subscribe, subject, req);
276
- this.sendMessage(msg);
400
+ const dataType = (0, proto_message_1.subjectToDataType)(subject);
401
+ const symbolsStr = symbols ? symbols.join(',') : undefined;
402
+ const req = (0, proto_message_1.buildSubscribeMessage)(dataType, symbolsStr, account, market);
403
+ this.sendMessage(req);
277
404
  }
278
- /** 内部退订方法 */
405
+ /** Internal unsubscribe method */
279
406
  doUnsubscribe(subject, symbols) {
280
- const req = { subject, symbols };
281
- const msg = (0, push_message_1.createPushMessage)(push_message_1.MessageType.Unsubscribe, subject, req);
282
- this.sendMessage(msg);
407
+ const dataType = (0, proto_message_1.subjectToDataType)(subject);
408
+ const symbolsStr = symbols ? symbols.join(',') : undefined;
409
+ const req = (0, proto_message_1.buildUnSubscribeMessage)(dataType, symbolsStr);
410
+ this.sendMessage(req);
283
411
  }
284
- /** 添加订阅记录 */
412
+ /** Add subscription record */
285
413
  addSubscription(subject, symbols) {
286
414
  if (!this.subscriptions.has(subject)) {
287
415
  this.subscriptions.set(subject, new Set());
@@ -290,7 +418,7 @@ class PushClient {
290
418
  for (const s of symbols)
291
419
  set.add(s);
292
420
  }
293
- /** 移除订阅记录 */
421
+ /** Remove subscription record */
294
422
  removeSubscription(subject, symbols) {
295
423
  if (!symbols) {
296
424
  this.subscriptions.delete(subject);
@@ -304,110 +432,110 @@ class PushClient {
304
432
  this.subscriptions.delete(subject);
305
433
  }
306
434
  }
307
- // ===== 行情订阅/退订 =====
308
- /** 订阅行情 */
435
+ // ===== Market data subscribe/unsubscribe =====
436
+ /** Subscribe to quotes */
309
437
  subscribeQuote(symbols) {
310
438
  this.doSubscribe(push_message_1.SubjectType.Quote, symbols);
311
439
  this.addSubscription(push_message_1.SubjectType.Quote, symbols);
312
440
  }
313
- /** 退订行情 */
441
+ /** Unsubscribe from quotes */
314
442
  unsubscribeQuote(symbols) {
315
443
  this.doUnsubscribe(push_message_1.SubjectType.Quote, symbols);
316
444
  this.removeSubscription(push_message_1.SubjectType.Quote, symbols);
317
445
  }
318
- /** 订阅逐笔成交 */
446
+ /** Subscribe to trade ticks */
319
447
  subscribeTick(symbols) {
320
448
  this.doSubscribe(push_message_1.SubjectType.Tick, symbols);
321
449
  this.addSubscription(push_message_1.SubjectType.Tick, symbols);
322
450
  }
323
- /** 退订逐笔成交 */
451
+ /** Unsubscribe from trade ticks */
324
452
  unsubscribeTick(symbols) {
325
453
  this.doUnsubscribe(push_message_1.SubjectType.Tick, symbols);
326
454
  this.removeSubscription(push_message_1.SubjectType.Tick, symbols);
327
455
  }
328
- /** 订阅深度行情 */
456
+ /** Subscribe to depth data */
329
457
  subscribeDepth(symbols) {
330
458
  this.doSubscribe(push_message_1.SubjectType.Depth, symbols);
331
459
  this.addSubscription(push_message_1.SubjectType.Depth, symbols);
332
460
  }
333
- /** 退订深度行情 */
461
+ /** Unsubscribe from depth data */
334
462
  unsubscribeDepth(symbols) {
335
463
  this.doUnsubscribe(push_message_1.SubjectType.Depth, symbols);
336
464
  this.removeSubscription(push_message_1.SubjectType.Depth, symbols);
337
465
  }
338
- /** 订阅期权行情 */
466
+ /** Subscribe to option quotes */
339
467
  subscribeOption(symbols) {
340
468
  this.doSubscribe(push_message_1.SubjectType.Option, symbols);
341
469
  this.addSubscription(push_message_1.SubjectType.Option, symbols);
342
470
  }
343
- /** 退订期权行情 */
471
+ /** Unsubscribe from option quotes */
344
472
  unsubscribeOption(symbols) {
345
473
  this.doUnsubscribe(push_message_1.SubjectType.Option, symbols);
346
474
  this.removeSubscription(push_message_1.SubjectType.Option, symbols);
347
475
  }
348
- /** 订阅期货行情 */
476
+ /** Subscribe to futures quotes */
349
477
  subscribeFuture(symbols) {
350
478
  this.doSubscribe(push_message_1.SubjectType.Future, symbols);
351
479
  this.addSubscription(push_message_1.SubjectType.Future, symbols);
352
480
  }
353
- /** 退订期货行情 */
481
+ /** Unsubscribe from futures quotes */
354
482
  unsubscribeFuture(symbols) {
355
483
  this.doUnsubscribe(push_message_1.SubjectType.Future, symbols);
356
484
  this.removeSubscription(push_message_1.SubjectType.Future, symbols);
357
485
  }
358
- /** 订阅 K 线 */
486
+ /** Subscribe to kline data */
359
487
  subscribeKline(symbols) {
360
488
  this.doSubscribe(push_message_1.SubjectType.Kline, symbols);
361
489
  this.addSubscription(push_message_1.SubjectType.Kline, symbols);
362
490
  }
363
- /** 退订 K 线 */
491
+ /** Unsubscribe from kline data */
364
492
  unsubscribeKline(symbols) {
365
493
  this.doUnsubscribe(push_message_1.SubjectType.Kline, symbols);
366
494
  this.removeSubscription(push_message_1.SubjectType.Kline, symbols);
367
495
  }
368
- // ===== 账户推送订阅/退订 =====
369
- /** 订阅资产变动 */
496
+ // ===== Account push subscribe/unsubscribe =====
497
+ /** Subscribe to asset changes */
370
498
  subscribeAsset(account) {
371
499
  this.doSubscribe(push_message_1.SubjectType.Asset, undefined, account || this.config.account);
372
500
  this.accountSubs.add(push_message_1.SubjectType.Asset);
373
501
  }
374
- /** 退订资产变动 */
502
+ /** Unsubscribe from asset changes */
375
503
  unsubscribeAsset() {
376
504
  this.doUnsubscribe(push_message_1.SubjectType.Asset);
377
505
  this.accountSubs.delete(push_message_1.SubjectType.Asset);
378
506
  }
379
- /** 订阅持仓变动 */
507
+ /** Subscribe to position changes */
380
508
  subscribePosition(account) {
381
509
  this.doSubscribe(push_message_1.SubjectType.Position, undefined, account || this.config.account);
382
510
  this.accountSubs.add(push_message_1.SubjectType.Position);
383
511
  }
384
- /** 退订持仓变动 */
512
+ /** Unsubscribe from position changes */
385
513
  unsubscribePosition() {
386
514
  this.doUnsubscribe(push_message_1.SubjectType.Position);
387
515
  this.accountSubs.delete(push_message_1.SubjectType.Position);
388
516
  }
389
- /** 订阅订单状态 */
517
+ /** Subscribe to order status */
390
518
  subscribeOrder(account) {
391
519
  this.doSubscribe(push_message_1.SubjectType.Order, undefined, account || this.config.account);
392
520
  this.accountSubs.add(push_message_1.SubjectType.Order);
393
521
  }
394
- /** 退订订单状态 */
522
+ /** Unsubscribe from order status */
395
523
  unsubscribeOrder() {
396
524
  this.doUnsubscribe(push_message_1.SubjectType.Order);
397
525
  this.accountSubs.delete(push_message_1.SubjectType.Order);
398
526
  }
399
- /** 订阅成交明细 */
527
+ /** Subscribe to transaction details */
400
528
  subscribeTransaction(account) {
401
529
  this.doSubscribe(push_message_1.SubjectType.Transaction, undefined, account || this.config.account);
402
530
  this.accountSubs.add(push_message_1.SubjectType.Transaction);
403
531
  }
404
- /** 退订成交明细 */
532
+ /** Unsubscribe from transaction details */
405
533
  unsubscribeTransaction() {
406
534
  this.doUnsubscribe(push_message_1.SubjectType.Transaction);
407
535
  this.accountSubs.delete(push_message_1.SubjectType.Transaction);
408
536
  }
409
- // ===== 查询订阅状态 =====
410
- /** 获取当前行情订阅状态 */
537
+ // ===== Query subscription state =====
538
+ /** Get current market data subscriptions */
411
539
  getSubscriptions() {
412
540
  const result = new Map();
413
541
  for (const [subject, symbols] of this.subscriptions) {
@@ -415,7 +543,7 @@ class PushClient {
415
543
  }
416
544
  return result;
417
545
  }
418
- /** 获取账户级别订阅状态 */
546
+ /** Get account-level subscriptions */
419
547
  getAccountSubscriptions() {
420
548
  return Array.from(this.accountSubs);
421
549
  }