forgex-cli 1.0.58 → 1.0.61

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 (158) hide show
  1. package/README.md +375 -368
  2. package/dist/bin/forgex.d.ts +5 -5
  3. package/dist/bin/forgex.js +14 -14
  4. package/dist/bin/forgex.js.map +1 -1
  5. package/dist/src/adapters/codex-adapter.d.ts +90 -90
  6. package/dist/src/adapters/codex-adapter.d.ts.map +1 -1
  7. package/dist/src/adapters/codex-adapter.js +76 -76
  8. package/dist/src/adapters/codex-adapter.js.map +1 -1
  9. package/dist/src/adapters/connection.d.ts +6 -6
  10. package/dist/src/adapters/connection.js +8 -8
  11. package/dist/src/adapters/connection.js.map +1 -1
  12. package/dist/src/adapters/ipfs.d.ts +3 -3
  13. package/dist/src/adapters/ipfs.js +3 -3
  14. package/dist/src/adapters/jito-adapter.d.ts +85 -85
  15. package/dist/src/adapters/jito-adapter.d.ts.map +1 -1
  16. package/dist/src/adapters/jito-adapter.js +111 -111
  17. package/dist/src/adapters/jito-adapter.js.map +1 -1
  18. package/dist/src/adapters/rpc-adapter.d.ts +53 -53
  19. package/dist/src/adapters/rpc-adapter.d.ts.map +1 -1
  20. package/dist/src/adapters/rpc-adapter.js +69 -69
  21. package/dist/src/adapters/rpc-adapter.js.map +1 -1
  22. package/dist/src/adapters/sdk-adapter.d.ts +21 -21
  23. package/dist/src/adapters/sdk-adapter.d.ts.map +1 -1
  24. package/dist/src/adapters/sdk-adapter.js +79 -79
  25. package/dist/src/adapters/sdk-adapter.js.map +1 -1
  26. package/dist/src/commands/config/index.d.ts +1 -1
  27. package/dist/src/commands/config/index.js +15 -15
  28. package/dist/src/commands/config/index.js.map +1 -1
  29. package/dist/src/commands/query/index.d.ts +2 -2
  30. package/dist/src/commands/query/index.js +82 -82
  31. package/dist/src/commands/query/index.js.map +1 -1
  32. package/dist/src/commands/token/index.d.ts +8 -8
  33. package/dist/src/commands/token/index.js +73 -73
  34. package/dist/src/commands/token/index.js.map +1 -1
  35. package/dist/src/commands/tools/index.d.ts +9 -9
  36. package/dist/src/commands/tools/index.js +137 -137
  37. package/dist/src/commands/tools/index.js.map +1 -1
  38. package/dist/src/commands/trade/index.d.ts +2 -2
  39. package/dist/src/commands/trade/index.js +82 -82
  40. package/dist/src/commands/trade/index.js.map +1 -1
  41. package/dist/src/commands/transfer/index.d.ts +8 -8
  42. package/dist/src/commands/transfer/index.js +106 -106
  43. package/dist/src/commands/transfer/index.js.map +1 -1
  44. package/dist/src/commands/wallet/index.d.ts +1 -1
  45. package/dist/src/commands/wallet/index.js +175 -175
  46. package/dist/src/commands/wallet/index.js.map +1 -1
  47. package/dist/src/config.d.ts +26 -26
  48. package/dist/src/config.d.ts.map +1 -1
  49. package/dist/src/config.js +28 -28
  50. package/dist/src/config.js.map +1 -1
  51. package/dist/src/const/index.js +1 -1
  52. package/dist/src/const/index.js.map +1 -1
  53. package/dist/src/data-source.d.ts +81 -81
  54. package/dist/src/data-source.d.ts.map +1 -1
  55. package/dist/src/data-source.js +149 -149
  56. package/dist/src/data-source.js.map +1 -1
  57. package/dist/src/data-store/index.d.ts +22 -22
  58. package/dist/src/data-store/index.d.ts.map +1 -1
  59. package/dist/src/data-store/index.js +46 -46
  60. package/dist/src/data-store/index.js.map +1 -1
  61. package/dist/src/data-store/types.d.ts +3 -3
  62. package/dist/src/data-store/types.js +3 -3
  63. package/dist/src/index.d.ts +2 -2
  64. package/dist/src/index.js +10 -10
  65. package/dist/src/index.js.map +1 -1
  66. package/dist/src/output.d.ts +18 -18
  67. package/dist/src/output.d.ts.map +1 -1
  68. package/dist/src/output.js +34 -34
  69. package/dist/src/output.js.map +1 -1
  70. package/dist/src/shims/store.d.ts +3 -2
  71. package/dist/src/shims/store.d.ts.map +1 -1
  72. package/dist/src/shims/store.js +6 -5
  73. package/dist/src/shims/store.js.map +1 -1
  74. package/dist/src/sol-sdk/batch/create.d.ts +4 -1
  75. package/dist/src/sol-sdk/batch/create.d.ts.map +1 -1
  76. package/dist/src/sol-sdk/batch/create.js +44 -44
  77. package/dist/src/sol-sdk/batch/create.js.map +1 -1
  78. package/dist/src/sol-sdk/batch/index.js +135 -135
  79. package/dist/src/sol-sdk/batch/index.js.map +1 -1
  80. package/dist/src/sol-sdk/calc.d.ts +63 -63
  81. package/dist/src/sol-sdk/calc.d.ts.map +1 -1
  82. package/dist/src/sol-sdk/calc.js +120 -120
  83. package/dist/src/sol-sdk/calc.js.map +1 -1
  84. package/dist/src/sol-sdk/jito/index.js +12 -12
  85. package/dist/src/sol-sdk/jito/index.js.map +1 -1
  86. package/dist/src/sol-sdk/launchlab/instructions/create.js +10 -10
  87. package/dist/src/sol-sdk/launchlab/instructions/create.js.map +1 -1
  88. package/dist/src/sol-sdk/meteora/index.d.ts +5 -5
  89. package/dist/src/sol-sdk/meteora/index.js +11 -11
  90. package/dist/src/sol-sdk/meteora/index.js.map +1 -1
  91. package/dist/src/sol-sdk/meteora/instructions/buy.js +8 -8
  92. package/dist/src/sol-sdk/meteora/instructions/buy.js.map +1 -1
  93. package/dist/src/sol-sdk/meteora/instructions/sell.js +6 -6
  94. package/dist/src/sol-sdk/meteora/instructions/sell.js.map +1 -1
  95. package/dist/src/sol-sdk/pump/index.js +3 -3
  96. package/dist/src/sol-sdk/pump/index.js.map +1 -1
  97. package/dist/src/sol-sdk/pump/instructions/buy.d.ts +12 -12
  98. package/dist/src/sol-sdk/pump/instructions/buy.d.ts.map +1 -1
  99. package/dist/src/sol-sdk/pump/instructions/buy.js +26 -26
  100. package/dist/src/sol-sdk/pump/instructions/buy.js.map +1 -1
  101. package/dist/src/sol-sdk/pump/instructions/createAndBuy.d.ts +13 -13
  102. package/dist/src/sol-sdk/pump/instructions/createAndBuy.js +17 -17
  103. package/dist/src/sol-sdk/pump/instructions/createAndBuy.js.map +1 -1
  104. package/dist/src/sol-sdk/pump/instructions/sell.d.ts +2 -2
  105. package/dist/src/sol-sdk/pump/instructions/sell.d.ts.map +1 -1
  106. package/dist/src/sol-sdk/pump/instructions/sell.js +7 -7
  107. package/dist/src/sol-sdk/pump/instructions/sell.js.map +1 -1
  108. package/dist/src/sol-sdk/pumpswap/index.d.ts +4 -4
  109. package/dist/src/sol-sdk/pumpswap/index.js +5 -5
  110. package/dist/src/sol-sdk/pumpswap/index.js.map +1 -1
  111. package/dist/src/sol-sdk/pumpswap/instructions/buy.d.ts +8 -8
  112. package/dist/src/sol-sdk/pumpswap/instructions/buy.js +19 -19
  113. package/dist/src/sol-sdk/pumpswap/instructions/buy.js.map +1 -1
  114. package/dist/src/sol-sdk/pumpswap/instructions/migrate.js +2 -2
  115. package/dist/src/sol-sdk/pumpswap/instructions/migrate.js.map +1 -1
  116. package/dist/src/sol-sdk/pumpswap/instructions/sell.js +4 -4
  117. package/dist/src/sol-sdk/pumpswap/instructions/sell.js.map +1 -1
  118. package/dist/src/sol-sdk/pumpswap/rpc/index.js +1 -1
  119. package/dist/src/sol-sdk/pumpswap/rpc/index.js.map +1 -1
  120. package/dist/src/sol-sdk/raydium/instructions/cpmmSell.js +3 -3
  121. package/dist/src/sol-sdk/raydium/instructions/cpmmSell.js.map +1 -1
  122. package/dist/src/sol-sdk/raydium/instructions/sell.d.ts +40 -8520
  123. package/dist/src/sol-sdk/raydium/instructions/sell.d.ts.map +1 -1
  124. package/dist/src/sol-sdk/raydium/instructions/sell.js +6 -6
  125. package/dist/src/sol-sdk/raydium/instructions/sell.js.map +1 -1
  126. package/dist/src/sol-sdk/raydium/rpc/index.d.ts +4 -4
  127. package/dist/src/sol-sdk/rpc/index.d.ts +14 -14
  128. package/dist/src/sol-sdk/rpc/index.d.ts.map +1 -1
  129. package/dist/src/sol-sdk/rpc/index.js +17 -17
  130. package/dist/src/sol-sdk/rpc/index.js.map +1 -1
  131. package/dist/src/sol-sdk/transfer/index.js +5 -5
  132. package/dist/src/sol-sdk/transfer/index.js.map +1 -1
  133. package/dist/src/sol-sdk/turnover/index.d.ts +3 -3
  134. package/dist/src/sol-sdk/turnover/index.js +56 -56
  135. package/dist/src/sol-sdk/turnover/index.js.map +1 -1
  136. package/dist/src/telemetry.d.ts +8 -8
  137. package/dist/src/telemetry.d.ts.map +1 -1
  138. package/dist/src/telemetry.js +28 -27
  139. package/dist/src/telemetry.js.map +1 -1
  140. package/dist/src/tx-tracker/detail-adapter.d.ts +53 -53
  141. package/dist/src/tx-tracker/detail-adapter.d.ts.map +1 -1
  142. package/dist/src/tx-tracker/detail-adapter.js +68 -68
  143. package/dist/src/tx-tracker/detail-adapter.js.map +1 -1
  144. package/dist/src/tx-tracker/index.d.ts +67 -67
  145. package/dist/src/tx-tracker/index.d.ts.map +1 -1
  146. package/dist/src/tx-tracker/index.js +103 -103
  147. package/dist/src/tx-tracker/index.js.map +1 -1
  148. package/dist/src/types/index.d.ts +10 -10
  149. package/dist/src/types/index.d.ts.map +1 -1
  150. package/dist/src/types/websocket.js +1 -1
  151. package/dist/src/types/websocket.js.map +1 -1
  152. package/dist/src/utils/index.js +20 -20
  153. package/dist/src/utils/index.js.map +1 -1
  154. package/dist/src/wallet-store.d.ts +51 -51
  155. package/dist/src/wallet-store.d.ts.map +1 -1
  156. package/dist/src/wallet-store.js +104 -104
  157. package/dist/src/wallet-store.js.map +1 -1
  158. package/package.json +1 -1
@@ -1,24 +1,24 @@
1
1
  /**
2
- * ForgeX CLI DataSource -- 统一数据源门面
2
+ * ForgeX CLI DataSource -- Unified Data Source Facade
3
3
  *
4
- * 命令层唯一的数据访问接口。将所有数据适配器(CodexAdapterRpcAdapter
5
- * JitoAdapterDataStore)统一封装,提供简洁的接口供命令层调用。
4
+ * Single data access interface for the command layer. Wraps all data adapters (CodexAdapter, RpcAdapter,
5
+ * JitoAdapter, DataStore) into a unified facade with simple interfaces for command use.
6
6
  *
7
- * 路由逻辑:
8
- * 代币信息 / 价格 / K线 / 池信息 --> CodexAdapter (远程, 缓存穿透到 DataStore)
9
- * 余额 / 账户信息 / 交易确认 --> RpcAdapter (链上)
10
- * Bundle 发送 / 状态查询 --> JitoAdapter (Jito Block Engine)
11
- * 交易记录 / 持仓 / 钱包组数据 --> DataStore (本地文件)
7
+ * Routing logic:
8
+ * Token info / price / candlestick / pool info --> CodexAdapter (remote, cache-through to DataStore)
9
+ * Balance / account info / tx confirmation --> RpcAdapter (on-chain)
10
+ * Bundle send / status query --> JitoAdapter (Jito Block Engine)
11
+ * Trade records / positions / wallet group data --> DataStore (local files)
12
12
  *
13
- * 缓存穿透:
14
- * 优先读 DataStore 本地缓存。如果 miss 或过期,则从远程 (Codex/RPC) 获取
15
- * 最新数据,写入 DataStore 后返回。
13
+ * Cache-through:
14
+ * Reads DataStore local cache first. On miss or expiry, fetches from remote (Codex/RPC),
15
+ * writes to DataStore, then returns.
16
16
  *
17
- * 容错:
18
- * Codex API 不可用时,fallback DataStore 中的历史缓存。
19
- * RPC/Jito 不可用时,抛出 DataSourceError 供命令层处理。
17
+ * Fault tolerance:
18
+ * When Codex API is unavailable, falls back to historical cache in DataStore.
19
+ * When RPC/Jito unavailable, throws DataSourceError for command layer to handle.
20
20
  *
21
- * 设计参考: ARCH-DESIGN-v2.md Section 2.7
21
+ * Design reference: ARCH-DESIGN-v2.md Section 2.7
22
22
  */
23
23
  import { getCodexAdapter } from './adapters/codex-adapter.js';
24
24
  import { getRpcAdapter } from './adapters/rpc-adapter.js';
@@ -26,14 +26,14 @@ import { getJitoAdapter } from './adapters/jito-adapter.js';
26
26
  import { getDataStore } from './data-store/index.js';
27
27
  import { getTxTracker } from './tx-tracker/index.js';
28
28
  // ============================================================
29
- // 统一错误类型
29
+ // Unified Error Type
30
30
  // ============================================================
31
31
  export class DataSourceError extends Error {
32
- /** 错误来源 */
32
+ /** Error source */
33
33
  source;
34
- /** 是否已 fallback 到缓存 */
34
+ /** Whether fallback to cache was used */
35
35
  fellBackToCache;
36
- /** 原始错误 */
36
+ /** Original error */
37
37
  cause;
38
38
  constructor(message, source, options) {
39
39
  super(message);
@@ -44,16 +44,16 @@ export class DataSourceError extends Error {
44
44
  }
45
45
  }
46
46
  // ============================================================
47
- // 缓存过期阈值 (ms)
47
+ // Cache expiry thresholds (ms)
48
48
  // ============================================================
49
- /** 代币信息缓存有效期: 10 分钟 */
49
+ /** Token info cache TTL: 10 minutes */
50
50
  const TOKEN_INFO_TTL_MS = 10 * 60 * 1000;
51
- /** 池信息缓存有效期: 2 分钟 */
51
+ /** Pool info cache TTL: 2 minutes */
52
52
  const POOL_INFO_TTL_MS = 2 * 60 * 1000;
53
- /** SOL 价格缓存有效期: 1 分钟 */
53
+ /** SOL price cache TTL: 1 minute */
54
54
  const SOL_PRICE_TTL_MS = 60 * 1000;
55
55
  // ============================================================
56
- // DataSource 实现
56
+ // DataSource Implementation
57
57
  // ============================================================
58
58
  export class DataSource {
59
59
  codex;
@@ -69,24 +69,24 @@ export class DataSource {
69
69
  this.tracker = options?.tracker ?? getTxTracker();
70
70
  }
71
71
  // ============================================================
72
- // 代币信息 -- CodexAdapter + DataStore 缓存穿透
72
+ // Token Info -- CodexAdapter + DataStore cache-through
73
73
  // ============================================================
74
74
  /**
75
- * 获取代币基本信息。
75
+ * Get basic token info.
76
76
  *
77
- * 流程:
78
- * 1. 先查 DataStore 缓存
79
- * 2. 缓存命中且未过期 -> 直接返回
80
- * 3. 缓存 miss 或过期 -> Codex 获取并写入 DataStore
81
- * 4. Codex 不可用 -> fallback DataStore 陈旧缓存 (如有)
77
+ * Flow:
78
+ * 1. Check DataStore cache first
79
+ * 2. Cache hit and not expired -> return directly
80
+ * 3. Cache miss or expired -> fetch from Codex and write to DataStore
81
+ * 4. Codex unavailable -> fallback to stale DataStore cache (if any)
82
82
  */
83
83
  async getTokenInfo(ca) {
84
- // 1. 查本地缓存
84
+ // 1. Check local cache
85
85
  const cached = this.store.getTokenInfo(ca);
86
86
  if (cached && !this.isExpired(cached.updatedAt, TOKEN_INFO_TTL_MS)) {
87
87
  return cached;
88
88
  }
89
- // 2. Codex 获取
89
+ // 2. Fetch from Codex
90
90
  try {
91
91
  const marketData = await this.codex.getTokenMarketData(ca);
92
92
  const topPair = await this.codex.getTopPair(ca).catch(() => null);
@@ -100,37 +100,37 @@ export class DataSource {
100
100
  pairAddress: marketData.topPairAddress || topPair?.pairAddress || '',
101
101
  updatedAt: Date.now(),
102
102
  };
103
- // 写入 DataStore
103
+ // Write to DataStore
104
104
  await this.store.saveTokenInfo(ca, tokenInfo);
105
105
  return tokenInfo;
106
106
  }
107
107
  catch (err) {
108
- // 3. Codex 不可用, fallback 到陈旧缓存
108
+ // 3. Codex unavailable, fallback to stale cache
109
109
  if (cached) {
110
110
  return cached;
111
111
  }
112
- throw new DataSourceError(`获取代币信息失败 (${ca}): ${err.message}`, 'codex', { cause: err });
112
+ throw new DataSourceError(`Failed to get token info (${ca}): ${err.message}`, 'codex', { cause: err });
113
113
  }
114
114
  }
115
115
  /**
116
- * 获取代币详细市场数据 (包含价格、交易量、持有者等)
117
- * 直接从 Codex 获取, 不做本地缓存穿透 (市场数据实时性要求高)
116
+ * Get detailed token market data (including price, volume, holders, etc).
117
+ * Fetches directly from Codex without local cache-through (market data requires high timeliness).
118
118
  */
119
119
  async getTokenMarketData(ca) {
120
120
  try {
121
121
  return await this.codex.getTokenMarketData(ca);
122
122
  }
123
123
  catch (err) {
124
- throw new DataSourceError(`获取代币市场数据失败 (${ca}): ${err.message}`, 'codex', { cause: err });
124
+ throw new DataSourceError(`Failed to get token market data (${ca}): ${err.message}`, 'codex', { cause: err });
125
125
  }
126
126
  }
127
127
  // ============================================================
128
- // 价格 -- CodexAdapter + DataStore 缓存穿透
128
+ // Price -- CodexAdapter + DataStore cache-through
129
129
  // ============================================================
130
130
  /**
131
- * 获取代币价格 (SOL USD)
131
+ * Get token price (SOL and USD).
132
132
  *
133
- * 缓存穿透: 先查 DataStore pool-info 缓存的价格, 过期则从 Codex 获取。
133
+ * Cache-through: checks DataStore pool-info cached price first, fetches from Codex if expired.
134
134
  */
135
135
  async getTokenPrice(ca) {
136
136
  try {
@@ -138,57 +138,57 @@ export class DataSource {
138
138
  return result;
139
139
  }
140
140
  catch (err) {
141
- // fallback: DataStore pool-info 中读取历史价格
141
+ // fallback: read historical price from DataStore pool-info
142
142
  const poolInfo = this.store.getPoolInfo(ca);
143
143
  if (poolInfo) {
144
144
  return { priceSol: poolInfo.priceSol, priceUsd: poolInfo.priceUsd };
145
145
  }
146
- throw new DataSourceError(`获取代币价格失败 (${ca}): ${err.message}`, 'codex', { cause: err });
146
+ throw new DataSourceError(`Failed to get token price (${ca}): ${err.message}`, 'codex', { cause: err });
147
147
  }
148
148
  }
149
149
  /**
150
- * 获取 SOL 价格 (USD)
150
+ * Get SOL price (USD).
151
151
  *
152
- * 缓存穿透: 先查 DataStore, 过期则从 Codex 获取并更新。
152
+ * Cache-through: checks DataStore first, fetches from Codex and updates if expired.
153
153
  */
154
154
  async getSolPrice() {
155
- // 1. 查本地缓存
155
+ // 1. Check local cache
156
156
  const cachedPrice = this.store.getSolPrice();
157
157
  if (cachedPrice > 0) {
158
- // 检查缓存是否过期 -- getSolPrice 返回的是数字, 需要额外检查时间
159
- // DataStore 内部的 MemoryCache 30s TTL, 这里再加一层文件级 TTL
160
- // 由于 DataStore.getSolPrice() 已经有 MemoryCache, 这里信任它即可
161
- // 但如果明确需要刷新, 下面的 try 会尝试
158
+ // Check if cache is expired -- getSolPrice returns a number, needs extra time check
159
+ // DataStore internal MemoryCache has 30s TTL, adding another file-level TTL here
160
+ // Since DataStore.getSolPrice() already has MemoryCache, trust it here
161
+ // But if refresh is explicitly needed, the try below will attempt it
162
162
  }
163
- // 2. Codex 获取
163
+ // 2. Fetch from Codex
164
164
  try {
165
165
  const price = await this.codex.getSolPrice();
166
166
  await this.store.saveSolPrice(price);
167
167
  return price;
168
168
  }
169
169
  catch (err) {
170
- // fallback: 使用缓存
170
+ // fallback: use cache
171
171
  if (cachedPrice > 0) {
172
172
  return cachedPrice;
173
173
  }
174
- throw new DataSourceError(`获取 SOL 价格失败: ${err.message}`, 'codex', { fellBackToCache: false, cause: err });
174
+ throw new DataSourceError(`Failed to get SOL price: ${err.message}`, 'codex', { fellBackToCache: false, cause: err });
175
175
  }
176
176
  }
177
177
  // ============================================================
178
- // 池/流动性信息 -- CodexAdapter + DataStore 缓存穿透
178
+ // Pool/Liquidity Info -- CodexAdapter + DataStore cache-through
179
179
  // ============================================================
180
180
  /**
181
- * 获取流动性池信息。
181
+ * Get liquidity pool info.
182
182
  *
183
- * 缓存穿透: DataStore 有效 -> 返回; miss/过期 -> Codex 获取并写入。
183
+ * Cache-through: DataStore valid -> return; miss/expired -> fetch from Codex and write.
184
184
  */
185
185
  async getPoolInfo(ca) {
186
- // 1. 查本地缓存
186
+ // 1. Check local cache
187
187
  const cached = this.store.getPoolInfo(ca);
188
188
  if (cached && !this.isExpired(cached.updatedAt, POOL_INFO_TTL_MS)) {
189
189
  return cached;
190
190
  }
191
- // 2. Codex 获取
191
+ // 2. Fetch from Codex
192
192
  try {
193
193
  const codexPool = await this.codex.getPoolInfo(ca);
194
194
  const poolInfo = {
@@ -204,105 +204,105 @@ export class DataSource {
204
204
  return poolInfo;
205
205
  }
206
206
  catch (err) {
207
- // fallback 到陈旧缓存
207
+ // fallback to stale cache
208
208
  if (cached) {
209
209
  return cached;
210
210
  }
211
- throw new DataSourceError(`获取池信息失败 (${ca}): ${err.message}`, 'codex', { cause: err });
211
+ throw new DataSourceError(`Failed to get pool info (${ca}): ${err.message}`, 'codex', { cause: err });
212
212
  }
213
213
  }
214
214
  // ============================================================
215
- // K线数据 -- CodexAdapter (无本地缓存)
215
+ // Candlestick Data -- CodexAdapter (no local cache)
216
216
  // ============================================================
217
217
  /**
218
- * 获取 K线 (OHLCV) 数据。
219
- * K线数据量大且时效性强, 不做本地缓存。
218
+ * Get candlestick (OHLCV) data.
219
+ * Candlestick data is large and time-sensitive, no local caching.
220
220
  */
221
221
  async getKlineData(params) {
222
222
  try {
223
223
  return await this.codex.getBars(params);
224
224
  }
225
225
  catch (err) {
226
- throw new DataSourceError(`获取 K线数据失败: ${err.message}`, 'codex', { cause: err });
226
+ throw new DataSourceError(`Failed to get candlestick data: ${err.message}`, 'codex', { cause: err });
227
227
  }
228
228
  }
229
229
  /**
230
- * 获取代币的交易对列表。
230
+ * Get trading pair list for a token.
231
231
  */
232
232
  async getPairsForToken(ca, limit) {
233
233
  try {
234
234
  return await this.codex.getPairsForToken(ca, limit);
235
235
  }
236
236
  catch (err) {
237
- throw new DataSourceError(`获取交易对失败 (${ca}): ${err.message}`, 'codex', { cause: err });
237
+ throw new DataSourceError(`Failed to get trading pairs (${ca}): ${err.message}`, 'codex', { cause: err });
238
238
  }
239
239
  }
240
240
  // ============================================================
241
- // 余额查询 -- RpcAdapter (链上实时数据)
241
+ // Balance Queries -- RpcAdapter (on-chain real-time data)
242
242
  // ============================================================
243
243
  /**
244
- * 获取单个钱包的 SOL 余额。
244
+ * Get SOL balance for a single wallet.
245
245
  */
246
246
  async getSolBalance(address) {
247
247
  try {
248
248
  return await this.rpc.getSolBalance(address);
249
249
  }
250
250
  catch (err) {
251
- throw new DataSourceError(`获取 SOL 余额失败 (${address}): ${err.message}`, 'rpc', { cause: err });
251
+ throw new DataSourceError(`Failed to get SOL balance (${address}): ${err.message}`, 'rpc', { cause: err });
252
252
  }
253
253
  }
254
254
  /**
255
- * 批量获取多个钱包的 SOL 余额。
255
+ * Batch get SOL balances for multiple wallets.
256
256
  */
257
257
  async getBatchSolBalances(addresses) {
258
258
  try {
259
259
  return await this.rpc.getBatchSolBalances(addresses);
260
260
  }
261
261
  catch (err) {
262
- throw new DataSourceError(`批量获取 SOL 余额失败: ${err.message}`, 'rpc', { cause: err });
262
+ throw new DataSourceError(`Failed to batch get SOL balances: ${err.message}`, 'rpc', { cause: err });
263
263
  }
264
264
  }
265
265
  /**
266
- * 获取单个钱包的单个 Token 余额。
266
+ * Get single token balance for a wallet.
267
267
  */
268
268
  async getTokenBalance(walletAddress, tokenMint) {
269
269
  try {
270
270
  return await this.rpc.getTokenBalance(walletAddress, tokenMint);
271
271
  }
272
272
  catch (err) {
273
- throw new DataSourceError(`获取 Token 余额失败 (${walletAddress}): ${err.message}`, 'rpc', { cause: err });
273
+ throw new DataSourceError(`Failed to get token balance (${walletAddress}): ${err.message}`, 'rpc', { cause: err });
274
274
  }
275
275
  }
276
276
  /**
277
- * 批量获取多个钱包在指定代币上的余额。
277
+ * Batch get token balances for multiple wallets on a specific token.
278
278
  */
279
279
  async getBatchTokenBalances(walletAddresses, tokenMint) {
280
280
  try {
281
281
  return await this.rpc.getBatchTokenBalances(walletAddresses, tokenMint);
282
282
  }
283
283
  catch (err) {
284
- throw new DataSourceError(`批量获取 Token 余额失败: ${err.message}`, 'rpc', { cause: err });
284
+ throw new DataSourceError(`Failed to batch get token balances: ${err.message}`, 'rpc', { cause: err });
285
285
  }
286
286
  }
287
287
  /**
288
- * 获取单个钱包的所有 Token 账户。
288
+ * Get all token accounts for a single wallet.
289
289
  */
290
290
  async getTokenAccountsByOwner(walletAddress) {
291
291
  try {
292
292
  return await this.rpc.getTokenAccountsByOwner(walletAddress);
293
293
  }
294
294
  catch (err) {
295
- throw new DataSourceError(`获取 Token 账户列表失败 (${walletAddress}): ${err.message}`, 'rpc', { cause: err });
295
+ throw new DataSourceError(`Failed to get token account list (${walletAddress}): ${err.message}`, 'rpc', { cause: err });
296
296
  }
297
297
  }
298
298
  /**
299
- * 获取钱包组在指定代币上的完整余额数据。
299
+ * Get complete balance data for wallet group on a specific token.
300
300
  *
301
- * RPC 实时获取并更新 DataStore, 然后返回 BalancesFile
301
+ * Fetches from RPC in real-time, updates DataStore, then returns BalancesFile.
302
302
  */
303
303
  async getWalletBalances(walletAddresses, ca, groupId) {
304
304
  try {
305
- // 并行获取 SOL Token 余额
305
+ // Fetch SOL and Token balances in parallel
306
306
  const [solBalances, tokenBalances] = await Promise.all([
307
307
  this.rpc.getBatchSolBalances(walletAddresses),
308
308
  this.rpc.getBatchTokenBalances(walletAddresses, ca),
@@ -314,7 +314,7 @@ export class DataSource {
314
314
  tokenBalance: tokenBalances[addr] ?? 0,
315
315
  updatedAt: now,
316
316
  }));
317
- // 批量写入 DataStore
317
+ // Batch write to DataStore
318
318
  await this.store.updateBalancesBatch(ca, groupId, balances);
319
319
  return {
320
320
  ca,
@@ -324,240 +324,240 @@ export class DataSource {
324
324
  };
325
325
  }
326
326
  catch (err) {
327
- // fallback: 返回 DataStore 中的历史数据
327
+ // fallback: return historical data from DataStore
328
328
  const cached = this.store.getBalances(ca, groupId);
329
329
  if (cached) {
330
330
  return cached;
331
331
  }
332
- throw new DataSourceError(`获取钱包余额失败: ${err.message}`, 'rpc', { cause: err });
332
+ throw new DataSourceError(`Failed to get wallet balances: ${err.message}`, 'rpc', { cause: err });
333
333
  }
334
334
  }
335
335
  // ============================================================
336
- // 交易状态 -- RpcAdapter
336
+ // Transaction Status -- RpcAdapter
337
337
  // ============================================================
338
338
  /**
339
- * 查询单笔交易的确认状态。
339
+ * Query confirmation status of a single transaction.
340
340
  */
341
341
  async getTransactionStatus(txHash) {
342
342
  try {
343
343
  return await this.rpc.getTransactionStatus(txHash);
344
344
  }
345
345
  catch (err) {
346
- throw new DataSourceError(`获取交易状态失败 (${txHash}): ${err.message}`, 'rpc', { cause: err });
346
+ throw new DataSourceError(`Failed to get transaction status (${txHash}): ${err.message}`, 'rpc', { cause: err });
347
347
  }
348
348
  }
349
349
  /**
350
- * 获取交易详情。
350
+ * Get transaction details.
351
351
  */
352
352
  async getTransactionDetail(txHash) {
353
353
  try {
354
354
  return await this.rpc.getTransactionDetail(txHash);
355
355
  }
356
356
  catch (err) {
357
- throw new DataSourceError(`获取交易详情失败 (${txHash}): ${err.message}`, 'rpc', { cause: err });
357
+ throw new DataSourceError(`Failed to get transaction details (${txHash}): ${err.message}`, 'rpc', { cause: err });
358
358
  }
359
359
  }
360
360
  /**
361
- * 批量查询交易状态。
361
+ * Batch query transaction statuses.
362
362
  */
363
363
  async getBatchTransactionStatuses(txHashes) {
364
364
  try {
365
365
  return await this.rpc.getBatchTransactionStatuses(txHashes);
366
366
  }
367
367
  catch (err) {
368
- throw new DataSourceError(`批量获取交易状态失败: ${err.message}`, 'rpc', { cause: err });
368
+ throw new DataSourceError(`Failed to batch get transaction statuses: ${err.message}`, 'rpc', { cause: err });
369
369
  }
370
370
  }
371
371
  // ============================================================
372
- // Bundle 操作 -- JitoAdapter
372
+ // Bundle Operations -- JitoAdapter
373
373
  // ============================================================
374
374
  /**
375
- * 发送 Bundle Jito Block Engine
375
+ * Send bundle to Jito Block Engine.
376
376
  */
377
377
  async sendBundle(base64Txs) {
378
378
  try {
379
379
  return await this.jito.sendBundle(base64Txs);
380
380
  }
381
381
  catch (err) {
382
- throw new DataSourceError(`发送 Bundle 失败: ${err.message}`, 'jito', { cause: err });
382
+ throw new DataSourceError(`Failed to send bundle: ${err.message}`, 'jito', { cause: err });
383
383
  }
384
384
  }
385
385
  /**
386
- * 查询 Bundle 状态。
386
+ * Query bundle status.
387
387
  */
388
388
  async getBundleStatus(bundleId) {
389
389
  try {
390
390
  return await this.jito.getBundleStatus(bundleId);
391
391
  }
392
392
  catch (err) {
393
- throw new DataSourceError(`获取 Bundle 状态失败 (${bundleId}): ${err.message}`, 'jito', { cause: err });
393
+ throw new DataSourceError(`Failed to get bundle status (${bundleId}): ${err.message}`, 'jito', { cause: err });
394
394
  }
395
395
  }
396
396
  /**
397
- * 等待 Bundle 确认。
397
+ * Wait for bundle confirmation.
398
398
  */
399
399
  async waitForBundleConfirmation(bundleId, options) {
400
400
  try {
401
401
  return await this.jito.waitForBundleConfirmation(bundleId, options);
402
402
  }
403
403
  catch (err) {
404
- throw new DataSourceError(`等待 Bundle 确认失败 (${bundleId}): ${err.message}`, 'jito', { cause: err });
404
+ throw new DataSourceError(`Failed waiting for bundle confirmation (${bundleId}): ${err.message}`, 'jito', { cause: err });
405
405
  }
406
406
  }
407
407
  // ============================================================
408
- // 单笔交易发送 -- JitoAdapter (sendTransaction)
408
+ // Single Transaction Sending -- JitoAdapter (sendTransaction)
409
409
  // ============================================================
410
410
  /**
411
- * 通过 Jito 发送单笔交易。
411
+ * Send single transaction via Jito.
412
412
  */
413
413
  async sendTransaction(base64Tx) {
414
414
  try {
415
415
  return await this.jito.sendTransaction(base64Tx);
416
416
  }
417
417
  catch (err) {
418
- throw new DataSourceError(`发送交易失败: ${err.message}`, 'jito', { cause: err });
418
+ throw new DataSourceError(`Failed to send transaction: ${err.message}`, 'jito', { cause: err });
419
419
  }
420
420
  }
421
421
  /**
422
- * 通过 RPC 确认交易状态。
422
+ * Confirm transaction status via RPC.
423
423
  */
424
424
  async confirmTransactionByRpc(connection, signature, timeoutMs) {
425
425
  try {
426
426
  return await this.jito.confirmTransactionByRpc(connection, signature, timeoutMs);
427
427
  }
428
428
  catch (err) {
429
- throw new DataSourceError(`确认交易失败 (${signature}): ${err.message}`, 'rpc', { cause: err });
429
+ throw new DataSourceError(`Failed to confirm transaction (${signature}): ${err.message}`, 'rpc', { cause: err });
430
430
  }
431
431
  }
432
432
  // ============================================================
433
- // 交易记录 -- DataStore (本地文件)
433
+ // Trade Records -- DataStore (local files)
434
434
  // ============================================================
435
435
  /**
436
- * 获取交易记录。
436
+ * Get trade records.
437
437
  */
438
438
  getTransactions(ca, groupId) {
439
439
  return this.store.getTransactions(ca, groupId);
440
440
  }
441
441
  /**
442
- * 获取指定钱包的交易记录。
442
+ * Get trade records for a specific wallet.
443
443
  */
444
444
  getTransactionsByWallet(ca, groupId, wallet) {
445
445
  return this.store.getTransactionsByWallet(ca, groupId, wallet);
446
446
  }
447
447
  /**
448
- * 追加交易记录。
448
+ * Append trade records.
449
449
  */
450
450
  async appendTransaction(ca, groupId, tx) {
451
451
  try {
452
452
  await this.store.appendTransaction(ca, groupId, tx);
453
453
  }
454
454
  catch (err) {
455
- throw new DataSourceError(`写入交易记录失败: ${err.message}`, 'store', { cause: err });
455
+ throw new DataSourceError(`Failed to write trade records: ${err.message}`, 'store', { cause: err });
456
456
  }
457
457
  }
458
458
  // ============================================================
459
- // 持仓数据 -- DataStore (本地文件)
459
+ // Position Data -- DataStore (local files)
460
460
  // ============================================================
461
461
  /**
462
- * 获取持仓数据。
462
+ * Get position data.
463
463
  */
464
464
  getHoldings(ca, groupId) {
465
465
  return this.store.getHoldings(ca, groupId);
466
466
  }
467
467
  /**
468
- * 更新持仓数据。
468
+ * Update position data.
469
469
  */
470
470
  async updateHolding(ca, groupId, wallet, update) {
471
471
  try {
472
472
  await this.store.updateHolding(ca, groupId, wallet, update);
473
473
  }
474
474
  catch (err) {
475
- throw new DataSourceError(`更新持仓失败: ${err.message}`, 'store', { cause: err });
475
+ throw new DataSourceError(`Failed to update positions: ${err.message}`, 'store', { cause: err });
476
476
  }
477
477
  }
478
478
  // ============================================================
479
- // 余额快照 -- DataStore (本地文件)
479
+ // Balance Snapshots -- DataStore (local files)
480
480
  // ============================================================
481
481
  /**
482
- * 获取本地缓存的余额快照。
482
+ * Get locally cached balance snapshot.
483
483
  */
484
484
  getBalancesSnapshot(ca, groupId) {
485
485
  return this.store.getBalances(ca, groupId);
486
486
  }
487
487
  /**
488
- * 更新余额快照。
488
+ * Update balance snapshot.
489
489
  */
490
490
  async updateBalance(ca, groupId, wallet, balance) {
491
491
  try {
492
492
  await this.store.updateBalance(ca, groupId, wallet, balance);
493
493
  }
494
494
  catch (err) {
495
- throw new DataSourceError(`更新余额快照失败: ${err.message}`, 'store', { cause: err });
495
+ throw new DataSourceError(`Failed to update balance snapshot: ${err.message}`, 'store', { cause: err });
496
496
  }
497
497
  }
498
498
  // ============================================================
499
- // 全局数据 -- DataStore
499
+ // Global Data -- DataStore
500
500
  // ============================================================
501
501
  /**
502
- * 获取手续费配置。
502
+ * Get fee configuration.
503
503
  */
504
504
  getFeeConfig() {
505
505
  return this.store.getFeeConfig();
506
506
  }
507
507
  /**
508
- * 保存手续费配置。
508
+ * Save fee configuration.
509
509
  */
510
510
  async saveFeeConfig(config) {
511
511
  try {
512
512
  await this.store.saveFeeConfig(config);
513
513
  }
514
514
  catch (err) {
515
- throw new DataSourceError(`保存手续费配置失败: ${err.message}`, 'store', { cause: err });
515
+ throw new DataSourceError(`Failed to save fee configuration: ${err.message}`, 'store', { cause: err });
516
516
  }
517
517
  }
518
518
  // ============================================================
519
- // DataStore 工具方法
519
+ // DataStore Utility Methods
520
520
  // ============================================================
521
521
  /**
522
- * 列出所有有数据的代币 CA。
522
+ * List all token CAs with data.
523
523
  */
524
524
  listTokens() {
525
525
  return this.store.listTokens();
526
526
  }
527
527
  /**
528
- * 列出某个代币下所有有数据的钱包组 ID。
528
+ * List all wallet group IDs with data for a token.
529
529
  */
530
530
  listGroups(ca) {
531
531
  return this.store.listGroups(ca);
532
532
  }
533
533
  // ============================================================
534
- // 交易追踪 -- TxTracker
534
+ // Transaction Tracking -- TxTracker
535
535
  // ============================================================
536
536
  /**
537
- * 追踪单笔交易。
538
- * 轮询确认后自动写入 DataStore (交易记录 + 持仓 + 余额)
537
+ * Track a single transaction.
538
+ * Auto-writes to DataStore after polling confirmation (trade records + positions + balances).
539
539
  */
540
540
  async trackTransaction(txHash, context, options) {
541
541
  return this.tracker.trackTransaction(txHash, context, options);
542
542
  }
543
543
  /**
544
- * 追踪 Jito Bundle
545
- * Bundle 确认后逐个处理内部交易并写入 DataStore
544
+ * Track a Jito Bundle.
545
+ * Processes internal transactions individually after bundle confirmation and writes to DataStore.
546
546
  */
547
547
  async trackBundle(bundleId, txHashes, context, options) {
548
548
  return this.tracker.trackBundle(bundleId, txHashes, context, options);
549
549
  }
550
550
  /**
551
- * 批量追踪多笔独立交易。
551
+ * Batch track multiple independent transactions.
552
552
  */
553
553
  async trackBatch(entries, options) {
554
554
  return this.tracker.trackBatch(entries, options);
555
555
  }
556
556
  // ============================================================
557
- // 健康检查
557
+ // Health Check
558
558
  // ============================================================
559
559
  /**
560
- * 检查所有数据源的健康状态。
560
+ * Check health status of all data sources.
561
561
  */
562
562
  async healthCheck() {
563
563
  const [codexResult, rpcResult, jitoResult] = await Promise.all([
@@ -572,43 +572,43 @@ export class DataSource {
572
572
  };
573
573
  }
574
574
  // ============================================================
575
- // 底层适配器直接访问 (高级用途)
575
+ // Direct adapter access (advanced use)
576
576
  // ============================================================
577
- /** 获取底层 CodexAdapter (仅当 DataSource 接口不够用时使用) */
577
+ /** Get underlying CodexAdapter (only when DataSource interface is insufficient) */
578
578
  getCodexAdapter() {
579
579
  return this.codex;
580
580
  }
581
- /** 获取底层 RpcAdapter */
581
+ /** Get underlying RpcAdapter */
582
582
  getRpcAdapter() {
583
583
  return this.rpc;
584
584
  }
585
- /** 获取底层 JitoAdapter */
585
+ /** Get underlying JitoAdapter */
586
586
  getJitoAdapter() {
587
587
  return this.jito;
588
588
  }
589
- /** 获取底层 DataStore */
589
+ /** Get underlying DataStore */
590
590
  getDataStore() {
591
591
  return this.store;
592
592
  }
593
- /** 获取底层 TxTracker */
593
+ /** Get underlying TxTracker */
594
594
  getTxTracker() {
595
595
  return this.tracker;
596
596
  }
597
597
  // ============================================================
598
- // 内部工具方法
598
+ // Internal utility methods
599
599
  // ============================================================
600
600
  /**
601
- * 检查时间戳是否已过期。
602
- * @param updatedAt 上次更新时间 (ms)
603
- * @param ttlMs 有效期 (ms)
604
- * @returns true 表示已过期
601
+ * Check if timestamp has expired.
602
+ * @param updatedAt Last update time (ms)
603
+ * @param ttlMs Time-to-live (ms)
604
+ * @returns true if expired
605
605
  */
606
606
  isExpired(updatedAt, ttlMs) {
607
607
  return Date.now() - updatedAt > ttlMs;
608
608
  }
609
609
  /**
610
- * 根据 DEX/交易所名称推断 DEX 类型。
611
- * Codex API 返回的 exchangeName 映射到 TokenInfoFile.dex 枚举。
610
+ * Infer DEX type from DEX/exchange name.
611
+ * Maps Codex API exchangeName to TokenInfoFile.dex enum.
612
612
  */
613
613
  inferDex(exchangeName) {
614
614
  if (!exchangeName)
@@ -624,17 +624,17 @@ export class DataSource {
624
624
  return 'launchlab';
625
625
  if (name.includes('meteora'))
626
626
  return 'meteora';
627
- // 无法识别时默认 pump
627
+ // Default to pump when unrecognized
628
628
  return 'pump';
629
629
  }
630
630
  }
631
631
  // ============================================================
632
- // 单例管理
632
+ // Singleton Management
633
633
  // ============================================================
634
634
  let _instance = null;
635
635
  /**
636
- * 获取 DataSource 全局单例。
637
- * 命令层的标准入口:
636
+ * Get DataSource global singleton.
637
+ * Standard entry point for command layer:
638
638
  * import { getDataSource } from '../data-source.js';
639
639
  * const ds = getDataSource();
640
640
  */
@@ -645,7 +645,7 @@ export function getDataSource() {
645
645
  return _instance;
646
646
  }
647
647
  /**
648
- * 重置单例 (用于测试或配置变更后重新初始化)
648
+ * Reset singleton (for testing or re-initialization after config changes).
649
649
  */
650
650
  export function resetDataSource() {
651
651
  _instance = null;