@tigeropenapi/tigeropen 0.4.0 → 0.4.5

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 (46) hide show
  1. package/dist/cjs/client/case-convert.js +4 -3
  2. package/dist/cjs/client/http-client.js +122 -5
  3. package/dist/cjs/config/client-config.js +56 -12
  4. package/dist/cjs/config/index.js +3 -1
  5. package/dist/cjs/config/token-manager.js +54 -4
  6. package/dist/cjs/index.js +51 -2
  7. package/dist/cjs/push/push-client.js +40 -15
  8. package/dist/cjs/quote/quote-client.js +14 -2
  9. package/dist/cjs/trade/trade-client.js +40 -2
  10. package/dist/esm/client/api-request.js +1 -1
  11. package/dist/esm/client/api-response.js +1 -1
  12. package/dist/esm/client/case-convert.js +4 -3
  13. package/dist/esm/client/http-client.js +127 -10
  14. package/dist/esm/client/index.js +6 -6
  15. package/dist/esm/config/client-config.js +59 -15
  16. package/dist/esm/config/index.js +4 -3
  17. package/dist/esm/config/token-manager.js +55 -5
  18. package/dist/esm/index.js +15 -1
  19. package/dist/esm/logger/index.js +1 -1
  20. package/dist/esm/model/contract-helpers.js +1 -1
  21. package/dist/esm/model/order-helpers.js +1 -1
  22. package/dist/esm/model/order-status.js +1 -1
  23. package/dist/esm/push/index.js +5 -5
  24. package/dist/esm/push/pb/PushData.js +11 -11
  25. package/dist/esm/push/pb/QuoteBasicData.js +1 -1
  26. package/dist/esm/push/pb/Response.js +1 -1
  27. package/dist/esm/push/pb/index.js +17 -17
  28. package/dist/esm/push/proto-message.js +3 -3
  29. package/dist/esm/push/push-client.js +47 -22
  30. package/dist/esm/quote/index.js +1 -1
  31. package/dist/esm/quote/quote-client.js +16 -4
  32. package/dist/esm/signer/index.js +2 -2
  33. package/dist/esm/trade/index.js +1 -1
  34. package/dist/esm/trade/trade-client.js +43 -5
  35. package/dist/types/client/case-convert.d.ts +3 -1
  36. package/dist/types/client/http-client.d.ts +32 -1
  37. package/dist/types/config/client-config.d.ts +16 -1
  38. package/dist/types/config/index.d.ts +2 -0
  39. package/dist/types/config/token-manager.d.ts +27 -3
  40. package/dist/types/index.d.ts +22 -1
  41. package/dist/types/model/trade-requests.d.ts +65 -0
  42. package/dist/types/model/trade.d.ts +102 -11
  43. package/dist/types/push/push-client.d.ts +5 -3
  44. package/dist/types/quote/quote-client.d.ts +3 -1
  45. package/dist/types/trade/trade-client.d.ts +15 -4
  46. package/package.json +2 -2
@@ -5,7 +5,7 @@
5
5
  // source: QuoteBasicData.proto
6
6
  /* eslint-disable */
7
7
  import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
8
- import { QuoteData_Minute } from "./QuoteData";
8
+ import { QuoteData_Minute } from "./QuoteData.js";
9
9
  export const protobufPackage = "com.tigerbrokers.stock.openapi.client.socket.data.pb";
10
10
  function createBaseQuoteBasicData() {
11
11
  return {
@@ -5,7 +5,7 @@
5
5
  // source: Response.proto
6
6
  /* eslint-disable */
7
7
  import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
8
- import { PushData } from "./PushData";
8
+ import { PushData } from "./PushData.js";
9
9
  export const protobufPackage = "com.tigerbrokers.stock.openapi.client.socket.data.pb";
10
10
  function createBaseResponse() {
11
11
  return { command: 0, id: undefined, code: undefined, msg: undefined, body: undefined };
@@ -4,22 +4,22 @@
4
4
  * 由 ts-proto 从 proto 文件生成的所有类型、枚举和编解码函数
5
5
  */
6
6
  // 基础层:命令和数据类型枚举
7
- export { SocketCommon_Command, SocketCommon_DataType, SocketCommon_QuoteType, } from './SocketCommon';
7
+ export { SocketCommon_Command, SocketCommon_DataType, SocketCommon_QuoteType, } from './SocketCommon.js';
8
8
  // 协议层:请求和响应消息
9
- export { Request, Request_Connect, Request_Subscribe } from './Request';
10
- export { Response } from './Response';
11
- export { PushData } from './PushData';
9
+ export { Request, Request_Connect, Request_Subscribe } from './Request.js';
10
+ export { Response } from './Response.js';
11
+ export { PushData } from './PushData.js';
12
12
  // 数据层:业务数据消息
13
- export { QuoteData } from './QuoteData';
14
- export { QuoteBasicData } from './QuoteBasicData';
15
- export { QuoteBBOData } from './QuoteBBOData';
16
- export { QuoteDepthData } from './QuoteDepthData';
17
- export { TradeTickData } from './TradeTickData';
18
- export { TickData } from './TickData';
19
- export { AssetData } from './AssetData';
20
- export { PositionData } from './PositionData';
21
- export { OrderStatusData } from './OrderStatusData';
22
- export { OrderTransactionData } from './OrderTransactionData';
23
- export { StockTopData } from './StockTopData';
24
- export { OptionTopData } from './OptionTopData';
25
- export { KlineData } from './KlineData';
13
+ export { QuoteData } from './QuoteData.js';
14
+ export { QuoteBasicData } from './QuoteBasicData.js';
15
+ export { QuoteBBOData } from './QuoteBBOData.js';
16
+ export { QuoteDepthData } from './QuoteDepthData.js';
17
+ export { TradeTickData } from './TradeTickData.js';
18
+ export { TickData } from './TickData.js';
19
+ export { AssetData } from './AssetData.js';
20
+ export { PositionData } from './PositionData.js';
21
+ export { OrderStatusData } from './OrderStatusData.js';
22
+ export { OrderTransactionData } from './OrderTransactionData.js';
23
+ export { StockTopData } from './StockTopData.js';
24
+ export { OptionTopData } from './OptionTopData.js';
25
+ export { KlineData } from './KlineData.js';
@@ -4,9 +4,9 @@
4
4
  * 对齐 Java SDK 的 ProtoMessageUtil,提供构建各种 Request 消息的工具函数。
5
5
  * 所有构建函数共享一个递增的 requestId 计数器。
6
6
  */
7
- import { Request, Request_Connect, Request_Subscribe, } from './pb/Request';
8
- import { SocketCommon_Command, SocketCommon_DataType, } from './pb/SocketCommon';
9
- import { SubjectType } from './push-message';
7
+ import { Request, Request_Connect, Request_Subscribe, } from './pb/Request.js';
8
+ import { SocketCommon_Command, SocketCommon_DataType, } from './pb/SocketCommon.js';
9
+ import { SubjectType } from './push-message.js';
10
10
  /** 递增请求 ID 计数器(单线程环境,简单递增变量) */
11
11
  let requestId = 0;
12
12
  /**
@@ -9,13 +9,13 @@
9
9
  * heartbeat keep-alive, and automatic reconnection.
10
10
  */
11
11
  import * as tls from 'tls';
12
- import { signWithRSA } from '../signer/signer';
13
- import { SubjectType } from './push-message';
14
- import { Request } from './pb/Request';
15
- import { Response } from './pb/Response';
16
- import { SocketCommon_Command, SocketCommon_DataType } from './pb/SocketCommon';
17
- import { encodeVarint32, decodeVarint32 } from './varint';
18
- import { buildConnectMessage, buildHeartBeatMessage, buildSubscribeMessage, buildUnSubscribeMessage, buildDisconnectMessage, subjectToDataType, } from './proto-message';
12
+ import { signWithRSA } from '../signer/signer.js';
13
+ import { SubjectType } from './push-message.js';
14
+ import { Request } from './pb/Request.js';
15
+ import { Response } from './pb/Response.js';
16
+ import { SocketCommon_Command, SocketCommon_DataType } from './pb/SocketCommon.js';
17
+ import { encodeVarint32, decodeVarint32 } from './varint.js';
18
+ import { buildConnectMessage, buildHeartBeatMessage, buildSubscribeMessage, buildUnSubscribeMessage, buildDisconnectMessage, subjectToDataType, } from './proto-message.js';
19
19
  /** Default push server host */
20
20
  const DEFAULT_PUSH_HOST = 'openapi.tigerfintech.com';
21
21
  /** Default push server port */
@@ -50,11 +50,13 @@ export class PushClient {
50
50
  constructor(config, options) {
51
51
  this.socket = null;
52
52
  this._state = ConnectionState.Disconnected;
53
+ /** Whether this connect attempt already fell back to unverified TLS */
54
+ this.tlsFallback = false;
53
55
  this.callbacks = {};
54
56
  /** Subscription state: subject -> Set<symbol> */
55
57
  this.subscriptions = new Map();
56
- /** Account-level subscriptions */
57
- this.accountSubs = new Set();
58
+ /** Account-level subscriptions: subject -> account string used at subscribe time */
59
+ this.accountSubs = new Map();
58
60
  this.heartbeatTimer = null;
59
61
  this.reconnectTimer = null;
60
62
  this.stopped = false;
@@ -88,6 +90,7 @@ export class PushClient {
88
90
  }
89
91
  this._state = ConnectionState.Connecting;
90
92
  this.stopped = false;
93
+ this.tlsFallback = false;
91
94
  this.recvBuffer = Buffer.alloc(0);
92
95
  const socket = this.createSocket(this.pushHost, this.pushPort);
93
96
  this.socket = socket;
@@ -144,6 +147,24 @@ export class PushClient {
144
147
  });
145
148
  socket.on('error', (err) => {
146
149
  if (!settled) {
150
+ // If this is a TLS certificate error, warn and retry without verification.
151
+ const isTlsCertError = err.message.includes('certificate') ||
152
+ err.message.includes('CERT') ||
153
+ err.code === 'DEPTH_ZERO_SELF_SIGNED_CERT' ||
154
+ err.code === 'UNABLE_TO_VERIFY_LEAF_SIGNATURE' ||
155
+ err.code === 'CERT_HAS_EXPIRED';
156
+ if (isTlsCertError && !this.tlsFallback) {
157
+ this.tlsFallback = true;
158
+ settled = true;
159
+ clearTimeout(timeout);
160
+ socket.destroy();
161
+ this.socket = null;
162
+ this._state = ConnectionState.Disconnected;
163
+ console.warn(`[TigerOpen] TLS certificate verification failed: ${err.message}. Retrying without verification.`);
164
+ // Retry immediately using unverified TLS
165
+ this.connect().then(resolve).catch(reject);
166
+ return;
167
+ }
147
168
  settled = true;
148
169
  clearTimeout(timeout);
149
170
  this._state = ConnectionState.Disconnected;
@@ -196,7 +217,7 @@ export class PushClient {
196
217
  createSocket(host, port) {
197
218
  if (this.socketFactory)
198
219
  return this.socketFactory(host, port);
199
- return tls.connect({ host, port, rejectUnauthorized: false });
220
+ return tls.connect({ host, port, rejectUnauthorized: !this.tlsFallback });
200
221
  }
201
222
  /** Handle incoming TCP data: buffer + decode varint32 frames */
202
223
  handleData(chunk, onConnected) {
@@ -295,8 +316,8 @@ export class PushClient {
295
316
  for (const [subject, symbols] of this.subscriptions) {
296
317
  this.doSubscribe(subject, Array.from(symbols));
297
318
  }
298
- for (const subject of this.accountSubs) {
299
- this.doSubscribe(subject, undefined, this.config.account);
319
+ for (const [subject, account] of this.accountSubs) {
320
+ this.doSubscribe(subject, undefined, account);
300
321
  }
301
322
  }
302
323
  /** Dispatch push data to the appropriate callback based on dataType */
@@ -530,8 +551,9 @@ export class PushClient {
530
551
  // ===== Account push subscribe/unsubscribe =====
531
552
  /** Subscribe to asset changes */
532
553
  subscribeAsset(account) {
533
- this.doSubscribe(SubjectType.Asset, undefined, account || this.config.account);
534
- this.accountSubs.add(SubjectType.Asset);
554
+ const acct = account || this.config.account;
555
+ this.doSubscribe(SubjectType.Asset, undefined, acct);
556
+ this.accountSubs.set(SubjectType.Asset, acct);
535
557
  }
536
558
  /** Unsubscribe from asset changes */
537
559
  unsubscribeAsset() {
@@ -540,8 +562,9 @@ export class PushClient {
540
562
  }
541
563
  /** Subscribe to position changes */
542
564
  subscribePosition(account) {
543
- this.doSubscribe(SubjectType.Position, undefined, account || this.config.account);
544
- this.accountSubs.add(SubjectType.Position);
565
+ const acct = account || this.config.account;
566
+ this.doSubscribe(SubjectType.Position, undefined, acct);
567
+ this.accountSubs.set(SubjectType.Position, acct);
545
568
  }
546
569
  /** Unsubscribe from position changes */
547
570
  unsubscribePosition() {
@@ -550,8 +573,9 @@ export class PushClient {
550
573
  }
551
574
  /** Subscribe to order status */
552
575
  subscribeOrder(account) {
553
- this.doSubscribe(SubjectType.Order, undefined, account || this.config.account);
554
- this.accountSubs.add(SubjectType.Order);
576
+ const acct = account || this.config.account;
577
+ this.doSubscribe(SubjectType.Order, undefined, acct);
578
+ this.accountSubs.set(SubjectType.Order, acct);
555
579
  }
556
580
  /** Unsubscribe from order status */
557
581
  unsubscribeOrder() {
@@ -560,8 +584,9 @@ export class PushClient {
560
584
  }
561
585
  /** Subscribe to transaction details */
562
586
  subscribeTransaction(account) {
563
- this.doSubscribe(SubjectType.Transaction, undefined, account || this.config.account);
564
- this.accountSubs.add(SubjectType.Transaction);
587
+ const acct = account || this.config.account;
588
+ this.doSubscribe(SubjectType.Transaction, undefined, acct);
589
+ this.accountSubs.set(SubjectType.Transaction, acct);
565
590
  }
566
591
  /** Unsubscribe from transaction details */
567
592
  unsubscribeTransaction() {
@@ -577,8 +602,8 @@ export class PushClient {
577
602
  }
578
603
  return result;
579
604
  }
580
- /** Get account-level subscriptions */
605
+ /** Get account-level subscriptions: subject -> account */
581
606
  getAccountSubscriptions() {
582
- return Array.from(this.accountSubs);
607
+ return new Map(this.accountSubs);
583
608
  }
584
609
  }
@@ -1,4 +1,4 @@
1
1
  /**
2
2
  * Quote module exports
3
3
  */
4
- export { QuoteClient, parseOptionIdentifier } from './quote-client';
4
+ export { QuoteClient, parseOptionIdentifier } from './quote-client.js';
@@ -1,5 +1,5 @@
1
- import { createApiRequest } from '../client/api-request';
2
- import { unmarshalData } from '../client/api-response';
1
+ import { createApiRequest } from '../client/api-request.js';
2
+ import { unmarshalData } from '../client/api-response.js';
3
3
  /**
4
4
  * Parse an OCC-style option identifier like "AAPL 260619C00150000"
5
5
  * into its component parts.
@@ -357,9 +357,21 @@ export class QuoteClient {
357
357
  }
358
358
  return acc;
359
359
  }
360
- /** Futures tick trades. wire: future_tick (API v3.0) */
360
+ /** Futures tick trades. wire: future_tick (API v3.0)
361
+ * Server returns {contractCode, items:[...]}; unwrap items and backfill contractCode.
362
+ * endIndex defaults to 30 when not set (consistent with Python/Go SDK). */
361
363
  async getFutureTradeTicks(req) {
362
- return this.callInto('future_tick', req, '3.0');
364
+ if (!req.endIndex)
365
+ req.endIndex = 30;
366
+ const wrap = await this.callInto('future_tick', req, '3.0');
367
+ const items = wrap?.items ?? [];
368
+ if (wrap?.contractCode) {
369
+ for (const item of items) {
370
+ if (!item.contractCode)
371
+ item.contractCode = wrap.contractCode;
372
+ }
373
+ }
374
+ return items;
363
375
  }
364
376
  /** Futures depth. wire: future_depth */
365
377
  async getFutureDepth(req) {
@@ -1,5 +1,5 @@
1
1
  /**
2
2
  * 认证层(RSA Signer)统一导出
3
3
  */
4
- export { loadPrivateKey, signWithRSA, verifyWithRSA } from './signer';
5
- export { getSignContent } from './sign-content';
4
+ export { loadPrivateKey, signWithRSA, verifyWithRSA } from './signer.js';
5
+ export { getSignContent } from './sign-content.js';
@@ -1,4 +1,4 @@
1
1
  /**
2
2
  * 交易模块导出
3
3
  */
4
- export { TradeClient } from './trade-client';
4
+ export { TradeClient } from './trade-client.js';
@@ -1,6 +1,6 @@
1
- import { createApiRequest } from '../client/api-request';
2
- import { unmarshalData } from '../client/api-response';
3
- import { normalizeOrderStatus } from '../model/order-status';
1
+ import { createApiRequest } from '../client/api-request.js';
2
+ import { unmarshalData } from '../client/api-response.js';
3
+ import { normalizeOrderStatus } from '../model/order-status.js';
4
4
  /** Normalize `Order.status` field in-place (handles int → string). */
5
5
  function normalizeOrderInPlace(o) {
6
6
  if (o && o.status !== undefined && o.status !== null) {
@@ -191,9 +191,10 @@ export class TradeClient {
191
191
  async getFundDetails(req) {
192
192
  return this.callIntoItems('fund_details', withAccount(req, this.account));
193
193
  }
194
- /** Funding history (wire method: `transfer_fund`). */
194
+ /** Funding history (wire method: `transfer_fund`).
195
+ * Server returns bare list (no items wrapper). */
195
196
  async getFundingHistory(req) {
196
- return this.callIntoItems('transfer_fund', withAccount(req, this.account));
197
+ return this.callInto('transfer_fund', withAccount(req, this.account));
197
198
  }
198
199
  // ===== v0.4.0 NEW: Internal / external position transfer =====
199
200
  /**
@@ -227,4 +228,41 @@ export class TradeClient {
227
228
  merged.accountId = this.account;
228
229
  return this.callIntoItems('position_transfer_external_records', merged);
229
230
  }
231
+ /** 行权检验:预估行权/作废后正股持仓变化 (wire: option_exercise_check) */
232
+ async checkOptionExercise(req) {
233
+ const merged = { ...req };
234
+ if (!merged.account)
235
+ merged.account = this.account;
236
+ return this.callInto('option_exercise_check', merged);
237
+ }
238
+ /** 查询可行权持仓列表 (wire: option_exercise_position) */
239
+ async getOptionExercisePositions(req) {
240
+ const merged = { ...req };
241
+ if (!merged.account)
242
+ merged.account = this.account;
243
+ return this.callInto('option_exercise_position', merged);
244
+ }
245
+ /** 提交行权/作废申请 (wire: option_exercise_submit) */
246
+ async submitOptionExercise(req) {
247
+ const merged = { ...req };
248
+ if (!merged.account)
249
+ merged.account = this.account;
250
+ const result = await this.callInto('option_exercise_submit', merged);
251
+ return result ?? false;
252
+ }
253
+ /** 分页查询行权记录 (wire: option_exercise_record) */
254
+ async getOptionExerciseRecords(req) {
255
+ const merged = { ...req };
256
+ if (!merged.account)
257
+ merged.account = this.account;
258
+ return this.callInto('option_exercise_record', merged);
259
+ }
260
+ /** 撤销行权申请 (wire: option_exercise_cancel) */
261
+ async cancelOptionExercise(req) {
262
+ const merged = { ...req };
263
+ if (!merged.account)
264
+ merged.account = this.account;
265
+ const result = await this.callInto('option_exercise_cancel', merged);
266
+ return result ?? false;
267
+ }
230
268
  }
@@ -11,6 +11,8 @@ export declare function camelToSnake(key: string): string;
11
11
  /**
12
12
  * Recursively convert all object keys from camelCase to snake_case.
13
13
  * Preserves arrays, primitives, and Date/null/undefined.
14
- * Keys already containing an underscore are kept as-is (already snake_case).
14
+ *
15
+ * Note: camelToSnake is idempotent for pure snake_case keys (no uppercase
16
+ * letters → no replacements), so no pre-check is needed.
15
17
  */
16
18
  export declare function keysToSnakeCase(value: unknown): unknown;
@@ -5,6 +5,7 @@
5
5
  * Uses Node.js built-in fetch (Node 18+).
6
6
  */
7
7
  import type { ClientConfig } from '../config/client-config';
8
+ import { TokenManager, type TokenManagerOptions } from '../config/token-manager';
8
9
  import { RetryPolicy } from './retry';
9
10
  import { type ApiResponse } from './api-response';
10
11
  import type { ApiRequest } from './api-request';
@@ -16,9 +17,16 @@ export declare class HttpClient {
16
17
  private retryPolicy;
17
18
  /** Override the target URL (used by quote client to hit quote server) */
18
19
  private targetUrl;
20
+ /** non-null when auto-refresh is active */
21
+ private tokenManager;
19
22
  constructor(config: ClientConfig, retryPolicy?: RetryPolicy, options?: {
20
23
  useQuoteServerUrl?: boolean;
21
24
  });
25
+ /**
26
+ * Stop the background token auto-refresh timer.
27
+ * Call this when the HttpClient is no longer needed to avoid timer leaks.
28
+ */
29
+ close(): void;
22
30
  /**
23
31
  * Build common request parameters
24
32
  */
@@ -41,9 +49,32 @@ export declare class HttpClient {
41
49
  *
42
50
  * @param apiMethod - API method name (e.g. "market_state", "place_order")
43
51
  * @param requestJson - Raw biz_content JSON string
52
+ * @param version - Optional API version override (default: "2.0")
44
53
  * @returns Raw response JSON string, unparsed
45
54
  */
46
- execute(apiMethod: string, requestJson: string): Promise<string>;
55
+ execute(apiMethod: string, requestJson: string, version?: string): Promise<string>;
56
+ /**
57
+ * 调用 user_token_refresh 接口获取新 token,返回新 token 字符串。
58
+ * 此方法仅查询,不修改 config 中的 token。
59
+ */
60
+ queryToken(): Promise<string>;
61
+ /**
62
+ * 刷新 token:调用接口获取新 token 后更新 config.token。
63
+ *
64
+ * @param tokenManager - 可选外部 TokenManager;若提供则调用 setToken() 写文件并触发回调。
65
+ * 若 NewHttpClient 已自动启动内部 TokenManager,其内存 token 也会同步更新。
66
+ */
67
+ refreshToken(tokenManager?: TokenManager | null): Promise<void>;
68
+ /**
69
+ * 启动后台 token 自动刷新。
70
+ *
71
+ * @param tokenManager - 可为 null:SDK 内部自动创建一个仅内存的 TokenManager,
72
+ * 适合直接通过 token 在代码里设置、不使用文件的场景。
73
+ * @param options - 仅在 tokenManager 为 null 时生效,用于配置内部 TokenManager
74
+ * (refreshDuration / refreshInterval / tokenWriter / tokenLoader)。
75
+ * @returns 使用或创建的 TokenManager 实例
76
+ */
77
+ startTokenAutoRefresh(tokenManager: TokenManager | null, options?: TokenManagerOptions): TokenManager;
47
78
  /** Delay for the specified milliseconds */
48
79
  private sleep;
49
80
  /**
@@ -9,6 +9,12 @@ export interface ClientConfig {
9
9
  timeout: number;
10
10
  token?: string;
11
11
  tokenRefreshDuration?: number;
12
+ /** 后台 token 检查间隔(毫秒),仅 tokenRefreshDuration > 0 时生效,默认 5 分钟 */
13
+ tokenCheckInterval?: number;
14
+ /** 自定义 token 加载函数,替代默认的文件加载 */
15
+ tokenLoader?: () => Promise<string> | string;
16
+ /** token 刷新写入后的可选回调 */
17
+ tokenWriter?: (token: string) => void;
12
18
  serverUrl: string;
13
19
  /** Quote server URL for quote-specific requests; falls back to serverUrl */
14
20
  quoteServerUrl: string;
@@ -27,13 +33,22 @@ export interface ClientConfigOptions {
27
33
  timeout?: number;
28
34
  token?: string;
29
35
  tokenRefreshDuration?: number;
36
+ /** 后台 token 检查间隔(毫秒),仅 tokenRefreshDuration > 0 时生效,默认 5 分钟 */
37
+ tokenCheckInterval?: number;
38
+ /** 自定义 token 加载函数,替代默认的文件加载 */
39
+ tokenLoader?: () => Promise<string> | string;
40
+ /** token 刷新写入后的可选回调 */
41
+ tokenWriter?: (token: string) => void;
30
42
  serverUrl?: string;
31
43
  /** Explicit quote server URL; resolved dynamically if not set */
32
44
  quoteServerUrl?: string;
33
45
  /** Enable dynamic domain resolution (default: true) */
34
46
  enableDynamicDomain?: boolean;
35
- /** Explicit properties file path (synchronous read) */
47
+ /** Explicit properties file path or directory (synchronous read).
48
+ * If a directory is given, appends 'tiger_openapi_config.properties' automatically. */
36
49
  propertiesFilePath?: string;
50
+ /** Override Tiger public key (e.g. for sandbox/QA environments) */
51
+ tigerPublicKey?: string;
37
52
  }
38
53
  /**
39
54
  * Load and parse a Java-style properties file.
@@ -4,4 +4,6 @@
4
4
  export { parsePropertiesFile, parsePropertiesString } from './config-parser';
5
5
  export { createClientConfig, loadPropertiesFile } from './client-config';
6
6
  export type { ClientConfig, ClientConfigOptions } from './client-config';
7
+ export { TokenManager } from './token-manager';
8
+ export type { TokenManagerOptions, RefreshFn } from './token-manager';
7
9
  export { queryDomains, resolveDynamicServerUrl, resolveDynamicQuoteServerUrl } from './domain';
@@ -4,6 +4,10 @@ export interface TokenManagerOptions {
4
4
  refreshInterval?: number;
5
5
  /** Token 刷新阈值(秒),0 表示不刷新,最小 30 秒 */
6
6
  refreshDuration?: number;
7
+ /** 自定义 token 加载函数,优先于文件加载 */
8
+ tokenLoader?: () => Promise<string> | string;
9
+ /** token 写入后的回调(SetToken 成功后触发,SyncToken 不触发) */
10
+ tokenWriter?: (token: string) => void;
7
11
  }
8
12
  /** Token 刷新函数类型 */
9
13
  export type RefreshFn = () => Promise<string>;
@@ -13,16 +17,36 @@ export type RefreshFn = () => Promise<string>;
13
17
  export declare class TokenManager {
14
18
  private token;
15
19
  private filePath;
20
+ /** 仅当显式传入 filePath 时才写文件(fileEnabled = true) */
21
+ private fileEnabled;
16
22
  private refreshInterval;
17
23
  private refreshDuration;
18
24
  private timer;
25
+ private tokenLoader;
26
+ private tokenWriter;
19
27
  constructor(options?: TokenManagerOptions);
20
- /** 从 properties 文件加载 Token */
21
- loadToken(): string;
28
+ /**
29
+ * 从 properties 文件(或自定义 tokenLoader)加载 Token。
30
+ * 若设置了 tokenLoader,优先调用;否则从 properties 文件读取。
31
+ */
32
+ loadToken(): Promise<string>;
33
+ /**
34
+ * 同步版文件加载(仅用于无 tokenLoader 时的兼容入口)。
35
+ * 建议优先使用 loadToken()(异步)。
36
+ */
37
+ loadTokenSync(): string;
22
38
  /** 获取当前 Token */
23
39
  getToken(): string;
24
- /** 设置 Token 并更新文件 */
40
+ /**
41
+ * 设置 Token;若启用了文件持久化(显式传入 filePath),则同步写文件。
42
+ * 成功后触发 tokenWriter 回调(如有)。
43
+ */
25
44
  setToken(token: string): void;
45
+ /**
46
+ * 仅更新内存中的 token,不写文件,不触发 tokenWriter 回调。
47
+ * 用于多个组件共享 token 时的内部同步。
48
+ */
49
+ syncToken(token: string): void;
26
50
  /** 将 Token 保存到 properties 文件 */
27
51
  private saveTokenToFile;
28
52
  /**
@@ -15,4 +15,25 @@
15
15
  * @packageDocumentation
16
16
  */
17
17
  /** SDK 版本号 */
18
- export declare const VERSION = "0.4.0";
18
+ export declare const VERSION = "0.4.4";
19
+ export { createClientConfig, loadPropertiesFile } from './config';
20
+ export type { ClientConfig, ClientConfigOptions } from './config';
21
+ export { TokenManager } from './config';
22
+ export type { TokenManagerOptions, RefreshFn } from './config';
23
+ export { HttpClient } from './client';
24
+ export { TigerError, classifyErrorCode } from './client';
25
+ export type { ErrorCategory } from './client';
26
+ export { QuoteClient, parseOptionIdentifier } from './quote';
27
+ export { TradeClient } from './trade';
28
+ export { PushClient, ConnectionState, SubjectType } from './push';
29
+ export type { PushClientOptions } from './push';
30
+ export type { Order, OrderRequest } from './model/order';
31
+ export { marketOrder, limitOrder, stopOrder, stopLimitOrder } from './model/order-helpers';
32
+ export { normalizeOrderStatus } from './model/order-status';
33
+ export type { Contract } from './model/contract';
34
+ export type { Position } from './model/position';
35
+ export type { Asset, AssetSegment, PrimeAsset, PreviewResult, PlaceOrderResult, OrderIdResult, Transaction, ManagedAccount, AnalyticsAsset, AggregateAssets, EstimateTradableQuantity, ForexOrderResult, SegmentFund, SegmentFundAvailableItem, SegmentFundHistoryItem, FundDetails, FundingHistoryItem, PositionTransferRecord, PositionTransferDetail, PositionTransferExternalRecord, OptionExerciseCheckResult, OptionExercisePositionPageResult, OptionExerciseRecordPageResult, } from './model/trade';
36
+ export type { OrdersRequest, GetOrderRequest, OrderTransactionsRequest, PositionsRequest, AssetsRequest, ManagedAccountsRequest, DerivativeContractsRequest, AnalyticsAssetRequest, AggregateAssetsRequest, EstimateTradableQuantityRequest, ForexOrderRequest, SegmentFundRequest, FundDetailsRequest, FundingHistoryRequest, PositionTransferRequest, PositionTransferRecordsRequest, PositionTransferDetailRequest, PositionTransferExternalRecordsRequest, OptionExerciseCheckRequest, OptionExercisePositionRequest, OptionExerciseSubmitRequest, OptionExerciseRecordsRequest, OptionExerciseCancelRequest, } from './model/trade-requests';
37
+ export type { MarketState, Brief, Kline, KlineItem, Timeline, TimelineItem, TradeTick, TradeTickItem, Depth, DepthLevel, OptionExpiration, OptionChain, OptionChainRow, OptionSymbol, FutureExchange, FutureContractInfo, FutureQuote, FutureKline, FutureKlineItem, FutureDepth, FutureTradeTickItem, FutureTradingTime, FinancialDailyItem, FinancialReportItem, CorporateAction, CapitalFlow, CapitalFlowItem, CapitalDistribution, ScannerResult, ScannerResultItem, QuotePermission, SymbolName, TradeMeta, StockDetail, StockBroker, StockBrokerItem, ShortInterest, StockIndustry, IndustryItem, IndustryStock, WarrantBrief, WarrantFilterResult, FundContractInfo, FundQuote, FundHistoryQuote, QuoteOvernight, KlineQuota, MarketScannerTag, MarketScannerTags, OptionAnalysis, OptionLeg, OptionVolatilityPoint, ExchangeRate, FinancialCurrency, BrokerDetail, TradingCalendarItem, FutureMainContractHistory, } from './model/quote';
38
+ export type { BriefRequest, DepthQuoteRequest, TradeTickRequest, BarsRequest, BarsByPageRequest, FutureBriefRequest, FutureBarsRequest, FutureBarsByPageRequest, FutureTradeTicksRequest, FutureDepthRequest, FutureContractSingleRequest, FutureContinuousContractsRequest, FutureHistoryMainContractRequest, FutureTradingTimesRequest, AllFutureContractsRequest, OptionBarsRequest, OptionTradeTicksRequest, OptionTimelineRequest, OptionDepthRequest, OptionSymbolsRequest, OptionAnalysisRequest, OptionQueryItem, ShortInterestRequest, StockBrokerRequest, StockDetailsRequest, StockFundamentalRequest, StockIndustryRequest, StockDelayBriefsRequest, SymbolsRequest, TradeMetasRequest, TradeRankRequest, TimelineHistoryRequest, TradingCalendarRequest, KlineQuotaRequest, QuotePermissionRequest, QuoteOvernightRequest, IndustryListRequest, IndustryStocksRequest, FundSymbolsRequest, FundContractsRequest, FundQuoteRequest, FundHistoryQuoteRequest, WarrantBriefsRequest, WarrantFilterRequest, MarketScannerTagsRequest, FinancialCurrencyRequest, FinancialExchangeRateRequest, } from './model/quote-requests';
39
+ export { OrderStatus, SecurityType, OrderType, TimeInForce, Market, Currency, QuoteRight, SegmentType, OrderSortBy, CorporateActionType, IndustryLevel, SortDirection, OptionAnalysisPeriod, FinancialReportPeriod, Language, License, BarPeriod, orderStatusCode, } from './model/enums';
@@ -193,3 +193,68 @@ export interface PositionTransferExternalRecordsRequest {
193
193
  limit?: number;
194
194
  lang?: string;
195
195
  }
196
+ /** 行权检验请求 (wire: option_exercise_check) */
197
+ export interface OptionExerciseCheckRequest {
198
+ account?: string;
199
+ secretKey?: string;
200
+ /** 期权合约 ID */
201
+ contractId: number;
202
+ /** Exercise | Expire */
203
+ type: string;
204
+ quantity?: number;
205
+ /** yyyy-MM-dd,Exercise 类型建议填 */
206
+ executingDate?: string;
207
+ /** Exercise 类型建议填 */
208
+ isForce?: boolean;
209
+ /** 0–10,Expire 类型专用 */
210
+ itmRate?: number;
211
+ lang?: string;
212
+ }
213
+ /** 查询可行权持仓请求 (wire: option_exercise_position) */
214
+ export interface OptionExercisePositionRequest {
215
+ account?: string;
216
+ secretKey?: string;
217
+ /** Exercise | Expire */
218
+ type: string;
219
+ lang?: string;
220
+ }
221
+ /** 提交行权申请请求 (wire: option_exercise_submit) */
222
+ export interface OptionExerciseSubmitRequest {
223
+ account?: string;
224
+ secretKey?: string;
225
+ contractId: number;
226
+ /** Exercise | Expire */
227
+ type: string;
228
+ quantity: number;
229
+ /** Exercise 必填,yyyy-MM-dd */
230
+ executingDate?: string;
231
+ /** Exercise 必填 */
232
+ isForce?: boolean;
233
+ /** 0–10,Expire 专用 */
234
+ itmRate?: number;
235
+ lang?: string;
236
+ }
237
+ /** 分页查询行权记录请求 (wire: option_exercise_record) */
238
+ export interface OptionExerciseRecordsRequest {
239
+ account?: string;
240
+ secretKey?: string;
241
+ /** 从 1 开始,默认 1 */
242
+ page?: number;
243
+ /** 1–100,默认 20 */
244
+ size?: number;
245
+ /** New | Cancel | Success | Fail */
246
+ status?: string;
247
+ /** Exercise | Expire */
248
+ type?: string;
249
+ symbol?: string;
250
+ /** symbol | expire_date | strike | is_call */
251
+ orderBy?: string;
252
+ lang?: string;
253
+ }
254
+ /** 撤销行权申请请求 (wire: option_exercise_cancel) */
255
+ export interface OptionExerciseCancelRequest {
256
+ account?: string;
257
+ secretKey?: string;
258
+ id: number;
259
+ lang?: string;
260
+ }